Snapshot. Includes first cut at output relocation sections.

This commit is contained in:
Ian Lance Taylor 2006-11-16 00:38:25 +00:00
parent 7495b3afc0
commit c06b7b0ba3
17 changed files with 885 additions and 179 deletions

View file

@ -1163,7 +1163,7 @@ class Sym_write
internal::Sym_data<size>* p_;
};
// Accessor classes for Elf relocation table entries.
// Accessor classes for an ELF REL relocation entry.
template<int size, bool big_endian>
class Rel
@ -1191,6 +1191,30 @@ class Rel
const internal::Rel_data<size>* p_;
};
// Writer class for an ELF Rel relocation.
template<int size, bool big_endian>
class Rel_write
{
public:
Rel_write(unsigned char* p)
: p_(reinterpret_cast<internal::Rel_data<size>*>(p))
{ }
void
put_r_offset(typename Elf_types<size>::Elf_Addr v)
{ this->p_->r_offset = Convert<size, big_endian>::convert_host(v); }
void
put_r_info(typename Elf_types<size>::Elf_WXword v)
{ this->p_->r_info = Convert<size, big_endian>::convert_host(v); }
private:
internal::Rel_data<size>* p_;
};
// Accessor class for an ELF Rela relocation.
template<int size, bool big_endian>
class Rela
{
@ -1221,6 +1245,32 @@ class Rela
const internal::Rela_data<size>* p_;
};
// Writer class for an ELF Rela relocation.
template<int size, bool big_endian>
class Rela_write
{
public:
Rela_write(unsigned char* p)
: p_(reinterpret_cast<internal::Rela_data<size>*>(p))
{ }
void
put_r_offset(typename Elf_types<size>::Elf_Addr v)
{ this->p_->r_offset = Convert<size, big_endian>::convert_host(v); }
void
put_r_info(typename Elf_types<size>::Elf_WXword v)
{ this->p_->r_info = Convert<size, big_endian>::convert_host(v); }
void
put_r_addend(typename Elf_types<size>::Elf_Swxword v)
{ this->p_->r_addend = Convert<size, big_endian>::convert_host(v); }
private:
internal::Rela_data<size>* p_;
};
// Accessor classes for entries in the ELF SHT_DYNAMIC section aka
// PT_DYNAMIC segment.

View file

@ -56,7 +56,9 @@ HFILES = \
output.h \
readsyms.h \
reloc.h \
reloc-types.h \
script.h \
script-c.h \
stringpool.h \
symtab.h \
target.h \

View file

@ -272,7 +272,9 @@ HFILES = \
output.h \
readsyms.h \
reloc.h \
reloc-types.h \
script.h \
script-c.h \
stringpool.h \
symtab.h \
target.h \

View file

@ -96,7 +96,7 @@ class Target_i386 : public Sized_target<32, false>
inline bool
relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum,
const elfcpp::Rel<32, false>&,
unsigned int r_type, Sized_symbol<32>*,
unsigned int r_type, const Sized_symbol<32>*,
elfcpp::Elf_types<32>::Elf_Addr,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
off_t);
@ -106,7 +106,7 @@ class Target_i386 : public Sized_target<32, false>
inline void
relocate_tls(const Relocate_info<32, false>*, size_t relnum,
const elfcpp::Rel<32, false>&,
unsigned int r_type, Sized_symbol<32>*,
unsigned int r_type, const Sized_symbol<32>*,
elfcpp::Elf_types<32>::Elf_Addr,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, off_t);
@ -529,7 +529,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
size_t relnum,
const elfcpp::Rel<32, false>& rel,
unsigned int r_type,
Sized_symbol<32>* gsym,
const Sized_symbol<32>* gsym,
elfcpp::Elf_types<32>::Elf_Addr value,
unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr address,
@ -670,7 +670,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
size_t relnum,
const elfcpp::Rel<32, false>& rel,
unsigned int r_type,
Sized_symbol<32>* gsym,
const Sized_symbol<32>* gsym,
elfcpp::Elf_types<32>::Elf_Addr value,
unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr,

View file

@ -676,19 +676,24 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
// Save space for the dummy symbol at the start of the section. We
// never bother to write this out--it will just be left as zero.
off += symsize;
unsigned int local_symbol_index = 1;
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
++p)
{
Task_lock_obj<Object> tlo(**p);
off = (*p)->finalize_local_symbols(off, &this->sympool_);
unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
off,
&this->sympool_);
off += (index - local_symbol_index) * symsize;
local_symbol_index = index;
}
unsigned int local_symcount = (off - startoff) / symsize;
unsigned int local_symcount = local_symbol_index;
assert(local_symcount * symsize == off - startoff);
off = symtab->finalize(off, &this->sympool_);
off = symtab->finalize(local_symcount, off, &this->sympool_);
this->sympool_.set_string_offsets();

View file

@ -128,7 +128,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
output_local_symbol_count_(0),
symbols_(NULL),
local_symbol_offset_(0),
values_(NULL)
local_values_(),
local_indexes_()
{
}
@ -505,23 +506,25 @@ Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
// Finalize the local symbols. Here we record the file offset at
// which they should be output, we add their names to *POOL, and we
// add their values to THIS->VALUES_. Return the new file offset.
// This function is always called from the main thread. The actual
// output of the local symbols will occur in a separate task.
// add their values to THIS->LOCAL_VALUES_ and their indexes in the
// output symbol table to THIS->LOCAL_INDEXES_. Return the symbol
// index. This function is always called from the main thread. The
// actual output of the local symbols will occur in a separate task.
template<int size, bool big_endian>
off_t
Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
unsigned int
Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
off_t off,
Stringpool* pool)
{
assert(this->symtab_shndx_ != -1U);
if (this->symtab_shndx_ == 0)
{
// This object has no symbols. Weird but legal.
return off;
return index;
}
off = align_address(off, size >> 3);
assert(off == static_cast<off_t>(align_address(off, size >> 3)));
this->local_symbol_offset_ = off;
@ -539,7 +542,8 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
locsize);
this->values_ = new typename elfcpp::Elf_types<size>::Elf_Addr[loccount];
this->local_values_.resize(loccount);
this->local_indexes_.resize(loccount);
// Read the symbol names.
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
@ -550,7 +554,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
// Loop over the local symbols.
std::vector<Map_to_output>& mo(this->map_to_output());
const std::vector<Map_to_output>& mo(this->map_to_output());
unsigned int shnum = this->shnum();
unsigned int count = 0;
// Skip the first, dummy, symbol.
@ -564,7 +568,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
if (shndx >= elfcpp::SHN_LORESERVE)
{
if (shndx == elfcpp::SHN_ABS)
this->values_[i] = sym.get_st_value();
this->local_values_[i] = sym.get_st_value();
else
{
// FIXME: Handle SHN_XINDEX.
@ -588,37 +592,46 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
if (mo[shndx].output_section == NULL)
{
this->values_[i] = 0;
this->local_values_[i] = 0;
this->local_indexes_[i] = -1U;
continue;
}
this->values_[i] = (mo[shndx].output_section->address()
+ mo[shndx].offset
+ sym.get_st_value());
this->local_values_[i] = (mo[shndx].output_section->address()
+ mo[shndx].offset
+ sym.get_st_value());
}
if (sym.get_st_type() != elfcpp::STT_SECTION)
// Decide whether this symbol should go into the output file.
if (sym.get_st_type() == elfcpp::STT_SECTION)
{
if (sym.get_st_name() >= strtab_size)
{
fprintf(stderr,
_("%s: %s: local symbol %u section name "
"out of range: %u >= %u\n"),
program_name, this->name().c_str(),
i, sym.get_st_name(),
static_cast<unsigned int>(strtab_size));
gold_exit(false);
}
pool->add(pnames + sym.get_st_name(), NULL);
off += sym_size;
++count;
this->local_indexes_[i] = -1U;
continue;
}
if (sym.get_st_name() >= strtab_size)
{
fprintf(stderr,
_("%s: %s: local symbol %u section name "
"out of range: %u >= %u\n"),
program_name, this->name().c_str(),
i, sym.get_st_name(),
static_cast<unsigned int>(strtab_size));
gold_exit(false);
}
const char* name = pnames + sym.get_st_name();
pool->add(name, NULL);
this->local_indexes_[i] = index;
++index;
off += sym_size;
++count;
}
this->output_local_symbol_count_ = count;
return off;
return index;
}
// Write out the local symbols.
@ -661,16 +674,20 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
unsigned char* oview = of->get_output_view(this->local_symbol_offset_,
output_size);
std::vector<Map_to_output>& mo(this->map_to_output());
const std::vector<Map_to_output>& mo(this->map_to_output());
assert(this->local_values_.size() == loccount);
assert(this->local_indexes_.size() == loccount);
psyms += sym_size;
unsigned char* ov = oview;
psyms += sym_size;
for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
{
elfcpp::Sym<size, big_endian> isym(psyms);
if (isym.get_st_type() == elfcpp::STT_SECTION)
if (this->local_indexes_[i] == -1U)
continue;
assert(this->local_indexes_[i] != 0);
unsigned int st_shndx = isym.get_st_shndx();
if (st_shndx < elfcpp::SHN_LORESERVE)
@ -684,8 +701,9 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
elfcpp::Sym_write<size, big_endian> osym(ov);
assert(isym.get_st_name() < strtab_size);
osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name()));
osym.put_st_value(this->values_[i]);
const char* name = pnames + isym.get_st_name();
osym.put_st_name(sympool->get_offset(name));
osym.put_st_value(this->local_values_[i]);
osym.put_st_size(isym.get_st_size());
osym.put_st_info(isym.get_st_info());
osym.put_st_other(isym.get_st_other());

View file

@ -352,10 +352,10 @@ class Relobj : public Object
// Initial local symbol processing: set the offset where local
// symbol information will be stored; add local symbol names to
// *POOL; return the offset following the local symbols.
off_t
finalize_local_symbols(off_t off, Stringpool* pool)
{ return this->do_finalize_local_symbols(off, pool); }
// *POOL; return the new local symbol index.
unsigned int
finalize_local_symbols(unsigned int index, off_t off, Stringpool* pool)
{ return this->do_finalize_local_symbols(index, off, pool); }
// Relocate the input sections and write out the local symbols.
void
@ -408,8 +408,8 @@ class Relobj : public Object
Read_relocs_data*) = 0;
// Finalize local symbols--implemented by child class.
virtual off_t
do_finalize_local_symbols(off_t, Stringpool*) = 0;
virtual unsigned int
do_finalize_local_symbols(unsigned int, off_t, Stringpool*) = 0;
// Relocate the input sections and write out the local
// symbols--implemented by child class.
@ -443,6 +443,9 @@ template<int size, bool big_endian>
class Sized_relobj : public Relobj
{
public:
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
typedef std::vector<Address> Local_values;
Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
const typename elfcpp::Ehdr<size, big_endian>&);
@ -452,6 +455,16 @@ class Sized_relobj : public Relobj
void
setup(const typename elfcpp::Ehdr<size, big_endian>&);
// Return the index of local symbol SYM in the ordinary symbol
// table. A value of -1U means that the symbol is not being output.
unsigned int
symtab_index(unsigned int sym) const
{
assert(sym < this->local_indexes_.size());
assert(this->local_indexes_[sym] != 0);
return this->local_indexes_[sym];
}
// Read the symbols.
void
do_read_symbols(Read_symbols_data*);
@ -475,8 +488,8 @@ class Sized_relobj : public Relobj
Read_relocs_data*);
// Finalize the local symbols.
off_t
do_finalize_local_symbols(off_t, Stringpool*);
unsigned int
do_finalize_local_symbols(unsigned int, off_t, Stringpool*);
// Relocate the input sections and write out the local symbols.
void
@ -563,7 +576,9 @@ class Sized_relobj : public Relobj
// File offset for local symbols.
off_t local_symbol_offset_;
// Values of local symbols.
typename elfcpp::Elf_types<size>::Elf_Addr *values_;
Local_values local_values_;
// Indexes of local symbols in the output file; -1U if not present.
std::vector<unsigned int> local_indexes_;
};
// A class to manage the list of all objects.
@ -643,9 +658,9 @@ struct Relocate_info
// Number of local symbols.
unsigned int local_symbol_count;
// Values of local symbols.
typename elfcpp::Elf_types<size>::Elf_Addr *values;
const typename Sized_relobj<size, big_endian>::Local_values* local_values;
// Global symbols.
Symbol** symbols;
const Symbol* const * symbols;
// Section index of relocation section.
unsigned int reloc_shndx;
// Section index of section being relocated.

View file

@ -366,6 +366,120 @@ Output_section_data::do_out_shndx() const
return this->output_section_->out_shndx();
}
// Output_reloc methods.
// Get the symbol index of a relocation.
template<bool dynamic, int size, bool big_endian>
unsigned int
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
const
{
unsigned int index;
switch (this->local_sym_index_)
{
case INVALID_CODE:
abort();
case GSYM_CODE:
if (this->u_.gsym == NULL)
index = 0;
else if (dynamic)
index = this->u_.gsym->dynsym_index();
else
index = this->u_.gsym->symtab_index();
break;
case SECTION_CODE:
if (dynamic)
index = this->u_.os->dynsym_index();
else
index = this->u_.os->symtab_index();
break;
default:
if (dynamic)
{
// FIXME: It seems that some targets may need to generate
// dynamic relocations against local symbols for some
// reasons. This will have to be addressed at some point.
abort();
}
else
index = this->u_.object->symtab_index(this->local_sym_index_);
break;
}
assert(index != -1U);
return index;
}
// Write out the offset and info fields of a Rel or Rela relocation
// entry.
template<bool dynamic, int size, bool big_endian>
template<typename Write_rel>
void
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
Write_rel* wr) const
{
wr->put_r_offset(this->address_);
wr->put_r_info(elfcpp::elf_r_info<size>(this->get_symbol_index(),
this->type_));
}
// Write out a Rel relocation.
template<bool dynamic, int size, bool big_endian>
void
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write(
unsigned char* pov) const
{
elfcpp::Rel_write<size, big_endian> orel(pov);
this->write_rel(&orel);
}
// Write out a Rela relocation.
template<bool dynamic, int size, bool big_endian>
void
Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
unsigned char* pov) const
{
elfcpp::Rela_write<size, big_endian> orel(pov);
this->rel_.write_rel(&orel);
orel.put_r_addend(this->addend_);
}
// Output_data_reloc_base methods.
// Write out relocation data.
template<int sh_type, bool dynamic, int size, bool big_endian>
void
Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
Output_file* of)
{
const off_t off = this->offset();
const off_t oview_size = this->data_size();
unsigned char* const oview = of->get_output_view(off, oview_size);
unsigned char* pov = oview;
for (typename Relocs::const_iterator p = this->relocs_.begin();
p != this->relocs_.end();
++p)
{
p->write(pov);
pov += reloc_size;
}
assert(pov - oview == oview_size);
of->write_output_view(off, oview_size, oview);
// We no longer need the relocation entries.
this->relocs_.clear();
}
// Output_data_got::Got_entry methods.
// Write out the entry.
@ -439,7 +553,7 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
const int add = size / 8;
const off_t off = this->offset();
const off_t oview_size = this->entries_.size() * add;
const off_t oview_size = this->data_size();
unsigned char* const oview = of->get_output_view(off, oview_size);
unsigned char* pov = oview;
@ -451,6 +565,8 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
pov += add;
}
assert(pov - oview == oview_size);
of->write_output_view(off, oview_size, oview);
// We no longer need the GOT entries.
@ -508,6 +624,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
type_(type),
flags_(flags),
out_shndx_(0),
symtab_index_(0),
dynsym_index_(0),
input_sections_(),
first_input_offset_(0),
may_add_data_(may_add_data)
@ -564,12 +682,17 @@ Output_section::add_input_section(Relobj* object, unsigned int shndx,
void
Output_section::add_output_section_data(Output_section_data* posd)
{
assert(this->may_add_data_);
if (this->input_sections_.empty())
this->first_input_offset_ = this->data_size();
this->input_sections_.push_back(Input_section(posd));
uint64_t addralign = posd->addralign();
if (addralign > this->addralign_)
this->addralign_ = addralign;
posd->set_output_section(this);
}
@ -627,14 +750,6 @@ Output_section::do_write(Output_file* of)
p->write(of);
}
// Output_section_symtab methods.
Output_section_symtab::Output_section_symtab(const char* name, off_t size)
: Output_section(name, elfcpp::SHT_SYMTAB, 0, false)
{
this->set_data_size(size);
}
// Output_section_strtab methods.
Output_section_strtab::Output_section_strtab(const char* name,
@ -1143,6 +1258,54 @@ Output_section::add_input_section<64, true>(
const char* secname,
const elfcpp::Shdr<64, true>& shdr);
template
class Output_data_reloc<elfcpp::SHT_REL, false, 32, false>;
template
class Output_data_reloc<elfcpp::SHT_REL, false, 32, true>;
template
class Output_data_reloc<elfcpp::SHT_REL, false, 64, false>;
template
class Output_data_reloc<elfcpp::SHT_REL, false, 64, true>;
template
class Output_data_reloc<elfcpp::SHT_REL, true, 32, false>;
template
class Output_data_reloc<elfcpp::SHT_REL, true, 32, true>;
template
class Output_data_reloc<elfcpp::SHT_REL, true, 64, false>;
template
class Output_data_reloc<elfcpp::SHT_REL, true, 64, true>;
template
class Output_data_reloc<elfcpp::SHT_RELA, false, 32, false>;
template
class Output_data_reloc<elfcpp::SHT_RELA, false, 32, true>;
template
class Output_data_reloc<elfcpp::SHT_RELA, false, 64, false>;
template
class Output_data_reloc<elfcpp::SHT_RELA, false, 64, true>;
template
class Output_data_reloc<elfcpp::SHT_RELA, true, 32, false>;
template
class Output_data_reloc<elfcpp::SHT_RELA, true, 32, true>;
template
class Output_data_reloc<elfcpp::SHT_RELA, true, 64, false>;
template
class Output_data_reloc<elfcpp::SHT_RELA, true, 64, true>;
template
class Output_data_got<32, false>;

View file

@ -9,6 +9,7 @@
#include "elfcpp.h"
#include "layout.h"
#include "reloc-types.h"
namespace gold
{
@ -16,9 +17,11 @@ namespace gold
class General_options;
class Object;
class Output_file;
class Output_section;
template<int size, bool big_endian>
class Sized_target;
template<int size, bool big_endian>
class Sized_relobj;
// An abtract class for data which has to go into the output file.
@ -361,6 +364,262 @@ class Output_data_common : public Output_section_data
{ }
};
// This POD class is used to represent a single reloc in the output
// file. This could be a private class within Output_data_reloc, but
// the templatization is complex enough that I broke it out into a
// separate class. The class is templatized on either elfcpp::SHT_REL
// or elfcpp::SHT_RELA, and also on whether this is a dynamic
// relocation or an ordinary relocation.
// A relocation can be against a global symbol, a local symbol, an
// output section, or the undefined symbol at index 0. We represent
// the latter by using a NULL global symbol.
template<int sh_type, bool dynamic, int size, bool big_endian>
class Output_reloc;
template<bool dynamic, int size, bool big_endian>
class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
{
public:
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
// An uninitialized entry. We need this because we want to put
// instances of this class into an STL container.
Output_reloc()
: local_sym_index_(INVALID_CODE)
{ }
// A reloc against a global symbol.
Output_reloc(Symbol* gsym, unsigned int type, Address address)
: local_sym_index_(GSYM_CODE), type_(type), address_(address)
{ this->u_.gsym = gsym; }
// A reloc against a local symbol.
Output_reloc(Sized_relobj<size, big_endian>* object,
unsigned int local_sym_index,
unsigned int type, Address address)
: local_sym_index_(local_sym_index), type_(type), address_(address)
{
assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE);
this->u_.object = object;
}
// A reloc against the STT_SECTION symbol of an output section.
Output_reloc(Output_section* os, unsigned int type, Address address)
: local_sym_index_(SECTION_CODE), type_(type), address_(address)
{ this->u_.os = os; }
// Write the reloc entry to an output view.
void
write(unsigned char* pov) const;
// Write the offset and info fields to Write_rel.
template<typename Write_rel>
void write_rel(Write_rel*) const;
private:
// Return the symbol index. We can't do a double template
// specialization, so we do a secondary template here.
unsigned int
get_symbol_index() const;
// Codes for local_sym_index_.
enum
{
// Global symbol.
GSYM_CODE = -1U,
// Output section.
SECTION_CODE = -2U,
// Invalid uninitialized entry.
INVALID_CODE = -3U
};
union
{
// For a local symbol, the object. We will never generate a
// relocation against a local symbol in a dynamic object; that
// doesn't make sense. And our callers will always be
// templatized, so we use Sized_relobj here.
Sized_relobj<size, big_endian>* object;
// For a global symbol, the symbol. If this is NULL, it indicates
// a relocation against the undefined 0 symbol.
Symbol* gsym;
// For a relocation against an output section, the output section.
Output_section* os;
} u_;
// For a local symbol, the local symbol index. This is GSYM_CODE
// for a global symbol, or INVALID_CODE for an uninitialized value.
unsigned int local_sym_index_;
unsigned int type_;
Address address_;
};
// The SHT_RELA version of Output_reloc<>. This is just derived from
// the SHT_REL version of Output_reloc, but it adds an addend.
template<bool dynamic, int size, bool big_endian>
class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
{
public:
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
// An uninitialized entry.
Output_reloc()
: rel_()
{ }
// A reloc against a global symbol.
Output_reloc(Symbol* gsym, unsigned int type, Address address, Addend addend)
: rel_(gsym, type, address), addend_(addend)
{ }
// A reloc against a local symbol.
Output_reloc(Sized_relobj<size, big_endian>* object,
unsigned int local_sym_index,
unsigned int type, Address address, Addend addend)
: rel_(object, local_sym_index, type, address), addend_(addend)
{ }
// A reloc against the STT_SECTION symbol of an output section.
Output_reloc(Output_section* os, unsigned int type, Address address,
Addend addend)
: rel_(os, type, address), addend_(addend)
{ }
// Write the reloc entry to an output view.
void
write(unsigned char* pov) const;
private:
// The basic reloc.
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> rel_;
// The addend.
Addend addend_;
};
// Output_data_reloc is used to manage a section containing relocs.
// SH_TYPE is either elfcpp::SHT_REL or elfcpp::SHT_RELA. DYNAMIC
// indicates whether this is a dynamic relocation or a normal
// relocation. Output_data_reloc_base is a base class.
// Output_data_reloc is the real class, which we specialize based on
// the reloc type.
template<int sh_type, bool dynamic, int size, bool big_endian>
class Output_data_reloc_base : public Output_section_data
{
public:
typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
typedef typename Output_reloc_type::Address Address;
static const int reloc_size =
Reloc_types<sh_type, size, big_endian>::reloc_size;
// Construct the section.
Output_data_reloc_base()
: Output_section_data(Output_data::default_alignment(size))
{ }
// Write out the data.
void
do_write(Output_file*);
protected:
// Add a relocation entry.
void
add(const Output_reloc_type& reloc)
{
this->relocs_.push_back(reloc);
this->set_data_size(this->relocs_.size() * reloc_size);
}
private:
typedef std::vector<Output_reloc_type> Relocs;
Relocs relocs_;
};
// The class which callers actually create.
template<int sh_type, bool dynamic, int size, bool big_endian>
class Output_data_reloc;
// The SHT_REL version of Output_data_reloc.
template<bool dynamic, int size, bool big_endian>
class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
: public Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>
{
private:
typedef Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size,
big_endian> Base;
public:
typedef typename Base::Output_reloc_type Output_reloc_type;
typedef typename Output_reloc_type::Address Address;
Output_data_reloc()
: Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>()
{ }
// Add a reloc against a global symbol.
void
add_global(Symbol* gsym, unsigned int type, Address address)
{ this->add(Output_reloc_type(gsym, type, address)); }
// Add a reloc against a local symbol.
void
add_local(Sized_relobj<size, big_endian>* object,
unsigned int local_sym_index, unsigned int type, Address address)
{ this->add(Output_reloc_type(object, local_sym_index, type, address)); }
// A reloc against the STT_SECTION symbol of an output section.
void
add_output_section(Output_section* os, unsigned int type, Address address)
{ this->add(Output_reloc_type(os, type, address)); }
};
// The SHT_RELA version of Output_data_reloc.
template<bool dynamic, int size, bool big_endian>
class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
: public Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>
{
private:
typedef Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size,
big_endian> Base;
public:
typedef typename Base::Output_reloc_type Output_reloc_type;
typedef typename Output_reloc_type::Address Address;
typedef typename Output_reloc_type::Addend Addend;
Output_data_reloc()
: Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>()
{ }
// Add a reloc against a global symbol.
void
add_global(Symbol* gsym, unsigned int type, Address address, Addend addend)
{ this->add(Output_reloc_type(gsym, type, address, addend)); }
// Add a reloc against a local symbol.
void
add_local(Sized_relobj<size, big_endian>* object,
unsigned int local_sym_index, unsigned int type,
Address address, Addend addend)
{
this->add(Output_reloc_type(object, local_sym_index, type, address,
addend));
}
// A reloc against the STT_SECTION symbol of an output section.
void
add_output_section(Output_section* os, unsigned int type, Address address,
Addend addend)
{ this->add(Output_reloc_type(os, type, address, addend)); }
};
// Output_data_got is used to manage a GOT. Each entry in the GOT is
// for one symbol--either a global symbol or a local symbol in an
// object. The target specific code adds entries to the GOT as
@ -456,8 +715,8 @@ class Output_data_got : public Output_section_data
// For a constant, the constant.
Valtype constant;
} u_;
// For a local symbol, the local symbol index. This is -1U for a
// global symbol, or -2U for a constant.
// For a local symbol, the local symbol index. This is GSYM_CODE
// for a global symbol, or CONSTANT_CODE for a constant.
unsigned int local_sym_index_;
};
@ -501,7 +760,7 @@ class Output_section : public Output_data
const elfcpp::Shdr<size, big_endian>& shdr);
// Add generated data ODATA to this output section.
virtual void
void
add_output_section_data(Output_section_data* posd);
// Return the section name.
@ -549,6 +808,58 @@ class Output_section : public Output_data
set_addralign(uint64_t v)
{ this->addralign_ = v; }
// Indicate that we need a symtab index.
void
set_needs_symtab_index()
{ this->needs_symtab_index_ = true; }
// Return whether we need a symtab index.
bool
needs_symtab_index() const
{ return this->needs_symtab_index_; }
// Get the symtab index.
unsigned int
symtab_index() const
{
assert(this->symtab_index_ != 0);
return this->symtab_index_;
}
// Set the symtab index.
void
set_symtab_index(unsigned int index)
{
assert(index != 0);
this->symtab_index_ = index;
}
// Indicate that we need a dynsym index.
void
set_needs_dynsym_index()
{ this->needs_dynsym_index_ = true; }
// Return whether we need a dynsym index.
bool
needs_dynsym_index() const
{ return this->needs_dynsym_index_; }
// Get the dynsym index.
unsigned int
dynsym_index() const
{
assert(this->dynsym_index_ != 0);
return this->dynsym_index_;
}
// Set the dynsym index.
void
set_dynsym_index(unsigned int index)
{
assert(index != 0);
this->dynsym_index_ = index;
}
// Set the address of the Output_section. For a typical
// Output_section, there is nothing to do, but if there are any
// Output_section_data objects we need to set the final addresses
@ -686,13 +997,31 @@ class Output_section : public Output_data
elfcpp::Elf_Xword flags_;
// The section index.
unsigned int out_shndx_;
// If there is a STT_SECTION for this output section in the normal
// symbol table, this is the symbol index. This starts out as zero.
// It is initialized in Layout::finalize() to be the index, or -1U
// if there isn't one.
unsigned int symtab_index_;
// If there is a STT_SECTION for this output section in the dynamic
// symbol table, this is the symbol index. This starts out as zero.
// It is initialized in Layout::finalize() to be the index, or -1U
// if there isn't one.
unsigned int dynsym_index_;
// The input sections. This will be empty in cases where we don't
// need to keep track of them.
Input_section_list input_sections_;
// The offset of the first entry in input_sections_.
off_t first_input_offset_;
// Whether we permit adding data.
bool may_add_data_;
bool may_add_data_ : 1;
// Whether this output section needs a STT_SECTION symbol in the
// normal symbol table. This will be true if there is a relocation
// which needs it.
bool needs_symtab_index_ : 1;
// Whether this output section needs a STT_SECTION symbol in the
// dynamic symbol table. This will be true if there is a dynamic
// relocation which needs it.
bool needs_dynsym_index_ : 1;
};
// A special Output_section which represents the symbol table
@ -702,18 +1031,33 @@ class Output_section : public Output_data
class Output_section_symtab : public Output_section
{
public:
Output_section_symtab(const char* name, off_t size);
Output_section_symtab(const char* name, off_t data_size)
: Output_section(name, elfcpp::SHT_SYMTAB, 0, false)
{ this->set_data_size(data_size); }
// The data is written out by Symbol_table::write_globals. We don't
// do anything here.
void
do_write(Output_file*)
{ }
};
// We don't expect to see any input sections or data here.
// A special Output_section which represents the dynamic symbol table
// (SHT_DYNSYM). The actual data is written out by
// Symbol_table::write_globals.
class Output_section_dynsym : public Output_section
{
public:
Output_section_dynsym(const char* name, off_t data_size)
: Output_section(name, elfcpp::SHT_DYNSYM, 0, false)
{ this->set_data_size(data_size); }
// The data is written out by Symbol_table::write_globals. We don't
// do anything here.
void
add_output_section_data(Output_section_data*)
{ abort(); }
do_write(Output_file*)
{ }
};
// A special Output_section which holds a string table.
@ -727,11 +1071,6 @@ class Output_section_strtab : public Output_section
void
do_write(Output_file*);
// We don't expect to see any input sections or data here.
void
add_output_section_data(Output_section_data*)
{ abort(); }
private:
Stringpool* contents_;
};

View file

@ -27,8 +27,10 @@ readsyms.cc
readsyms.h
reloc.cc
reloc.h
reloc-types.h
resolve.cc
script.cc
script-c.h
script.h
stringpool.cc
stringpool.h

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-11-14 11:17-0800\n"
"POT-Creation-Date: 2006-11-15 16:35-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -101,7 +101,7 @@ msgstr ""
msgid "%s: %s: dynamic symbol table name section has wrong type: %u\n"
msgstr ""
#: dynobj.cc:356 object.cc:421
#: dynobj.cc:356 object.cc:422
#, c-format
msgid "%s: %s: bad section name offset for section %u: %lu\n"
msgstr ""
@ -300,87 +300,87 @@ msgstr ""
msgid "%s: %s: section name section has wrong type: %u\n"
msgstr ""
#: object.cc:229
#: object.cc:230
#, c-format
msgid "%s: %s: invalid symbol table name index: %u\n"
msgstr ""
#: object.cc:237
#: object.cc:238
#, c-format
msgid "%s: %s: symbol table name section has wrong type: %u\n"
msgstr ""
#: object.cc:293
#: object.cc:294
#, c-format
msgid "%s: %s: section group %u info %u out of range\n"
msgstr ""
#: object.cc:310
#: object.cc:311
#, c-format
msgid "%s: %s: symbol %u name offset %u out of range\n"
msgstr ""
#: object.cc:344
#: object.cc:345
#, c-format
msgid "%s: %s: section %u in section group %u out of range"
msgstr ""
#: object.cc:488
#: object.cc:489
#, c-format
msgid "%s: %s: size of symbols is not multiple of symbol size\n"
msgstr ""
#: object.cc:572
#: object.cc:576
#, c-format
msgid "%s: %s: unknown section index %u for local symbol %u\n"
msgstr ""
#: object.cc:583
#: object.cc:587
#, c-format
msgid "%s: %s: local symbol %u section index %u out of range\n"
msgstr ""
#: object.cc:605
#: object.cc:616
#, c-format
msgid "%s: %s: local symbol %u section name out of range: %u >= %u\n"
msgstr ""
#: object.cc:782
#: object.cc:800
#, c-format
msgid "%s: %s: unsupported ELF file type %d\n"
msgstr ""
#: object.cc:801 object.cc:854 object.cc:875
#: object.cc:819 object.cc:872 object.cc:893
#, c-format
msgid "%s: %s: ELF file too short\n"
msgstr ""
#: object.cc:810
#: object.cc:828
#, c-format
msgid "%s: %s: invalid ELF version 0\n"
msgstr ""
#: object.cc:813
#: object.cc:831
#, c-format
msgid "%s: %s: unsupported ELF version %d\n"
msgstr ""
#: object.cc:821
#: object.cc:839
#, c-format
msgid "%s: %s: invalid ELF class 0\n"
msgstr ""
#: object.cc:828
#: object.cc:846
#, c-format
msgid "%s: %s: unsupported ELF class %d\n"
msgstr ""
#: object.cc:836
#: object.cc:854
#, c-format
msgid "%s: %s: invalid ELF data encoding\n"
msgstr ""
#: object.cc:843
#: object.cc:861
#, c-format
msgid "%s: %s: unsupported ELF data encoding %d\n"
msgstr ""
@ -496,37 +496,37 @@ msgstr ""
msgid "%s: -%c: %s\n"
msgstr ""
#: output.cc:538
#: output.cc:656
#, c-format
msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
msgstr ""
#: output.cc:1056
#: output.cc:1171
#, c-format
msgid "%s: %s: open: %s\n"
msgstr ""
#: output.cc:1065
#: output.cc:1180
#, c-format
msgid "%s: %s: lseek: %s\n"
msgstr ""
#: output.cc:1072
#: output.cc:1187
#, c-format
msgid "%s: %s: write: %s\n"
msgstr ""
#: output.cc:1082
#: output.cc:1197
#, c-format
msgid "%s: %s: mmap: %s\n"
msgstr ""
#: output.cc:1096
#: output.cc:1211
#, c-format
msgid "%s: %s: munmap: %s\n"
msgstr ""
#: output.cc:1104
#: output.cc:1219
#, c-format
msgid "%s: %s: close: %s\n"
msgstr ""
@ -567,62 +567,62 @@ msgstr ""
msgid "%s: %s: reloc section %u size %lu uneven"
msgstr ""
#: resolve.cc:141
#: resolve.cc:142
#, c-format
msgid "%s: %s: invalid STB_LOCAL symbol %s in external symbols\n"
msgstr ""
#: resolve.cc:147
#: resolve.cc:148
#, c-format
msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
msgstr ""
#: symtab.cc:443 symtab.cc:540
#: symtab.cc:446 symtab.cc:543
#, c-format
msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
msgstr ""
#: symtab.cc:460
#: symtab.cc:463
#, c-format
msgid "%s: %s: bad global symbol name offset %u at %lu\n"
msgstr ""
#: symtab.cc:547
#: symtab.cc:550
#, c-format
msgid "%s: %s: too few symbol versions\n"
msgstr ""
#: symtab.cc:567
#: symtab.cc:570
#, c-format
msgid "%s: %s: bad symbol name offset %u at %lu\n"
msgstr ""
#: symtab.cc:611
#: symtab.cc:614
#, c-format
msgid "%s: %s: versym for symbol %zu out of range: %u\n"
msgstr ""
#: symtab.cc:619
#: symtab.cc:622
#, c-format
msgid "%s: %s: versym for symbol %zu has no name: %u\n"
msgstr ""
#: symtab.cc:1010 symtab.cc:1149
#: symtab.cc:1019 symtab.cc:1158
#, c-format
msgid "%s: %s: unsupported symbol section 0x%x\n"
msgstr ""
#: symtab.cc:1262
#: symtab.cc:1274
#, c-format
msgid "%s: %s: warning: %s\n"
msgstr ""
#: target-reloc.h:181
#: target-reloc.h:163
#, c-format
msgid "%s: %s: reloc has bad offset %zu\n"
msgstr ""
#: target-reloc.h:191
#: target-reloc.h:173
#, c-format
msgid "%s: %s: undefined reference to '%s'\n"
msgstr ""

36
gold/reloc-types.h Normal file
View file

@ -0,0 +1,36 @@
// reloc-types.h -- ELF relocation templates for gold -*- C++ -*-
// This header files defines a few convenient templated types for use
// when handling ELF relocations.
#ifndef GOLD_RELOC_TYPES_H
#define GOLD_RELOC_TYPES_H
#include "elfcpp.h"
namespace gold
{
// Pick the ELF relocation accessor class and the size based on
// SH_TYPE, which is either elfcpp::SHT_REL or elfcpp::SHT_RELA.
template<int sh_type, int size, bool big_endian>
struct Reloc_types;
template<int size, bool big_endian>
struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
{
typedef typename elfcpp::Rel<size, big_endian> Reloc;
static const int reloc_size = elfcpp::Elf_sizes<size>::rel_size;
};
template<int size, bool big_endian>
struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
{
typedef typename elfcpp::Rela<size, big_endian> Reloc;
static const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
};
}; // End namespace gold.
#endif // !defined(GOLD_RELOC_TYPE_SH)

View file

@ -391,7 +391,7 @@ Sized_relobj<size, big_endian>::relocate_sections(
relinfo.layout = layout;
relinfo.object = this;
relinfo.local_symbol_count = this->local_symbol_count_;
relinfo.values = this->values_;
relinfo.local_values = &this->local_values_;
relinfo.symbols = this->symbols_;
const unsigned char* p = pshdrs + This::shdr_size;

View file

@ -106,7 +106,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
abort();
}
if (to->object() != NULL && to->object()->is_dynamic())
if (to->source() == Symbol::FROM_OBJECT
&& to->object()->is_dynamic())
tobits |= (1 << 1);
switch (to->shnum())
@ -174,6 +175,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
break;
}
if ((tobits & (1 << 1)) != (frombits & (1 << 1)))
{
// This symbol is seen in both a dynamic object and a regular
// object. That means that we need the symbol to go into the
// dynamic symbol table, so that the dynamic linker can use the
// regular symbol to override or define the dynamic symbol.
to->set_needs_dynsym_entry();
}
// FIXME: Warn if either but not both of TO and SYM are STT_TLS.
// We use a giant switch table for symbol resolution. This code is

View file

@ -29,6 +29,8 @@ Symbol::init_fields(const char* name, const char* version,
{
this->name_ = name;
this->version_ = version;
this->symtab_index_ = 0;
this->dynsym_index_ = 0;
this->got_offset_ = 0;
this->type_ = type;
this->binding_ = binding;
@ -37,6 +39,7 @@ Symbol::init_fields(const char* name, const char* version,
this->is_target_special_ = false;
this->is_def_ = false;
this->is_forwarder_ = false;
this->needs_dynsym_entry_ = false;
this->in_dyn_ = false;
this->has_got_offset_ = false;
this->has_warning_ = false;
@ -204,10 +207,10 @@ Symbol_table::make_forwarder(Symbol* from, Symbol* to)
// Resolve the forwards from FROM, returning the real symbol.
Symbol*
Symbol_table::resolve_forwards(Symbol* from) const
Symbol_table::resolve_forwards(const Symbol* from) const
{
assert(from->is_forwarder());
Unordered_map<Symbol*, Symbol*>::const_iterator p =
Unordered_map<const Symbol*, Symbol*>::const_iterator p =
this->forwarders_.find(from);
assert(p != this->forwarders_.end());
return p->second;
@ -952,18 +955,22 @@ Symbol_table::define_symbols(const Layout* layout, Target* target, int count,
}
}
// Set the final values for all the symbols. Record the file offset
// Set the final values for all the symbols. The index of the first
// global symbol in the output file is INDEX. Record the file offset
// OFF. Add their names to POOL. Return the new file offset.
off_t
Symbol_table::finalize(off_t off, Stringpool* pool)
Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
{
off_t ret;
assert(index != 0);
this->first_global_index_ = index;
if (this->size_ == 32)
ret = this->sized_finalize<32>(off, pool);
ret = this->sized_finalize<32>(index, off, pool);
else if (this->size_ == 64)
ret = this->sized_finalize<64>(off, pool);
ret = this->sized_finalize<64>(index, off, pool);
else
abort();
@ -980,15 +987,17 @@ Symbol_table::finalize(off_t off, Stringpool* pool)
template<int size>
off_t
Symbol_table::sized_finalize(off_t off, Stringpool* pool)
Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
{
off = align_address(off, size >> 3);
this->offset_ = off;
size_t orig_index = index;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
Symbol_table_type::iterator p = this->table_.begin();
size_t count = 0;
while (p != this->table_.end())
for (Symbol_table_type::iterator p = this->table_.begin();
p != this->table_.end();
++p)
{
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
@ -1030,12 +1039,7 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
if (os == NULL)
{
// We should be able to erase this symbol from the
// symbol table, but at least with gcc 4.0.2
// std::unordered_map::erase doesn't appear to return
// the new iterator.
// p = this->table_.erase(p);
++p;
sym->set_symtab_index(-1U);
continue;
}
@ -1082,13 +1086,13 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
}
sym->set_value(value);
sym->set_symtab_index(index);
pool->add(sym->name(), NULL);
++count;
++index;
off += sym_size;
++p;
}
this->output_count_ = count;
this->output_count_ = index - orig_index;
return off;
}
@ -1126,8 +1130,10 @@ Symbol_table::sized_write_globals(const Target*,
Output_file* of) const
{
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned char* psyms = of->get_output_view(this->offset_,
this->output_count_ * sym_size);
unsigned int index = this->first_global_index_;
const off_t oview_size = this->output_count_ * sym_size;
unsigned char* psyms = of->get_output_view(this->offset_, oview_size);
unsigned char* ps = psyms;
for (Symbol_table_type::const_iterator p = this->table_.begin();
p != this->table_.end();
@ -1135,6 +1141,9 @@ Symbol_table::sized_write_globals(const Target*,
{
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
if (sym->symtab_index() == -1U)
continue;
unsigned int shndx;
switch (sym->source())
{
@ -1164,9 +1173,7 @@ Symbol_table::sized_write_globals(const Target*,
Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff;
Output_section* os = relobj->output_section(shnum, &secoff);
if (os == NULL)
continue;
assert(os != NULL);
shndx = os->out_shndx();
}
}
@ -1188,6 +1195,9 @@ Symbol_table::sized_write_globals(const Target*,
abort();
}
assert(sym->symtab_index() == index);
++index;
elfcpp::Sym_write<size, big_endian> osym(ps);
osym.put_st_name(sympool->get_offset(sym->name()));
osym.put_st_value(sym->value());
@ -1200,7 +1210,9 @@ Symbol_table::sized_write_globals(const Target*,
ps += sym_size;
}
of->write_output_view(this->offset_, this->output_count_ * sym_size, psyms);
assert(ps - psyms == oview_size);
of->write_output_view(this->offset_, oview_size, psyms);
}
// Warnings functions.
@ -1254,7 +1266,7 @@ Warnings::note_warnings(Symbol_table* symtab)
// symbol for which has a warning.
void
Warnings::issue_warning(Symbol* sym, const std::string& location) const
Warnings::issue_warning(const Symbol* sym, const std::string& location) const
{
assert(sym->has_warning());
Warning_table::const_iterator p = this->warnings_.find(sym->name());

View file

@ -173,6 +173,17 @@ class Symbol
set_forwarder()
{ this->is_forwarder_ = true; }
// Return whether this symbol needs an entry in the dynamic symbol
// table.
bool
needs_dynsym_entry() const
{ return this->needs_dynsym_entry_; }
// Mark this symbol as needing an entry in the dynamic symbol table.
void
set_needs_dynsym_entry()
{ this->needs_dynsym_entry_ = true; }
// Return whether this symbol was ever seen in a dynamic object.
bool
in_dyn() const
@ -183,6 +194,46 @@ class Symbol
set_in_dyn()
{ this->in_dyn_ = true; }
// Return the index of this symbol in the output file symbol table.
// A value of -1U means that this symbol is not going into the
// output file. This starts out as zero, and is set to a non-zero
// value by Symbol_table::finalize. It is an error to ask for the
// symbol table index before it has been set.
unsigned int
symtab_index() const
{
assert(this->symtab_index_ != 0);
return this->symtab_index_;
}
// Set the index of the symbol in the output file symbol table.
void
set_symtab_index(unsigned int index)
{
assert(index != 0);
this->symtab_index_ = index;
}
// Return the index of this symbol in the dynamic symbol table. A
// value of -1U means that this symbol is not going into the dynamic
// symbol table. This starts out as zero, and is set to a non-zero
// during Layout::finalize. It is an error to ask for the dynamic
// symbol table index before it has been set.
unsigned int
dynsym_index() const
{
assert(this->dynsym_index_ != 0);
return this->dynsym_index_;
}
// Set the index of the symbol in the dynamic symbol table.
void
set_dynsym_index(unsigned int index)
{
assert(index != 0);
this->dynsym_index_ = index;
}
// Return whether this symbol has an entry in the GOT section.
bool
has_got_offset() const
@ -334,9 +385,22 @@ class Symbol
} in_output_segment;
} u_;
// The index of this symbol in the output file. If the symbol is
// not going into the output file, this value is -1U. This field
// starts as always holding zero. It is set to a non-zero value by
// Symbol_table::finalize.
unsigned int symtab_index_;
// The index of this symbol in the dynamic symbol table. If the
// symbol is not going into the dynamic symbol table, this value is
// -1U. This field starts as always holding zero. It is set to a
// non-zero value during Layout::finalize.
unsigned int dynsym_index_;
// If this symbol has an entry in the GOT section (has_got_offset_
// is true), this is the offset.
// is true), this is the offset from the start of the GOT section.
unsigned int got_offset_;
// Symbol type.
elfcpp::STT type_ : 4;
// Symbol binding.
@ -360,6 +424,8 @@ class Symbol
// It forwards to the symbol found in the forwarders_ map of
// Symbol_table.
bool is_forwarder_ : 1;
// True if this symbol needs to be in the dynamic symbol table.
bool needs_dynsym_entry_ : 1;
// True if we've seen this symbol in a dynamic object.
bool in_dyn_ : 1;
// True if the symbol has an entry in the GOT section.
@ -548,7 +614,7 @@ class Warnings
// Issue a warning for a reference to SYM at LOCATION.
void
issue_warning(Symbol* sym, const std::string& location) const;
issue_warning(const Symbol* sym, const std::string& location) const;
private:
Warnings(const Warnings&);
@ -667,7 +733,7 @@ class Symbol_table
// Return the real symbol associated with the forwarder symbol FROM.
Symbol*
resolve_forwards(Symbol* from) const;
resolve_forwards(const Symbol* from) const;
// Return the size of the symbols in the table.
int
@ -705,15 +771,16 @@ class Symbol_table
// Possibly issue a warning for a reference to SYM at LOCATION which
// is in OBJ.
void
issue_warning(Symbol* sym, const std::string& location) const
issue_warning(const Symbol* sym, const std::string& location) const
{ this->warnings_.issue_warning(sym, location); }
// Finalize the symbol table after we have set the final addresses
// of all the input sections. This sets the final symbol values and
// adds the names to *POOL. It records the file offset OFF, and
// of all the input sections. This sets the final symbol indexes,
// values and adds the names to *POOL. INDEX is the index of the
// first global symbol. This records the file offset OFF, and
// returns the new file offset.
off_t
finalize(off_t, Stringpool*);
finalize(unsigned int index, off_t off, Stringpool* pool);
// Write out the global symbols.
void
@ -791,7 +858,7 @@ class Symbol_table
// Finalize symbols specialized for size.
template<int size>
off_t
sized_finalize(off_t, Stringpool*);
sized_finalize(unsigned int, off_t, Stringpool*);
// Write globals specialized for size and endianness.
template<int size, bool big_endian>
@ -828,6 +895,9 @@ class Symbol_table
// use in archive groups.
int saw_undefined_;
// The index of the first global symbol in the output file.
unsigned int first_global_index_;
// The file offset within the output symtab section where we should
// write the table.
off_t offset_;
@ -843,7 +913,7 @@ class Symbol_table
Stringpool namepool_;
// Forwarding symbols.
Unordered_map<Symbol*, Symbol*> forwarders_;
Unordered_map<const Symbol*, Symbol*> forwarders_;
// We don't expect there to be very many common symbols, so we keep
// a list of them. When we find a common symbol we add it to this

View file

@ -6,30 +6,11 @@
#include "elfcpp.h"
#include "object.h"
#include "symtab.h"
#include "reloc-types.h"
namespace gold
{
// Pick the ELF relocation accessor class and the size based on
// SH_TYPE, which is either SHT_REL or SHT_RELA.
template<int sh_type, int size, bool big_endian>
struct Reloc_types;
template<int size, bool big_endian>
struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
{
typedef typename elfcpp::Rel<size, big_endian> Reloc;
static const int reloc_size = elfcpp::Elf_sizes<size>::rel_size;
};
template<int size, bool big_endian>
struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
{
typedef typename elfcpp::Rela<size, big_endian> Reloc;
static const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
};
// This function implements the generic part of reloc scanning. This
// is an inline function which takes a class whose operator()
// implements the machine specific part of scanning. We do it this
@ -140,8 +121,9 @@ relocate_section(
Relocate relocate;
unsigned int local_count = relinfo->local_symbol_count;
typename elfcpp::Elf_types<size>::Elf_Addr *local_values = relinfo->values;
Symbol** global_syms = relinfo->symbols;
const typename Sized_relobj<size, big_endian>::Local_values* local_values =
relinfo->local_values;
const Symbol* const * global_syms = relinfo->symbols;
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
{
@ -153,22 +135,22 @@ relocate_section(
unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
Sized_symbol<size>* sym;
const Sized_symbol<size>* sym;
typename elfcpp::Elf_types<size>::Elf_Addr value;
if (r_sym < local_count)
{
sym = NULL;
value = local_values[r_sym];
value = (*local_values)[r_sym];
}
else
{
Symbol* gsym = global_syms[r_sym - local_count];
const Symbol* gsym = global_syms[r_sym - local_count];
assert(gsym != NULL);
if (gsym->is_forwarder())
gsym = relinfo->symtab->resolve_forwards(gsym);
sym = static_cast<Sized_symbol<size>*>(gsym);
sym = static_cast<const Sized_symbol<size>*>(gsym);
value = sym->value();
}