diff options
-rw-r--r-- | elfcpp/elfcpp.h | 52 | ||||
-rw-r--r-- | gold/Makefile.am | 2 | ||||
-rw-r--r-- | gold/Makefile.in | 2 | ||||
-rw-r--r-- | gold/i386.cc | 8 | ||||
-rw-r--r-- | gold/layout.cc | 11 | ||||
-rw-r--r-- | gold/object.cc | 88 | ||||
-rw-r--r-- | gold/object.h | 37 | ||||
-rw-r--r-- | gold/output.cc | 181 | ||||
-rw-r--r-- | gold/output.h | 367 | ||||
-rw-r--r-- | gold/po/POTFILES.in | 2 | ||||
-rw-r--r-- | gold/po/gold.pot | 76 | ||||
-rw-r--r-- | gold/reloc-types.h | 36 | ||||
-rw-r--r-- | gold/reloc.cc | 2 | ||||
-rw-r--r-- | gold/resolve.cc | 12 | ||||
-rw-r--r-- | gold/symtab.cc | 64 | ||||
-rw-r--r-- | gold/symtab.h | 88 | ||||
-rw-r--r-- | gold/target-reloc.h | 34 |
17 files changed, 884 insertions, 178 deletions
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index e106fab..afbd74d 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -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. diff --git a/gold/Makefile.am b/gold/Makefile.am index 12ec749..f76ee5b 100644 --- a/gold/Makefile.am +++ b/gold/Makefile.am @@ -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 \ diff --git a/gold/Makefile.in b/gold/Makefile.in index deef51c..560f481 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -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 \ diff --git a/gold/i386.cc b/gold/i386.cc index dc13dca..e6522e3 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -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, diff --git a/gold/layout.cc b/gold/layout.cc index bcb1029..f9f5548 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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(); diff --git a/gold/object.cc b/gold/object.cc index 1bfd969..74c1347 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -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); - } + this->local_indexes_[i] = -1U; + continue; + } - pool->add(pnames + sym.get_st_name(), NULL); - off += sym_size; - ++count; + 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()); diff --git a/gold/object.h b/gold/object.h index 6361356..b2f4706 100644 --- a/gold/object.h +++ b/gold/object.h @@ -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. diff --git a/gold/output.cc b/gold/output.cc index aba8ee1..0330384 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -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, @@ -1144,6 +1259,54 @@ Output_section::add_input_section<64, true>( 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>; template diff --git a/gold/output.h b/gold/output.h index 9763d74..c31640f 100644 --- a/gold/output.h +++ b/gold/output.h @@ -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*) { } +}; + +// 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); } - // We don't expect to see any input sections or data here. + // 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_; }; diff --git a/gold/po/POTFILES.in b/gold/po/POTFILES.in index d13ddf5..834e31a 100644 --- a/gold/po/POTFILES.in +++ b/gold/po/POTFILES.in @@ -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 diff --git a/gold/po/gold.pot b/gold/po/gold.pot index c002c5c..b5725e5 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -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 "" diff --git a/gold/reloc-types.h b/gold/reloc-types.h new file mode 100644 index 0000000..62538d6 --- /dev/null +++ b/gold/reloc-types.h @@ -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) diff --git a/gold/reloc.cc b/gold/reloc.cc index dd3eef1..ce6af0b 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -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; diff --git a/gold/resolve.cc b/gold/resolve.cc index 86645a4..2b6d65c 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -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 diff --git a/gold/symtab.cc b/gold/symtab.cc index 9279d26..92d5583 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -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()); diff --git a/gold/symtab.h b/gold/symtab.h index e972600..06a4b6b 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -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 diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 7069278..5b057ac 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -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(); } |