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_; 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> template<int size, bool big_endian>
class Rel class Rel
@ -1191,6 +1191,30 @@ class Rel
const internal::Rel_data<size>* p_; 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> template<int size, bool big_endian>
class Rela class Rela
{ {
@ -1221,6 +1245,32 @@ class Rela
const internal::Rela_data<size>* p_; 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 // Accessor classes for entries in the ELF SHT_DYNAMIC section aka
// PT_DYNAMIC segment. // PT_DYNAMIC segment.

View file

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

View file

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

View file

@ -96,7 +96,7 @@ class Target_i386 : public Sized_target<32, false>
inline bool inline bool
relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum, relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum,
const elfcpp::Rel<32, false>&, 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, elfcpp::Elf_types<32>::Elf_Addr,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
off_t); off_t);
@ -106,7 +106,7 @@ class Target_i386 : public Sized_target<32, false>
inline void inline void
relocate_tls(const Relocate_info<32, false>*, size_t relnum, relocate_tls(const Relocate_info<32, false>*, size_t relnum,
const elfcpp::Rel<32, false>&, 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, elfcpp::Elf_types<32>::Elf_Addr,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, off_t); 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, size_t relnum,
const elfcpp::Rel<32, false>& rel, const elfcpp::Rel<32, false>& rel,
unsigned int r_type, unsigned int r_type,
Sized_symbol<32>* gsym, const Sized_symbol<32>* gsym,
elfcpp::Elf_types<32>::Elf_Addr value, elfcpp::Elf_types<32>::Elf_Addr value,
unsigned char* view, unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr address, 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, size_t relnum,
const elfcpp::Rel<32, false>& rel, const elfcpp::Rel<32, false>& rel,
unsigned int r_type, unsigned int r_type,
Sized_symbol<32>* gsym, const Sized_symbol<32>* gsym,
elfcpp::Elf_types<32>::Elf_Addr value, elfcpp::Elf_types<32>::Elf_Addr value,
unsigned char* view, unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr, 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 // 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. // never bother to write this out--it will just be left as zero.
off += symsize; off += symsize;
unsigned int local_symbol_index = 1;
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end(); p != input_objects->relobj_end();
++p) ++p)
{ {
Task_lock_obj<Object> tlo(**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); 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(); this->sympool_.set_string_offsets();

View file

@ -128,7 +128,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
output_local_symbol_count_(0), output_local_symbol_count_(0),
symbols_(NULL), symbols_(NULL),
local_symbol_offset_(0), 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 // Finalize the local symbols. Here we record the file offset at
// which they should be output, we add their names to *POOL, and we // which they should be output, we add their names to *POOL, and we
// add their values to THIS->VALUES_. Return the new file offset. // add their values to THIS->LOCAL_VALUES_ and their indexes in the
// This function is always called from the main thread. The actual // output symbol table to THIS->LOCAL_INDEXES_. Return the symbol
// output of the local symbols will occur in a separate task. // 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> template<int size, bool big_endian>
off_t unsigned int
Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off, Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
off_t off,
Stringpool* pool) Stringpool* pool)
{ {
assert(this->symtab_shndx_ != -1U); assert(this->symtab_shndx_ != -1U);
if (this->symtab_shndx_ == 0) if (this->symtab_shndx_ == 0)
{ {
// This object has no symbols. Weird but legal. // 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; 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(), const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
locsize); 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. // Read the symbol names.
const unsigned int strtab_shndx = symtabshdr.get_sh_link(); 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. // 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 shnum = this->shnum();
unsigned int count = 0; unsigned int count = 0;
// Skip the first, dummy, symbol. // 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_LORESERVE)
{ {
if (shndx == elfcpp::SHN_ABS) if (shndx == elfcpp::SHN_ABS)
this->values_[i] = sym.get_st_value(); this->local_values_[i] = sym.get_st_value();
else else
{ {
// FIXME: Handle SHN_XINDEX. // FIXME: Handle SHN_XINDEX.
@ -588,17 +592,24 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
if (mo[shndx].output_section == NULL) if (mo[shndx].output_section == NULL)
{ {
this->values_[i] = 0; this->local_values_[i] = 0;
this->local_indexes_[i] = -1U;
continue; continue;
} }
this->values_[i] = (mo[shndx].output_section->address() this->local_values_[i] = (mo[shndx].output_section->address()
+ mo[shndx].offset + mo[shndx].offset
+ sym.get_st_value()); + 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)
{ {
this->local_indexes_[i] = -1U;
continue;
}
if (sym.get_st_name() >= strtab_size) if (sym.get_st_name() >= strtab_size)
{ {
fprintf(stderr, fprintf(stderr,
@ -610,15 +621,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
gold_exit(false); gold_exit(false);
} }
pool->add(pnames + sym.get_st_name(), NULL); const char* name = pnames + sym.get_st_name();
pool->add(name, NULL);
this->local_indexes_[i] = index;
++index;
off += sym_size; off += sym_size;
++count; ++count;
} }
}
this->output_local_symbol_count_ = count; this->output_local_symbol_count_ = count;
return off; return index;
} }
// Write out the local symbols. // 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_, unsigned char* oview = of->get_output_view(this->local_symbol_offset_,
output_size); 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; unsigned char* ov = oview;
psyms += sym_size;
for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
{ {
elfcpp::Sym<size, big_endian> isym(psyms); elfcpp::Sym<size, big_endian> isym(psyms);
if (isym.get_st_type() == elfcpp::STT_SECTION) if (this->local_indexes_[i] == -1U)
continue; continue;
assert(this->local_indexes_[i] != 0);
unsigned int st_shndx = isym.get_st_shndx(); unsigned int st_shndx = isym.get_st_shndx();
if (st_shndx < elfcpp::SHN_LORESERVE) 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); elfcpp::Sym_write<size, big_endian> osym(ov);
assert(isym.get_st_name() < strtab_size); assert(isym.get_st_name() < strtab_size);
osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name())); const char* name = pnames + isym.get_st_name();
osym.put_st_value(this->values_[i]); 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_size(isym.get_st_size());
osym.put_st_info(isym.get_st_info()); osym.put_st_info(isym.get_st_info());
osym.put_st_other(isym.get_st_other()); 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 // Initial local symbol processing: set the offset where local
// symbol information will be stored; add local symbol names to // symbol information will be stored; add local symbol names to
// *POOL; return the offset following the local symbols. // *POOL; return the new local symbol index.
off_t unsigned int
finalize_local_symbols(off_t off, Stringpool* pool) finalize_local_symbols(unsigned int index, off_t off, Stringpool* pool)
{ return this->do_finalize_local_symbols(off, pool); } { return this->do_finalize_local_symbols(index, off, pool); }
// Relocate the input sections and write out the local symbols. // Relocate the input sections and write out the local symbols.
void void
@ -408,8 +408,8 @@ class Relobj : public Object
Read_relocs_data*) = 0; Read_relocs_data*) = 0;
// Finalize local symbols--implemented by child class. // Finalize local symbols--implemented by child class.
virtual off_t virtual unsigned int
do_finalize_local_symbols(off_t, Stringpool*) = 0; do_finalize_local_symbols(unsigned int, off_t, Stringpool*) = 0;
// Relocate the input sections and write out the local // Relocate the input sections and write out the local
// symbols--implemented by child class. // symbols--implemented by child class.
@ -443,6 +443,9 @@ template<int size, bool big_endian>
class Sized_relobj : public Relobj class Sized_relobj : public Relobj
{ {
public: 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, Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
const typename elfcpp::Ehdr<size, big_endian>&); const typename elfcpp::Ehdr<size, big_endian>&);
@ -452,6 +455,16 @@ class Sized_relobj : public Relobj
void void
setup(const typename elfcpp::Ehdr<size, big_endian>&); 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. // Read the symbols.
void void
do_read_symbols(Read_symbols_data*); do_read_symbols(Read_symbols_data*);
@ -475,8 +488,8 @@ class Sized_relobj : public Relobj
Read_relocs_data*); Read_relocs_data*);
// Finalize the local symbols. // Finalize the local symbols.
off_t unsigned int
do_finalize_local_symbols(off_t, Stringpool*); do_finalize_local_symbols(unsigned int, off_t, Stringpool*);
// Relocate the input sections and write out the local symbols. // Relocate the input sections and write out the local symbols.
void void
@ -563,7 +576,9 @@ class Sized_relobj : public Relobj
// File offset for local symbols. // File offset for local symbols.
off_t local_symbol_offset_; off_t local_symbol_offset_;
// Values of local symbols. // 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. // A class to manage the list of all objects.
@ -643,9 +658,9 @@ struct Relocate_info
// Number of local symbols. // Number of local symbols.
unsigned int local_symbol_count; unsigned int local_symbol_count;
// Values of local symbols. // 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. // Global symbols.
Symbol** symbols; const Symbol* const * symbols;
// Section index of relocation section. // Section index of relocation section.
unsigned int reloc_shndx; unsigned int reloc_shndx;
// Section index of section being relocated. // 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(); 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. // Output_data_got::Got_entry methods.
// Write out the entry. // 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 int add = size / 8;
const off_t off = this->offset(); 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* const oview = of->get_output_view(off, oview_size);
unsigned char* pov = oview; unsigned char* pov = oview;
@ -451,6 +565,8 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
pov += add; pov += add;
} }
assert(pov - oview == oview_size);
of->write_output_view(off, oview_size, oview); of->write_output_view(off, oview_size, oview);
// We no longer need the GOT entries. // We no longer need the GOT entries.
@ -508,6 +624,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
type_(type), type_(type),
flags_(flags), flags_(flags),
out_shndx_(0), out_shndx_(0),
symtab_index_(0),
dynsym_index_(0),
input_sections_(), input_sections_(),
first_input_offset_(0), first_input_offset_(0),
may_add_data_(may_add_data) may_add_data_(may_add_data)
@ -564,12 +682,17 @@ Output_section::add_input_section(Relobj* object, unsigned int shndx,
void void
Output_section::add_output_section_data(Output_section_data* posd) Output_section::add_output_section_data(Output_section_data* posd)
{ {
assert(this->may_add_data_);
if (this->input_sections_.empty()) if (this->input_sections_.empty())
this->first_input_offset_ = this->data_size(); this->first_input_offset_ = this->data_size();
this->input_sections_.push_back(Input_section(posd)); this->input_sections_.push_back(Input_section(posd));
uint64_t addralign = posd->addralign(); uint64_t addralign = posd->addralign();
if (addralign > this->addralign_) if (addralign > this->addralign_)
this->addralign_ = addralign; this->addralign_ = addralign;
posd->set_output_section(this); posd->set_output_section(this);
} }
@ -627,14 +750,6 @@ Output_section::do_write(Output_file* of)
p->write(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 methods.
Output_section_strtab::Output_section_strtab(const char* name, Output_section_strtab::Output_section_strtab(const char* name,
@ -1143,6 +1258,54 @@ Output_section::add_input_section<64, true>(
const char* secname, const char* secname,
const elfcpp::Shdr<64, true>& shdr); 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 template
class Output_data_got<32, false>; class Output_data_got<32, false>;

View file

@ -9,6 +9,7 @@
#include "elfcpp.h" #include "elfcpp.h"
#include "layout.h" #include "layout.h"
#include "reloc-types.h"
namespace gold namespace gold
{ {
@ -16,9 +17,11 @@ namespace gold
class General_options; class General_options;
class Object; class Object;
class Output_file; class Output_file;
class Output_section;
template<int size, bool big_endian> template<int size, bool big_endian>
class Sized_target; 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. // 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 // 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 // for one symbol--either a global symbol or a local symbol in an
// object. The target specific code adds entries to the GOT as // 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. // For a constant, the constant.
Valtype constant; Valtype constant;
} u_; } u_;
// For a local symbol, the local symbol index. This is -1U for a // For a local symbol, the local symbol index. This is GSYM_CODE
// global symbol, or -2U for a constant. // for a global symbol, or CONSTANT_CODE for a constant.
unsigned int local_sym_index_; unsigned int local_sym_index_;
}; };
@ -501,7 +760,7 @@ class Output_section : public Output_data
const elfcpp::Shdr<size, big_endian>& shdr); const elfcpp::Shdr<size, big_endian>& shdr);
// Add generated data ODATA to this output section. // Add generated data ODATA to this output section.
virtual void void
add_output_section_data(Output_section_data* posd); add_output_section_data(Output_section_data* posd);
// Return the section name. // Return the section name.
@ -549,6 +808,58 @@ class Output_section : public Output_data
set_addralign(uint64_t v) set_addralign(uint64_t v)
{ this->addralign_ = 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 // Set the address of the Output_section. For a typical
// Output_section, there is nothing to do, but if there are any // Output_section, there is nothing to do, but if there are any
// Output_section_data objects we need to set the final addresses // 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_; elfcpp::Elf_Xword flags_;
// The section index. // The section index.
unsigned int out_shndx_; 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 // The input sections. This will be empty in cases where we don't
// need to keep track of them. // need to keep track of them.
Input_section_list input_sections_; Input_section_list input_sections_;
// The offset of the first entry in input_sections_. // The offset of the first entry in input_sections_.
off_t first_input_offset_; off_t first_input_offset_;
// Whether we permit adding data. // 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 // 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 class Output_section_symtab : public Output_section
{ {
public: 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 // The data is written out by Symbol_table::write_globals. We don't
// do anything here. // do anything here.
void void
do_write(Output_file*) 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 void
add_output_section_data(Output_section_data*) do_write(Output_file*)
{ abort(); } { }
}; };
// A special Output_section which holds a string table. // A special Output_section which holds a string table.
@ -727,11 +1071,6 @@ class Output_section_strtab : public Output_section
void void
do_write(Output_file*); 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: private:
Stringpool* contents_; Stringpool* contents_;
}; };

View file

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

View file

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

View file

@ -106,7 +106,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
abort(); abort();
} }
if (to->object() != NULL && to->object()->is_dynamic()) if (to->source() == Symbol::FROM_OBJECT
&& to->object()->is_dynamic())
tobits |= (1 << 1); tobits |= (1 << 1);
switch (to->shnum()) switch (to->shnum())
@ -174,6 +175,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
break; 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. // 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 // 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->name_ = name;
this->version_ = version; this->version_ = version;
this->symtab_index_ = 0;
this->dynsym_index_ = 0;
this->got_offset_ = 0; this->got_offset_ = 0;
this->type_ = type; this->type_ = type;
this->binding_ = binding; this->binding_ = binding;
@ -37,6 +39,7 @@ Symbol::init_fields(const char* name, const char* version,
this->is_target_special_ = false; this->is_target_special_ = false;
this->is_def_ = false; this->is_def_ = false;
this->is_forwarder_ = false; this->is_forwarder_ = false;
this->needs_dynsym_entry_ = false;
this->in_dyn_ = false; this->in_dyn_ = false;
this->has_got_offset_ = false; this->has_got_offset_ = false;
this->has_warning_ = 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. // Resolve the forwards from FROM, returning the real symbol.
Symbol* Symbol*
Symbol_table::resolve_forwards(Symbol* from) const Symbol_table::resolve_forwards(const Symbol* from) const
{ {
assert(from->is_forwarder()); assert(from->is_forwarder());
Unordered_map<Symbol*, Symbol*>::const_iterator p = Unordered_map<const Symbol*, Symbol*>::const_iterator p =
this->forwarders_.find(from); this->forwarders_.find(from);
assert(p != this->forwarders_.end()); assert(p != this->forwarders_.end());
return p->second; 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. Add their names to POOL. Return the new file offset.
off_t off_t
Symbol_table::finalize(off_t off, Stringpool* pool) Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
{ {
off_t ret; off_t ret;
assert(index != 0);
this->first_global_index_ = index;
if (this->size_ == 32) if (this->size_ == 32)
ret = this->sized_finalize<32>(off, pool); ret = this->sized_finalize<32>(index, off, pool);
else if (this->size_ == 64) else if (this->size_ == 64)
ret = this->sized_finalize<64>(off, pool); ret = this->sized_finalize<64>(index, off, pool);
else else
abort(); abort();
@ -980,15 +987,17 @@ Symbol_table::finalize(off_t off, Stringpool* pool)
template<int size> template<int size>
off_t 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); off = align_address(off, size >> 3);
this->offset_ = off; this->offset_ = off;
size_t orig_index = index;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size; const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
Symbol_table_type::iterator p = this->table_.begin(); for (Symbol_table_type::iterator p = this->table_.begin();
size_t count = 0; p != this->table_.end();
while (p != this->table_.end()) ++p)
{ {
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second); 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) if (os == NULL)
{ {
// We should be able to erase this symbol from the sym->set_symtab_index(-1U);
// 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;
continue; continue;
} }
@ -1082,13 +1086,13 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
} }
sym->set_value(value); sym->set_value(value);
sym->set_symtab_index(index);
pool->add(sym->name(), NULL); pool->add(sym->name(), NULL);
++count; ++index;
off += sym_size; off += sym_size;
++p;
} }
this->output_count_ = count; this->output_count_ = index - orig_index;
return off; return off;
} }
@ -1126,8 +1130,10 @@ Symbol_table::sized_write_globals(const Target*,
Output_file* of) const Output_file* of) const
{ {
const int sym_size = elfcpp::Elf_sizes<size>::sym_size; const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned char* psyms = of->get_output_view(this->offset_, unsigned int index = this->first_global_index_;
this->output_count_ * sym_size); 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; unsigned char* ps = psyms;
for (Symbol_table_type::const_iterator p = this->table_.begin(); for (Symbol_table_type::const_iterator p = this->table_.begin();
p != this->table_.end(); 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); Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
if (sym->symtab_index() == -1U)
continue;
unsigned int shndx; unsigned int shndx;
switch (sym->source()) switch (sym->source())
{ {
@ -1164,9 +1173,7 @@ Symbol_table::sized_write_globals(const Target*,
Relobj* relobj = static_cast<Relobj*>(symobj); Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff; off_t secoff;
Output_section* os = relobj->output_section(shnum, &secoff); Output_section* os = relobj->output_section(shnum, &secoff);
if (os == NULL) assert(os != NULL);
continue;
shndx = os->out_shndx(); shndx = os->out_shndx();
} }
} }
@ -1188,6 +1195,9 @@ Symbol_table::sized_write_globals(const Target*,
abort(); abort();
} }
assert(sym->symtab_index() == index);
++index;
elfcpp::Sym_write<size, big_endian> osym(ps); elfcpp::Sym_write<size, big_endian> osym(ps);
osym.put_st_name(sympool->get_offset(sym->name())); osym.put_st_name(sympool->get_offset(sym->name()));
osym.put_st_value(sym->value()); osym.put_st_value(sym->value());
@ -1200,7 +1210,9 @@ Symbol_table::sized_write_globals(const Target*,
ps += sym_size; 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. // Warnings functions.
@ -1254,7 +1266,7 @@ Warnings::note_warnings(Symbol_table* symtab)
// symbol for which has a warning. // symbol for which has a warning.
void 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()); assert(sym->has_warning());
Warning_table::const_iterator p = this->warnings_.find(sym->name()); Warning_table::const_iterator p = this->warnings_.find(sym->name());

View file

@ -173,6 +173,17 @@ class Symbol
set_forwarder() set_forwarder()
{ this->is_forwarder_ = true; } { 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. // Return whether this symbol was ever seen in a dynamic object.
bool bool
in_dyn() const in_dyn() const
@ -183,6 +194,46 @@ class Symbol
set_in_dyn() set_in_dyn()
{ this->in_dyn_ = true; } { 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. // Return whether this symbol has an entry in the GOT section.
bool bool
has_got_offset() const has_got_offset() const
@ -334,9 +385,22 @@ class Symbol
} in_output_segment; } in_output_segment;
} u_; } 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_ // 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_; unsigned int got_offset_;
// Symbol type. // Symbol type.
elfcpp::STT type_ : 4; elfcpp::STT type_ : 4;
// Symbol binding. // Symbol binding.
@ -360,6 +424,8 @@ class Symbol
// It forwards to the symbol found in the forwarders_ map of // It forwards to the symbol found in the forwarders_ map of
// Symbol_table. // Symbol_table.
bool is_forwarder_ : 1; 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. // True if we've seen this symbol in a dynamic object.
bool in_dyn_ : 1; bool in_dyn_ : 1;
// True if the symbol has an entry in the GOT section. // 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. // Issue a warning for a reference to SYM at LOCATION.
void void
issue_warning(Symbol* sym, const std::string& location) const; issue_warning(const Symbol* sym, const std::string& location) const;
private: private:
Warnings(const Warnings&); Warnings(const Warnings&);
@ -667,7 +733,7 @@ class Symbol_table
// Return the real symbol associated with the forwarder symbol FROM. // Return the real symbol associated with the forwarder symbol FROM.
Symbol* Symbol*
resolve_forwards(Symbol* from) const; resolve_forwards(const Symbol* from) const;
// Return the size of the symbols in the table. // Return the size of the symbols in the table.
int int
@ -705,15 +771,16 @@ class Symbol_table
// Possibly issue a warning for a reference to SYM at LOCATION which // Possibly issue a warning for a reference to SYM at LOCATION which
// is in OBJ. // is in OBJ.
void 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); } { this->warnings_.issue_warning(sym, location); }
// Finalize the symbol table after we have set the final addresses // Finalize the symbol table after we have set the final addresses
// of all the input sections. This sets the final symbol values and // of all the input sections. This sets the final symbol indexes,
// adds the names to *POOL. It records the file offset OFF, and // 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. // returns the new file offset.
off_t off_t
finalize(off_t, Stringpool*); finalize(unsigned int index, off_t off, Stringpool* pool);
// Write out the global symbols. // Write out the global symbols.
void void
@ -791,7 +858,7 @@ class Symbol_table
// Finalize symbols specialized for size. // Finalize symbols specialized for size.
template<int size> template<int size>
off_t off_t
sized_finalize(off_t, Stringpool*); sized_finalize(unsigned int, off_t, Stringpool*);
// Write globals specialized for size and endianness. // Write globals specialized for size and endianness.
template<int size, bool big_endian> template<int size, bool big_endian>
@ -828,6 +895,9 @@ class Symbol_table
// use in archive groups. // use in archive groups.
int saw_undefined_; 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 // The file offset within the output symtab section where we should
// write the table. // write the table.
off_t offset_; off_t offset_;
@ -843,7 +913,7 @@ class Symbol_table
Stringpool namepool_; Stringpool namepool_;
// Forwarding symbols. // 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 // 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 // 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 "elfcpp.h"
#include "object.h" #include "object.h"
#include "symtab.h" #include "symtab.h"
#include "reloc-types.h"
namespace gold 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 // This function implements the generic part of reloc scanning. This
// is an inline function which takes a class whose operator() // is an inline function which takes a class whose operator()
// implements the machine specific part of scanning. We do it this // implements the machine specific part of scanning. We do it this
@ -140,8 +121,9 @@ relocate_section(
Relocate relocate; Relocate relocate;
unsigned int local_count = relinfo->local_symbol_count; unsigned int local_count = relinfo->local_symbol_count;
typename elfcpp::Elf_types<size>::Elf_Addr *local_values = relinfo->values; const typename Sized_relobj<size, big_endian>::Local_values* local_values =
Symbol** global_syms = relinfo->symbols; relinfo->local_values;
const Symbol* const * global_syms = relinfo->symbols;
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) 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_sym = elfcpp::elf_r_sym<size>(r_info);
unsigned int r_type = elfcpp::elf_r_type<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; typename elfcpp::Elf_types<size>::Elf_Addr value;
if (r_sym < local_count) if (r_sym < local_count)
{ {
sym = NULL; sym = NULL;
value = local_values[r_sym]; value = (*local_values)[r_sym];
} }
else else
{ {
Symbol* gsym = global_syms[r_sym - local_count]; const Symbol* gsym = global_syms[r_sym - local_count];
assert(gsym != NULL); assert(gsym != NULL);
if (gsym->is_forwarder()) if (gsym->is_forwarder())
gsym = relinfo->symtab->resolve_forwards(gsym); gsym = relinfo->symtab->resolve_forwards(gsym);
sym = static_cast<Sized_symbol<size>*>(gsym); sym = static_cast<const Sized_symbol<size>*>(gsym);
value = sym->value(); value = sym->value();
} }