diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 166 | ||||
-rw-r--r-- | gold/copy-relocs.cc | 5 | ||||
-rw-r--r-- | gold/dwarf_reader.cc | 27 | ||||
-rw-r--r-- | gold/dwarf_reader.h | 9 | ||||
-rw-r--r-- | gold/dynobj.cc | 64 | ||||
-rw-r--r-- | gold/dynobj.h | 16 | ||||
-rw-r--r-- | gold/ehframe.cc | 7 | ||||
-rw-r--r-- | gold/gold.cc | 3 | ||||
-rw-r--r-- | gold/i386.cc | 54 | ||||
-rw-r--r-- | gold/layout.cc | 153 | ||||
-rw-r--r-- | gold/layout.h | 34 | ||||
-rw-r--r-- | gold/object.cc | 236 | ||||
-rw-r--r-- | gold/object.h | 149 | ||||
-rw-r--r-- | gold/output.cc | 71 | ||||
-rw-r--r-- | gold/output.h | 44 | ||||
-rw-r--r-- | gold/reloc.cc | 15 | ||||
-rw-r--r-- | gold/resolve.cc | 91 | ||||
-rw-r--r-- | gold/sparc.cc | 22 | ||||
-rw-r--r-- | gold/symtab.cc | 223 | ||||
-rw-r--r-- | gold/symtab.h | 120 | ||||
-rw-r--r-- | gold/target-reloc.h | 21 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 28 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 91 | ||||
-rw-r--r-- | gold/testsuite/binary_unittest.cc | 14 | ||||
-rw-r--r-- | gold/testsuite/many_sections_test.cc | 37 | ||||
-rw-r--r-- | gold/x86_64.cc | 60 |
26 files changed, 1402 insertions, 358 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index a230f59..877d828 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,169 @@ +2008-04-19 Ian Lance Taylor <iant@google.com> + + * object.cc (Xindex::initialize_symtab_xindex): New function. + (Xindex::read_symtab_xindex): New function. + (Xindex::sym_xindex_to_shndx): New function. + (Sized_relobj::find_symtab): Pick up SHT_SYMTAB_SHNDX section if + available. + (Sized_relobj::do_initialize_xindex): New function. + (Sized_relobj::do_read_symbols): Adjust section links. + (Sized_relobj::symbol_section_and_value): Add is_ordinary + parameter. Change all callers. + (Sized_relobj::include_section_group): Adjust section links and + symbol section indexes. + (Sized_relobj::do_layout): Adjust section links. + (Sized_relobj::do_count_local_symbols): Adjust section links and + symbol section indexes. + (Sized_relobj::do_finalize_local_symbols): Distinguish between + ordinary and special symbols. + (Sized_relobj::write_local_symbols): Add symtab_xindex and + dynsym_xindex parameters. Change all callers. Adjust section + links. Use SHN_XINDEX when needed. + (Sized_relobj::get_symbol_location_info): Adjust section links. + Don't get fooled by special symbols. + * object.h (class Xindex): Define. + (class Object): Add xindex_ parameter. Declare virtual functoin + do_initialize_xindex. + (Object::adjust_sym_shndx): New function. + (Object::set_xindex): New protected function. + (class Symbol_value): Add is_ordinary_shndx_ field. + (Symbol_value::Symbol_value): Initialize is_ordinary_shndx_. + (Symbol_value::value): Assert ordinary section. + (Symbol_value::initialize_input_to_output_map): Likewise. + (Symbol_value::set_input_shndx): Add is_ordinary parameter. + Change all callers. + (Symbol_value::input_shndx): Add is_ordinary parameter. Change + all callers. + (class Sized_relobj): Update declarations. + (Sized_relobj::local_symbol_input_shndx): Add is_ordinary + parameter. Change all callers. + (Sized_relobj::adjust_shndx): New function. + * dynobj.cc (Sized_dynobj::Sized_dynobj): Initialize dynsym_shndx_ + field. + (Sized_dynobj::find_dynsym_sections): Remove pdynsym_shndx + parameter. Change all callers. Pick up SHT_DYNSYM_SHNDX section + for SHT_DYNSYM section if available. Set dynsym_shndx_ field. + (Sized_dynobj::read_dynsym_section): Adjust section links. + (Sized_dynobj::read_dynamic): Likewise. + (Sized_dynobj::do_read_symbols): Use dynsym_shndx_ field. Adjust + section links. + (Sized_dynobj::do_initialize_xindex): New function. + * dynobj.h (class Sized_dynobj): Add dynsym_shndx_ field. Declare + do_initialize_xindex. + (Sized_dynobj::adjust_shndx): New function. + * layout.cc (Layout::Layout): Initialize symtab_xindex_ and + dynsym_xindex_ fields. + (Layout::finalize): Add a call to set_section_indexes before + creating the symtab sections. + (Layout::set_section_indexes): Don't do anything if the section + already has a section index. + (Layout::create_symtab_sections): Add shnum parameter. Change + caller. Create .symtab_shndx section if needed. + (Layout::create_shdrs): Add shstrtab_section parameter. Change + caller. + (Layout::allocated_output_section_count): New function. + (Layout::create_dynamic_symtab): Create .dynsym_shndx section if + needed. + * layout.h (class Layout): Add symtab_xindex_ and dynsym_xindex_ + fields. Update declarations. + (Layout::symtab_xindex): New function. + (Layout::dynsym_xindex): New function. + (class Write_symbols_task): Add layout_ field. + (Write_symbols_task::Write_symbols_task): Add layout parameter. + Change caller. + * output.cc (Output_section_headers::Output_section_headers): Add + shstrtab_section parameter. Change all callers. + (Output_section_headers::do_sized_write): Store overflow values + for section count and section string table section index in + section header zero. + (Output_file_header::do_sized_write): Check for overflow of + section count and section string table section index. + (Output_symtab_xindex::do_write): New function. + (Output_symtab_xindex::endian_do_write): New function. + * output.h (class Output_section_headers): Add shstrtab_section_. + Update declarations. + (class Output_symtab_xindex): Define. + (Output_section::has_out_shndx): New function. + * symtab.cc (Symbol::init_fields): Initialize is_ordinary_shndx_ + field. + (Symbol::init_base): Add st_shndx and is_ordinary parameters. + Change all callers. + (Sized_symbol::init): Likewise. + (Symbol::output_section): Check for ordinary symbol. + (Symbol_table::add_from_object): Remove orig_sym parameter. Add + st_shndx, is_ordinary, and orig_st_shndx parameters. Change all + callers. + (Symbol_table::add_from_relobj): Add symndx_offset parameter. + Change all callers. Simplify handling of symbols from sections + not included in the link. + (Symbol_table::add_from_dynobj): Handle ordinary symbol + distinction. + (Weak_alias_sorter::operator()): Assert that symbols are + ordinary. + (Symbol_table::sized_finalize_symbol): Handle ordinary symbol + distinction. + (Symbol_table::write_globals): Add symtab_xindex and dynsym_xindex + parameters. Change all callers. + (Symbol_table::sized_write_globals): Likewise. Handle ordinary + symbol distinction. Use SHN_XINDEX when needed. + (Symbol_table::write_section_symbol): Add symtab_xindex + parameter. Change all callers. + (Symbol_table::sized_write_section_symbol): Likewise. Use + SHN_XINDEX when needed. + * symtab.h (class Symbol): Add is_ordinary_shndx_ field. Update + declarations. + (Symbol::shndx): Add is_ordinary parameter. Change all callers. + (Symbol::is_defined): Check is_ordinary. + (Symbol::is_undefined, Symbol::is_weak_undefined): Likewise. + (Symbol::is_absolute, Symbol::is_common): Likewise. + (class Sized_symbol): Update declarations. + (class Symbol_table): Update declarations. + * resolve.cc (Symbol::override_base): Add st_shndx and is_ordinary + parameters. Change all callers. + (Sized_symbol::override): Likewise. + (Symbol_table::override): Likewise. + (symbol_to_bits): Add is_ordinary parameter. Change all callers. + (Symbol_table::resolve): Remove orig_sym parameter. Add st_shndx, + is_ordinary, and orig_st_shndx parameters. Change all callers. + * copy-relocs.cc (Copy_relocs::emit_copy_reloc): Require symbol + to be in an ordinary section. + * dwarf_reader.cc (Sized_dwarf_line_info::symbol_section): Add + object and is_ordinary parameters. Change all callers. + (Sized_dwarf_line_info::read_relocs): Add object parameter. + Change all callers. Don't add undefined or non-ordinary symbols + to reloc_map_. + (Sized_dwarf_line_info::read_line_mappings): Add object parameter. + Change all callers. + * dwarf_reader.h (class Sized_dwarf_line_info): Update + declarations. + * ehframe.cc (Eh_frame::read_fde): Check for ordinary symbol. + * reloc.cc (Sized_relobj::do_read_relocs): Adjust section links. + (Sized_relobj::relocate_sections): Likewise. + * target-reloc.h (scan_relocs): Adjust section symbol index. + (scan_relocatable_relocs): Likewise. + * i386.cc (Scan::local): Check for ordinary symbols. + * sparc.cc (Scan::local): Likewise. + * x86_64.cc (Scan::local): Likewise. + * testsuite/binary_unittest.cc (Sized_binary_test): Update calls + to symbol_section_and_value. + * testsuite/many_sections_test.cc: New file. + * testsuite/Makefile.am (BUILT_SOURCES): Define. + (check_PROGRAMS): Add many_sections_test. + (many_sections_test_SOURCES): Define. + (many_sections_test_DEPENDENCIES): Define. + (many_sections_test_LDFLAGS): Define. + (BUILT_SOURCES): Add many_sections_define.h. + (many_sections_define.h): New target. + (BUILT_SOURCES): Add many_sections_check.h. + (many_sections_check.h): New target. + (check_PROGRAMS): Add many_sections_r_test. + (many_sections_r_test_SOURCES): Define. + (many_sections_r_test_DEPENDENCIES): Define. + (many_sections_r_test_LDFLAGS): Define. + (many_sections_r_test_LDADD): Define. + (many_sections_r_test.o): New target. + * testsuite/Makefile.in: Rebuild. + 2008-04-17 Cary Coutant <ccoutant@google.com> * errors.cc (Errors::info): New function. diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 1e9705e..3df50c8 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -118,8 +118,11 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc( // that. Then we reduce that alignment if the symbol is not aligned // within the section. gold_assert(sym->is_from_dynobj()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + gold_assert(is_ordinary); typename elfcpp::Elf_types<size>::Elf_WXword addralign = - sym->object()->section_addralign(sym->shndx()); + sym->object()->section_addralign(shndx); typename Sized_symbol<size>::Value_type value = sym->value(); while ((value & (addralign - 1)) != 0) diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc index e345ff8..d3faeeb 100644 --- a/gold/dwarf_reader.cc +++ b/gold/dwarf_reader.cc @@ -175,7 +175,7 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object, // Now that we have successfully read all the data, parse the debug // info. this->data_valid_ = true; - this->read_line_mappings(read_shndx); + this->read_line_mappings(object, read_shndx); } // Read the DWARF header. @@ -542,21 +542,23 @@ Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr template<int size, bool big_endian> unsigned int Sized_dwarf_line_info<size, big_endian>::symbol_section( + Object* object, unsigned int sym, - typename elfcpp::Elf_types<size>::Elf_Addr* value) + typename elfcpp::Elf_types<size>::Elf_Addr* value, + bool* is_ordinary) { const int symsize = elfcpp::Elf_sizes<size>::sym_size; gold_assert(sym * symsize < this->symtab_buffer_size_); elfcpp::Sym<size, big_endian> elfsym(this->symtab_buffer_ + sym * symsize); *value = elfsym.get_st_value(); - return elfsym.get_st_shndx(); + return object->adjust_sym_shndx(sym, elfsym.get_st_shndx(), is_ordinary); } // Read the relocations into a Reloc_map. template<int size, bool big_endian> void -Sized_dwarf_line_info<size, big_endian>::read_relocs() +Sized_dwarf_line_info<size, big_endian>::read_relocs(Object* object) { if (this->symtab_buffer_ == NULL) return; @@ -566,8 +568,16 @@ Sized_dwarf_line_info<size, big_endian>::read_relocs() while ((reloc_offset = this->track_relocs_.next_offset()) != -1) { const unsigned int sym = this->track_relocs_.next_symndx(); - const unsigned int shndx = this->symbol_section(sym, &value); - this->reloc_map_[reloc_offset] = std::make_pair(shndx, value); + + bool is_ordinary; + const unsigned int shndx = this->symbol_section(object, sym, &value, + &is_ordinary); + + // There is no reason to record non-ordinary section indexes, or + // SHN_UNDEF, because they will never match the real section. + if (is_ordinary && shndx != elfcpp::SHN_UNDEF) + this->reloc_map_[reloc_offset] = std::make_pair(shndx, value); + this->track_relocs_.advance(reloc_offset + 1); } } @@ -576,11 +586,12 @@ Sized_dwarf_line_info<size, big_endian>::read_relocs() template<int size, bool big_endian> void -Sized_dwarf_line_info<size, big_endian>::read_line_mappings(off_t shndx) +Sized_dwarf_line_info<size, big_endian>::read_line_mappings(Object* object, + off_t shndx) { gold_assert(this->data_valid_ == true); - read_relocs(); + this->read_relocs(object); while (this->buffer_ < this->buffer_end_) { const unsigned char* lineptr = this->buffer_; diff --git a/gold/dwarf_reader.h b/gold/dwarf_reader.h index 2d85765..9c6b175 100644 --- a/gold/dwarf_reader.h +++ b/gold/dwarf_reader.h @@ -101,17 +101,18 @@ class Sized_dwarf_line_info : public Dwarf_line_info // If SHNDX is non-negative, only store debug information that // pertains to the specified section. void - read_line_mappings(off_t shndx); + read_line_mappings(Object*, off_t shndx); // Reads the relocation section associated with .debug_line and // stores relocation information in reloc_map_. void - read_relocs(); + read_relocs(Object*); // Looks in the symtab to see what section a symbol is in. unsigned int - symbol_section(unsigned int sym, - typename elfcpp::Elf_types<size>::Elf_Addr* value); + symbol_section(Object*, unsigned int sym, + typename elfcpp::Elf_types<size>::Elf_Addr* value, + bool* is_ordinary); // Reads the DWARF2/3 header for this line info. Each takes as input // a starting buffer position, and returns the ending position. diff --git a/gold/dynobj.cc b/gold/dynobj.cc index e593b89..89186ad 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -72,7 +72,8 @@ Sized_dynobj<size, big_endian>::Sized_dynobj( off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr) : Dynobj(name, input_file, offset), - elf_file_(this, ehdr) + elf_file_(this, ehdr), + dynsym_shndx_(-1U) { } @@ -98,18 +99,18 @@ template<int size, bool big_endian> void Sized_dynobj<size, big_endian>::find_dynsym_sections( const unsigned char* pshdrs, - unsigned int* pdynsym_shndx, unsigned int* pversym_shndx, unsigned int* pverdef_shndx, unsigned int* pverneed_shndx, unsigned int* pdynamic_shndx) { - *pdynsym_shndx = -1U; *pversym_shndx = -1U; *pverdef_shndx = -1U; *pverneed_shndx = -1U; *pdynamic_shndx = -1U; + unsigned int xindex_shndx = 0; + unsigned int xindex_link = 0; const unsigned int shnum = this->shnum(); const unsigned char* p = pshdrs; for (unsigned int i = 0; i < shnum; ++i, p += This::shdr_size) @@ -120,7 +121,15 @@ Sized_dynobj<size, big_endian>::find_dynsym_sections( switch (shdr.get_sh_type()) { case elfcpp::SHT_DYNSYM: - pi = pdynsym_shndx; + this->dynsym_shndx_ = i; + if (xindex_shndx > 0 && xindex_link == i) + { + Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset()); + xindex->read_symtab_xindex<size, big_endian>(this, xindex_shndx, + pshdrs); + this->set_xindex(xindex); + } + pi = NULL; break; case elfcpp::SHT_GNU_versym: pi = pversym_shndx; @@ -134,6 +143,18 @@ Sized_dynobj<size, big_endian>::find_dynsym_sections( case elfcpp::SHT_DYNAMIC: pi = pdynamic_shndx; break; + case elfcpp::SHT_SYMTAB_SHNDX: + xindex_shndx = i; + xindex_link = this->adjust_shndx(shdr.get_sh_link()); + if (xindex_link == this->dynsym_shndx_) + { + Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset()); + xindex->read_symtab_xindex<size, big_endian>(this, xindex_shndx, + pshdrs); + this->set_xindex(xindex); + } + pi = NULL; + break; default: pi = NULL; break; @@ -178,9 +199,9 @@ Sized_dynobj<size, big_endian>::read_dynsym_section( gold_assert(shdr.get_sh_type() == type); - if (shdr.get_sh_link() != link) + if (this->adjust_shndx(shdr.get_sh_link()) != link) this->error(_("unexpected link in section %u header: %u != %u"), - shndx, shdr.get_sh_link(), link); + shndx, this->adjust_shndx(shdr.get_sh_link()), link); *view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false); @@ -210,7 +231,7 @@ Sized_dynobj<size, big_endian>::read_dynamic(const unsigned char* pshdrs, const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(), dynamic_size, true, false); - const unsigned int link = dynamicshdr.get_sh_link(); + const unsigned int link = this->adjust_shndx(dynamicshdr.get_sh_link()); if (link != strtab_shndx) { if (link >= this->shnum()) @@ -291,13 +312,12 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) const unsigned char* const pshdrs = sd->section_headers->data(); - unsigned int dynsym_shndx; unsigned int versym_shndx; unsigned int verdef_shndx; unsigned int verneed_shndx; unsigned int dynamic_shndx; - this->find_dynsym_sections(pshdrs, &dynsym_shndx, &versym_shndx, - &verdef_shndx, &verneed_shndx, &dynamic_shndx); + this->find_dynsym_sections(pshdrs, &versym_shndx, &verdef_shndx, + &verneed_shndx, &dynamic_shndx); unsigned int strtab_shndx = -1U; @@ -307,10 +327,11 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) sd->symbol_names = NULL; sd->symbol_names_size = 0; - if (dynsym_shndx != -1U) + if (this->dynsym_shndx_ != -1U) { // Get the dynamic symbols. - typename This::Shdr dynsymshdr(pshdrs + dynsym_shndx * This::shdr_size); + typename This::Shdr dynsymshdr(pshdrs + + this->dynsym_shndx_ * This::shdr_size); gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM); sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(), @@ -320,7 +341,7 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) convert_to_section_size_type(dynsymshdr.get_sh_size()); // Get the symbol names. - strtab_shndx = dynsymshdr.get_sh_link(); + strtab_shndx = this->adjust_shndx(dynsymshdr.get_sh_link()); if (strtab_shndx >= this->shnum()) { this->error(_("invalid dynamic symbol table name index: %u"), @@ -346,8 +367,8 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) unsigned int dummy; this->read_dynsym_section(pshdrs, versym_shndx, elfcpp::SHT_GNU_versym, - dynsym_shndx, &sd->versym, &sd->versym_size, - &dummy); + this->dynsym_shndx_, + &sd->versym, &sd->versym_size, &dummy); // We require that the version definition and need section link // to the same string table as the dynamic symbol table. This @@ -375,6 +396,19 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) sd->symbol_names_size); } +// Return the Xindex structure to use for object with lots of +// sections. + +template<int size, bool big_endian> +Xindex* +Sized_dynobj<size, big_endian>::do_initialize_xindex() +{ + gold_assert(this->dynsym_shndx_ != -1U); + Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset()); + xindex->initialize_symtab_xindex<size, big_endian>(this, this->dynsym_shndx_); + return xindex; +} + // Lay out the input sections for a dynamic object. We don't want to // include sections from a dynamic object, so all that we actually do // here is check for .gnu.warning sections. diff --git a/gold/dynobj.h b/gold/dynobj.h index bab15cd..bd5e12d 100644 --- a/gold/dynobj.h +++ b/gold/dynobj.h @@ -221,6 +221,10 @@ class Sized_dynobj : public Dynobj do_section_addralign(unsigned int shndx) { return this->elf_file_.section_addralign(shndx); } + // Return the Xindex structure to use. + Xindex* + do_initialize_xindex(); + private: // For convenience. typedef Sized_dynobj<size, big_endian> This; @@ -230,11 +234,19 @@ class Sized_dynobj : public Dynobj typedef elfcpp::Shdr<size, big_endian> Shdr; typedef elfcpp::Dyn<size, big_endian> Dyn; + // Adjust a section index if necessary. + unsigned int + adjust_shndx(unsigned int shndx) + { + if (shndx >= elfcpp::SHN_LORESERVE) + shndx += this->elf_file_.large_shndx_offset(); + return shndx; + } + // Find the dynamic symbol table and the version sections, given the // section headers. void find_dynsym_sections(const unsigned char* pshdrs, - unsigned int* pdynshm_shndx, unsigned int* pversym_shndx, unsigned int* pverdef_shndx, unsigned int* pverneed_shndx, @@ -274,6 +286,8 @@ class Sized_dynobj : public Dynobj // General access to the ELF file. elfcpp::Elf_file<size, big_endian, Object> elf_file_; + // The section index of the dynamic symbol table. + unsigned int dynsym_shndx_; }; // A base class for Verdef and Verneed_version which just handles the diff --git a/gold/ehframe.cc b/gold/ehframe.cc index 4ec29f6..5061f80 100644 --- a/gold/ehframe.cc +++ b/gold/ehframe.cc @@ -971,9 +971,12 @@ Eh_frame::read_fde(Sized_relobj<size, big_endian>* object, if (symndx >= symbols_size / sym_size) return false; elfcpp::Sym<size, big_endian> sym(symbols + symndx * sym_size); - fde_shndx = sym.get_st_shndx(); + bool is_ordinary; + fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(), + &is_ordinary); - if (fde_shndx != elfcpp::SHN_UNDEF + if (is_ordinary + && fde_shndx != elfcpp::SHN_UNDEF && fde_shndx < object->shnum() && !object->is_section_included(fde_shndx)) { diff --git a/gold/gold.cc b/gold/gold.cc index d150db7..54b0828 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -310,7 +310,8 @@ queue_final_tasks(const General_options& options, // Queue a task to write out the symbol table. final_blocker->add_blocker(); - workqueue->queue(new Write_symbols_task(symtab, + workqueue->queue(new Write_symbols_task(layout, + symtab, input_objects, layout->sympool(), layout->dynpool(), diff --git a/gold/i386.cc b/gold/i386.cc index 3e24836..dcd4c03 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -881,18 +881,24 @@ Target_i386::Scan::local(const General_options&, if (parameters->options().output_is_position_independent()) { Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); if (lsym.get_st_type() != elfcpp::STT_SECTION) - { - unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); - rel_dyn->add_local(object, r_sym, r_type, output_section, - data_shndx, reloc.get_r_offset()); - } + rel_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset()); else { gold_assert(lsym.get_st_value() == 0); - rel_dyn->add_local_section(object, lsym.get_st_shndx(), - r_type, output_section, - data_shndx, reloc.get_r_offset()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, + &is_ordinary); + if (!is_ordinary) + object->error(_("section symbol %u has bad shndx %u"), + r_sym, shndx); + else + rel_dyn->add_local_section(object, shndx, + r_type, output_section, + data_shndx, reloc.get_r_offset()); } } break; @@ -975,11 +981,17 @@ Target_i386::Scan::local(const General_options&, Output_data_got<32, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); - got->add_local_pair_with_rel(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_PAIR, - target->rel_dyn_section(layout), - elfcpp::R_386_TLS_DTPMOD32, 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rel(object, r_sym, shndx, + GOT_TYPE_TLS_PAIR, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DTPMOD32, 0); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -993,11 +1005,17 @@ Target_i386::Scan::local(const General_options&, Output_data_got<32, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); - got->add_local_pair_with_rel(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_DESC, - target->rel_dyn_section(layout), - elfcpp::R_386_TLS_DESC, 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rel(object, r_sym, shndx, + GOT_TYPE_TLS_DESC, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DESC, 0); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); diff --git a/gold/layout.cc b/gold/layout.cc index fa0d4c8..a3bcf21 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -76,15 +76,33 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task) // Layout methods. Layout::Layout(const General_options& options, Script_options* script_options) - : options_(options), script_options_(script_options), namepool_(), - sympool_(), dynpool_(), signatures_(), - section_name_map_(), segment_list_(), section_list_(), - unattached_section_list_(), sections_are_attached_(false), - special_output_list_(), section_headers_(NULL), tls_segment_(NULL), - symtab_section_(NULL), dynsym_section_(NULL), dynamic_section_(NULL), - dynamic_data_(NULL), eh_frame_section_(NULL), eh_frame_data_(NULL), - added_eh_frame_data_(false), eh_frame_hdr_section_(NULL), - build_id_note_(NULL), group_signatures_(), output_file_size_(-1), + : options_(options), + script_options_(script_options), + namepool_(), + sympool_(), + dynpool_(), + signatures_(), + section_name_map_(), + segment_list_(), + section_list_(), + unattached_section_list_(), + sections_are_attached_(false), + special_output_list_(), + section_headers_(NULL), + tls_segment_(NULL), + symtab_section_(NULL), + symtab_xindex_(NULL), + dynsym_section_(NULL), + dynsym_xindex_(NULL), + dynamic_section_(NULL), + dynamic_data_(NULL), + eh_frame_section_(NULL), + eh_frame_data_(NULL), + added_eh_frame_data_(false), + eh_frame_hdr_section_(NULL), + build_id_note_(NULL), + group_signatures_(), + output_file_size_(-1), input_requires_executable_stack_(false), input_with_gnu_stack_note_(false), input_without_gnu_stack_note_(false), @@ -1149,8 +1167,12 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // sections. off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS); + // Set the section indexes of all unallocated sections seen so far, + // in case any of them are somehow referenced by a symbol. + shndx = this->set_section_indexes(shndx); + // Create the symbol table sections. - this->create_symtab_sections(input_objects, symtab, &off); + this->create_symtab_sections(input_objects, symtab, shndx, &off); if (!parameters->doing_static_link()) this->assign_local_dynsym_offsets(input_objects); @@ -1165,11 +1187,12 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // don't have to wait for the input sections. off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS); - // Now that all sections have been created, set the section indexes. + // Now that all sections have been created, set the section indexes + // for any sections which haven't been done yet. shndx = this->set_section_indexes(shndx); // Create the section table header. - this->create_shdrs(&off); + this->create_shdrs(shstrtab_section, &off); // If there are no sections which require postprocessing, we can // handle the section names now, and avoid a resize later. @@ -1816,18 +1839,15 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass) unsigned int Layout::set_section_indexes(unsigned int shndx) { - const bool output_is_object = parameters->options().relocatable(); for (Section_list::iterator p = this->unattached_section_list_.begin(); p != this->unattached_section_list_.end(); ++p) { - // In a relocatable link, we already did group sections. - if (output_is_object - && (*p)->type() == elfcpp::SHT_GROUP) - continue; - - (*p)->set_out_shndx(shndx); - ++shndx; + if (!(*p)->has_out_shndx()) + { + (*p)->set_out_shndx(shndx); + ++shndx; + } } return shndx; } @@ -1893,11 +1913,12 @@ Layout::count_local_symbols(const Task* task, // Create the symbol table sections. Here we also set the final // values of the symbols. At this point all the loadable sections are -// fully laid out. +// fully laid out. SHNUM is the number of sections so far. void Layout::create_symtab_sections(const Input_objects* input_objects, Symbol_table* symtab, + unsigned int shnum, off_t* poff) { int symsize; @@ -1988,6 +2009,38 @@ Layout::create_symtab_sections(const Input_objects* input_objects, align); osymtab->add_output_section_data(pos); + // We generate a .symtab_shndx section if we have more than + // SHN_LORESERVE sections. Technically it is possible that we + // don't need one, because it is possible that there are no + // symbols in any of sections with indexes larger than + // SHN_LORESERVE. That is probably unusual, though, and it is + // easier to always create one than to compute section indexes + // twice (once here, once when writing out the symbols). + if (shnum >= elfcpp::SHN_LORESERVE) + { + const char* symtab_xindex_name = this->namepool_.add(".symtab_shndx", + false, NULL); + Output_section* osymtab_xindex = + this->make_output_section(symtab_xindex_name, + elfcpp::SHT_SYMTAB_SHNDX, 0); + + size_t symcount = (off - startoff) / symsize; + this->symtab_xindex_ = new Output_symtab_xindex(symcount); + + osymtab_xindex->add_output_section_data(this->symtab_xindex_); + + osymtab_xindex->set_link_section(osymtab); + osymtab_xindex->set_addralign(4); + osymtab_xindex->set_entsize(4); + + osymtab_xindex->set_after_input_sections(); + + // This tells the driver code to wait until the symbol table + // has written out before writing out the postprocessing + // sections, including the .symtab_shndx section. + this->any_postprocessing_sections_ = true; + } + const char* strtab_name = this->namepool_.add(".strtab", false, NULL); Output_section* ostrtab = this->make_output_section(strtab_name, elfcpp::SHT_STRTAB, @@ -2035,14 +2088,15 @@ Layout::create_shstrtab() // offset. void -Layout::create_shdrs(off_t* poff) +Layout::create_shdrs(const Output_section* shstrtab_section, off_t* poff) { Output_section_headers* oshdrs; oshdrs = new Output_section_headers(this, &this->segment_list_, &this->section_list_, &this->unattached_section_list_, - &this->namepool_); + &this->namepool_, + shstrtab_section); off_t off = align_address(*poff, oshdrs->addralign()); oshdrs->set_address_and_file_offset(0, off); off += oshdrs->data_size(); @@ -2050,6 +2104,19 @@ Layout::create_shdrs(off_t* poff) this->section_headers_ = oshdrs; } +// Count the allocated sections. + +size_t +Layout::allocated_output_section_count() const +{ + size_t section_count = 0; + for (Segment_list::const_iterator p = this->segment_list_.begin(); + p != this->segment_list_.end(); + ++p) + section_count += (*p)->output_section_count(); + return section_count; +} + // Create the dynamic symbol table. void @@ -2093,8 +2160,6 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, unsigned int local_symcount = index; *plocal_dynamic_count = local_symcount; - // FIXME: We have to tell set_dynsym_indexes whether the - // -E/--export-dynamic option was used. index = symtab->set_dynsym_indexes(index, pdynamic_symbols, &this->dynpool_, pversions); @@ -2135,6 +2200,37 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym); odyn->add_constant(elfcpp::DT_SYMENT, symsize); + // If there are more than SHN_LORESERVE allocated sections, we + // create a .dynsym_shndx section. It is possible that we don't + // need one, because it is possible that there are no dynamic + // symbols in any of the sections with indexes larger than + // SHN_LORESERVE. This is probably unusual, though, and at this + // time we don't know the actual section indexes so it is + // inconvenient to check. + if (this->allocated_output_section_count() >= elfcpp::SHN_LORESERVE) + { + Output_section* dynsym_xindex = + this->choose_output_section(NULL, ".dynsym_shndx", + elfcpp::SHT_SYMTAB_SHNDX, + elfcpp::SHF_ALLOC, + false); + + this->dynsym_xindex_ = new Output_symtab_xindex(index); + + dynsym_xindex->add_output_section_data(this->dynsym_xindex_); + + dynsym_xindex->set_link_section(dynsym); + dynsym_xindex->set_addralign(4); + dynsym_xindex->set_entsize(4); + + dynsym_xindex->set_after_input_sections(); + + // This tells the driver code to wait until the symbol table has + // written out before writing out the postprocessing sections, + // including the .dynsym_shndx section. + this->any_postprocessing_sections_ = true; + } + // Create the dynamic string table section. Output_section* dynstr = this->choose_output_section(NULL, ".dynstr", @@ -2766,7 +2862,7 @@ Layout::write_data(const Symbol_table* symtab, Output_file* of) const gold_assert(index > 0 && index != -1U); off_t off = (symtab_section->offset() + index * symtab_section->entsize()); - symtab->write_section_symbol(*p, of, off); + symtab->write_section_symbol(*p, this->symtab_xindex_, of, off); } } } @@ -2783,7 +2879,7 @@ Layout::write_data(const Symbol_table* symtab, Output_file* of) const gold_assert(index > 0 && index != -1U); off_t off = (dynsym_section->offset() + index * dynsym_section->entsize()); - symtab->write_section_symbol(*p, of, off); + symtab->write_section_symbol(*p, this->dynsym_xindex_, of, off); } } @@ -3014,7 +3110,8 @@ void Write_symbols_task::run(Workqueue*) { this->symtab_->write_globals(this->input_objects_, this->sympool_, - this->dynpool_, this->of_); + this->dynpool_, this->layout_->symtab_xindex(), + this->layout_->dynsym_xindex(), this->of_); } // Write_after_input_sections_task methods. diff --git a/gold/layout.h b/gold/layout.h index 13fafd6..efa8b61 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -46,6 +46,7 @@ class Output_section_headers; class Output_segment; class Output_data; class Output_data_dynamic; +class Output_symtab_xindex; class Eh_frame; class Target; @@ -193,6 +194,18 @@ class Layout dynpool() const { return &this->dynpool_; } + // Return the symtab_xindex section used to hold large section + // indexes for the normal symbol table. + Output_symtab_xindex* + symtab_xindex() const + { return this->symtab_xindex_; } + + // Return the dynsym_xindex section used to hold large section + // indexes for the dynamic symbol table. + Output_symtab_xindex* + dynsym_xindex() const + { return this->dynsym_xindex_; } + // Return whether a section is a .gnu.linkonce section, given the // section name. static inline bool @@ -407,7 +420,8 @@ class Layout // Create the output sections for the symbol table. void - create_symtab_sections(const Input_objects*, Symbol_table*, off_t*); + create_symtab_sections(const Input_objects*, Symbol_table*, + unsigned int, off_t*); // Create the .shstrtab section. Output_section* @@ -415,7 +429,7 @@ class Layout // Create the section header table. void - create_shdrs(off_t*); + create_shdrs(const Output_section* shstrtab_section, off_t*); // Create the dynamic symbol table. void @@ -470,6 +484,10 @@ class Layout static const char* linkonce_output_name(const char* name, size_t* plen); + // Return the number of allocated output sections. + size_t + allocated_output_section_count() const; + // Return the output section for NAME, TYPE and FLAGS. Output_section* get_output_section(const char* name, Stringpool::Key name_key, @@ -589,8 +607,12 @@ class Layout Output_segment* tls_segment_; // The SHT_SYMTAB output section. Output_section* symtab_section_; + // The SHT_SYMTAB_SHNDX for the regular symbol table if there is one. + Output_symtab_xindex* symtab_xindex_; // The SHT_DYNSYM output section if there is one. Output_section* dynsym_section_; + // The SHT_SYMTAB_SHNDX for the dynamic symbol table if there is one. + Output_symtab_xindex* dynsym_xindex_; // The SHT_DYNAMIC output section if there is one. Output_section* dynamic_section_; // The dynamic data which goes into dynamic_section_. @@ -702,12 +724,13 @@ class Write_data_task : public Task class Write_symbols_task : public Task { public: - Write_symbols_task(const Symbol_table* symtab, + Write_symbols_task(const Layout* layout, const Symbol_table* symtab, const Input_objects* input_objects, const Stringpool* sympool, const Stringpool* dynpool, Output_file* of, Task_token* final_blocker) - : symtab_(symtab), input_objects_(input_objects), sympool_(sympool), - dynpool_(dynpool), of_(of), final_blocker_(final_blocker) + : layout_(layout), symtab_(symtab), input_objects_(input_objects), + sympool_(sympool), dynpool_(dynpool), of_(of), + final_blocker_(final_blocker) { } // The standard Task methods. @@ -726,6 +749,7 @@ class Write_symbols_task : public Task { return "Write_symbols_task"; } private: + const Layout* layout_; const Symbol_table* symtab_; const Input_objects* input_objects_; const Stringpool* sympool_; diff --git a/gold/object.cc b/gold/object.cc index 2849093..19d9185 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -40,6 +40,93 @@ namespace gold { +// Class Xindex. + +// Initialize the symtab_xindex_ array. Find the SHT_SYMTAB_SHNDX +// section and read it in. SYMTAB_SHNDX is the index of the symbol +// table we care about. + +template<int size, bool big_endian> +void +Xindex::initialize_symtab_xindex(Object* object, unsigned int symtab_shndx) +{ + if (!this->symtab_xindex_.empty()) + return; + + gold_assert(symtab_shndx != 0); + + // Look through the sections in reverse order, on the theory that it + // is more likely to be near the end than the beginning. + unsigned int i = object->shnum(); + while (i > 0) + { + --i; + if (object->section_type(i) == elfcpp::SHT_SYMTAB_SHNDX + && this->adjust_shndx(object->section_link(i)) == symtab_shndx) + { + this->read_symtab_xindex<size, big_endian>(object, i, NULL); + return; + } + } + + object->error(_("missing SHT_SYMTAB_SHNDX section")); +} + +// Read in the symtab_xindex_ array, given the section index of the +// SHT_SYMTAB_SHNDX section. If PSHDRS is not NULL, it points at the +// section headers. + +template<int size, bool big_endian> +void +Xindex::read_symtab_xindex(Object* object, unsigned int xindex_shndx, + const unsigned char* pshdrs) +{ + section_size_type bytecount; + const unsigned char* contents; + if (pshdrs == NULL) + contents = object->section_contents(xindex_shndx, &bytecount, false); + else + { + const unsigned char* p = (pshdrs + + (xindex_shndx + * elfcpp::Elf_sizes<size>::shdr_size)); + typename elfcpp::Shdr<size, big_endian> shdr(p); + bytecount = convert_to_section_size_type(shdr.get_sh_size()); + contents = object->get_view(shdr.get_sh_offset(), bytecount, true, false); + } + + gold_assert(this->symtab_xindex_.empty()); + this->symtab_xindex_.reserve(bytecount / 4); + for (section_size_type i = 0; i < bytecount; i += 4) + { + unsigned int shndx = elfcpp::Swap<32, big_endian>::readval(contents + i); + // We preadjust the section indexes we save. + this->symtab_xindex_.push_back(this->adjust_shndx(shndx)); + } +} + +// Symbol symndx has a section of SHN_XINDEX; return the real section +// index. + +unsigned int +Xindex::sym_xindex_to_shndx(Object* object, unsigned int symndx) +{ + if (symndx >= this->symtab_xindex_.size()) + { + object->error(_("symbol %u out of range for SHT_SYMTAB_SHNDX section"), + symndx); + return elfcpp::SHN_UNDEF; + } + unsigned int shndx = this->symtab_xindex_[symndx]; + if (shndx < elfcpp::SHN_LORESERVE || shndx >= object->shnum()) + { + object->error(_("extended index for symbol %u out of range: %u"), + symndx, shndx); + return elfcpp::SHN_UNDEF; + } + return shndx; +} + // Class Object. // Set the target based on fields in the ELF file header. @@ -204,6 +291,8 @@ Sized_relobj<size, big_endian>::find_symtab(const unsigned char* pshdrs) // to put the symbol table at the end. const unsigned char* p = pshdrs + shnum * This::shdr_size; unsigned int i = shnum; + unsigned int xindex_shndx = 0; + unsigned int xindex_link = 0; while (i > 0) { --i; @@ -212,12 +301,43 @@ Sized_relobj<size, big_endian>::find_symtab(const unsigned char* pshdrs) if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB) { this->symtab_shndx_ = i; + if (xindex_shndx > 0 && xindex_link == i) + { + Xindex* xindex = + new Xindex(this->elf_file_.large_shndx_offset()); + xindex->read_symtab_xindex<size, big_endian>(this, + xindex_shndx, + pshdrs); + this->set_xindex(xindex); + } break; } + + // Try to pick up the SHT_SYMTAB_SHNDX section, if there is + // one. This will work if it follows the SHT_SYMTAB + // section. + if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB_SHNDX) + { + xindex_shndx = i; + xindex_link = this->adjust_shndx(shdr.get_sh_link()); + } } } } +// Return the Xindex structure to use for object with lots of +// sections. + +template<int size, bool big_endian> +Xindex* +Sized_relobj<size, big_endian>::do_initialize_xindex() +{ + gold_assert(this->symtab_shndx_ != -1U); + Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset()); + xindex->initialize_symtab_xindex<size, big_endian>(this, this->symtab_shndx_); + return xindex; +} + // Return whether SHDR has the right type and flags to be a GNU // .eh_frame section. @@ -323,7 +443,7 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) File_view* fvsymtab = this->get_lasting_view(readoff, readsize, true, false); // Read the section header for the symbol names. - unsigned int strtab_shndx = symtabshdr.get_sh_link(); + unsigned int strtab_shndx = this->adjust_shndx(symtabshdr.get_sh_link()); if (strtab_shndx >= this->shnum()) { this->error(_("invalid symbol table name index: %u"), strtab_shndx); @@ -351,14 +471,17 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) } // Return the section index of symbol SYM. Set *VALUE to its value in -// the object file. Note that for a symbol which is not defined in -// this object file, this will set *VALUE to 0 and return SHN_UNDEF; -// it will not return the final value of the symbol in the link. +// the object file. Set *IS_ORDINARY if this is an ordinary section +// index. not a special cod between SHN_LORESERVE and SHN_HIRESERVE. +// Note that for a symbol which is not defined in this object file, +// this will set *VALUE to 0 and return SHN_UNDEF; it will not return +// the final value of the symbol in the link. template<int size, bool big_endian> unsigned int Sized_relobj<size, big_endian>::symbol_section_and_value(unsigned int sym, - Address* value) + Address* value, + bool* is_ordinary) { section_size_type symbols_size; const unsigned char* symbols = this->section_contents(this->symtab_shndx_, @@ -370,8 +493,8 @@ Sized_relobj<size, big_endian>::symbol_section_and_value(unsigned int sym, elfcpp::Sym<size, big_endian> elfsym(symbols + sym * This::sym_size); *value = elfsym.get_st_value(); - // FIXME: Handle SHN_XINDEX. - return elfsym.get_st_shndx(); + + return this->adjust_sym_shndx(sym, elfsym.get_st_shndx(), is_ordinary); } // Return whether to include a section group in the link. LAYOUT is @@ -408,17 +531,18 @@ Sized_relobj<size, big_endian>::include_section_group( // Get the appropriate symbol table header (this will normally be // the single SHT_SYMTAB section, but in principle it need not be). - const unsigned int link = shdr.get_sh_link(); + const unsigned int link = this->adjust_shndx(shdr.get_sh_link()); typename This::Shdr symshdr(this, this->elf_file_.section_header(link)); // Read the symbol table entry. - if (shdr.get_sh_info() >= symshdr.get_sh_size() / This::sym_size) + unsigned int symndx = shdr.get_sh_info(); + if (symndx >= symshdr.get_sh_size() / This::sym_size) { this->error(_("section group %u info %u out of range"), - index, shdr.get_sh_info()); + index, symndx); return false; } - off_t symoff = symshdr.get_sh_offset() + shdr.get_sh_info() * This::sym_size; + off_t symoff = symshdr.get_sh_offset() + symndx * This::sym_size; const unsigned char* psym = this->get_view(symoff, This::sym_size, true, false); elfcpp::Sym<size, big_endian> sym(psym); @@ -426,15 +550,15 @@ Sized_relobj<size, big_endian>::include_section_group( // Read the symbol table names. section_size_type symnamelen; const unsigned char* psymnamesu; - psymnamesu = this->section_contents(symshdr.get_sh_link(), &symnamelen, - true); + psymnamesu = this->section_contents(this->adjust_shndx(symshdr.get_sh_link()), + &symnamelen, true); const char* psymnames = reinterpret_cast<const char*>(psymnamesu); // Get the section group signature. if (sym.get_st_name() >= symnamelen) { this->error(_("symbol %u name offset %u out of range"), - shdr.get_sh_info(), sym.get_st_name()); + symndx, sym.get_st_name()); return false; } @@ -443,11 +567,20 @@ Sized_relobj<size, big_endian>::include_section_group( // It seems that some versions of gas will create a section group // associated with a section symbol, and then fail to give a name to // the section symbol. In such a case, use the name of the section. - // FIXME. std::string secname; if (signature[0] == '\0' && sym.get_st_type() == elfcpp::STT_SECTION) { - secname = this->section_name(sym.get_st_shndx()); + bool is_ordinary; + unsigned int sym_shndx = this->adjust_sym_shndx(symndx, + sym.get_st_shndx(), + &is_ordinary); + if (!is_ordinary || sym_shndx >= this->shnum()) + { + this->error(_("symbol %u invalid section index %u"), + symndx, sym_shndx); + return false; + } + secname = this->section_name(sym_shndx); signature = secname.c_str(); } @@ -559,7 +692,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, unsigned int sh_type = shdr.get_sh_type(); if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA) { - unsigned int target_shndx = shdr.get_sh_info(); + unsigned int target_shndx = this->adjust_shndx(shdr.get_sh_info()); if (target_shndx == 0 || target_shndx >= shnum) { this->error(_("relocation section %u has bad info %u"), @@ -723,7 +856,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, pshdr = sd->section_headers->data() + i * This::shdr_size; typename This::Shdr shdr(pshdr); - unsigned int data_shndx = shdr.get_sh_info(); + unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info()); if (data_shndx >= shnum) { // We already warned about this above. @@ -813,7 +946,11 @@ Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab, reinterpret_cast<const char*>(sd->symbol_names->data()); symtab->add_from_relobj(this, sd->symbols->data() + sd->external_symbols_offset, - symcount, sym_names, sd->symbol_names_size, + symcount, + (sd->external_symbols_offset == 0 + ? this->local_symbol_count_ + : 0), + sym_names, sd->symbol_names_size, &this->symbols_); delete sd->symbols; @@ -855,7 +992,8 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, locsize, true, true); // Read the symbol names. - const unsigned int strtab_shndx = symtabshdr.get_sh_link(); + const unsigned int strtab_shndx = + this->adjust_shndx(symtabshdr.get_sh_link()); section_size_type strtab_size; const unsigned char* pnamesu = this->section_contents(strtab_shndx, &strtab_size, @@ -876,8 +1014,10 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, Symbol_value<size>& lv(this->local_values_[i]); - unsigned int shndx = sym.get_st_shndx(); - lv.set_input_shndx(shndx); + bool is_ordinary; + unsigned int shndx = this->adjust_sym_shndx(i, sym.get_st_shndx(), + &is_ordinary); + lv.set_input_shndx(shndx, is_ordinary); if (sym.get_st_type() == elfcpp::STT_SECTION) lv.set_is_section_symbol(); @@ -937,7 +1077,7 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, template<int size, bool big_endian> unsigned int Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, - off_t off) + off_t off) { gold_assert(off == static_cast<off_t>(align_address(off, size >> 3))); @@ -951,17 +1091,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, { Symbol_value<size>& lv(this->local_values_[i]); - unsigned int shndx = lv.input_shndx(); + bool is_ordinary; + unsigned int shndx = lv.input_shndx(&is_ordinary); // Set the output symbol value. - if (shndx >= elfcpp::SHN_LORESERVE) + if (!is_ordinary) { if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON) lv.set_output_value(lv.input_value()); else { - // FIXME: Handle SHN_XINDEX. this->error(_("unknown section index %u for local symbol %u"), shndx, i); lv.set_output_value(0); @@ -1062,7 +1202,9 @@ void Sized_relobj<size, big_endian>::write_local_symbols( Output_file* of, const Stringpool* sympool, - const Stringpool* dynpool) + const Stringpool* dynpool, + Output_symtab_xindex* symtab_xindex, + Output_symtab_xindex* dynsym_xindex) { if (parameters->options().strip_all() && this->output_local_dynsym_count_ == 0) @@ -1090,7 +1232,8 @@ Sized_relobj<size, big_endian>::write_local_symbols( locsize, true, false); // Read the symbol names. - const unsigned int strtab_shndx = symtabshdr.get_sh_link(); + const unsigned int strtab_shndx = + this->adjust_shndx(symtabshdr.get_sh_link()); section_size_type strtab_size; const unsigned char* pnamesu = this->section_contents(strtab_shndx, &strtab_size, @@ -1121,18 +1264,30 @@ Sized_relobj<size, big_endian>::write_local_symbols( { elfcpp::Sym<size, big_endian> isym(psyms); - unsigned int st_shndx = isym.get_st_shndx(); - if (st_shndx < elfcpp::SHN_LORESERVE) + Symbol_value<size>& lv(this->local_values_[i]); + + bool is_ordinary; + unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(), + &is_ordinary); + if (is_ordinary) { gold_assert(st_shndx < mo.size()); if (mo[st_shndx].output_section == NULL) continue; st_shndx = mo[st_shndx].output_section->out_shndx(); + if (st_shndx >= elfcpp::SHN_LORESERVE) + { + if (lv.needs_output_symtab_entry()) + symtab_xindex->add(lv.output_symtab_index(), st_shndx); + if (lv.needs_output_dynsym_entry()) + dynsym_xindex->add(lv.output_dynsym_index(), st_shndx); + st_shndx = elfcpp::SHN_XINDEX; + } } // Write the symbol to the output symbol table. if (!parameters->options().strip_all() - && this->local_values_[i].needs_output_symtab_entry()) + && lv.needs_output_symtab_entry()) { elfcpp::Sym_write<size, big_endian> osym(ov); @@ -1149,7 +1304,7 @@ Sized_relobj<size, big_endian>::write_local_symbols( } // Write the symbol to the output dynamic symbol table. - if (this->local_values_[i].needs_output_dynsym_entry()) + if (lv.needs_output_dynsym_entry()) { gold_assert(dyn_ov < dyn_oview + dyn_output_size); elfcpp::Sym_write<size, big_endian> osym(dyn_ov); @@ -1201,7 +1356,8 @@ Sized_relobj<size, big_endian>::get_symbol_location_info( &symbols_size, false); - unsigned int symbol_names_shndx = this->section_link(this->symtab_shndx_); + unsigned int symbol_names_shndx = + this->adjust_shndx(this->section_link(this->symtab_shndx_)); section_size_type names_size; const unsigned char* symbol_names_u = this->section_contents(symbol_names_shndx, &names_size, false); @@ -1221,11 +1377,17 @@ Sized_relobj<size, big_endian>::get_symbol_location_info( info->source_file = "(invalid)"; else info->source_file = symbol_names + sym.get_st_name(); + continue; } - else if (sym.get_st_shndx() == shndx - && static_cast<off_t>(sym.get_st_value()) <= offset - && (static_cast<off_t>(sym.get_st_value() + sym.get_st_size()) - > offset)) + + bool is_ordinary; + unsigned int st_shndx = this->adjust_sym_shndx(i, sym.get_st_shndx(), + &is_ordinary); + if (is_ordinary + && st_shndx == shndx + && static_cast<off_t>(sym.get_st_value()) <= offset + && (static_cast<off_t>(sym.get_st_value() + sym.get_st_size()) + > offset)) { if (sym.get_st_name() > names_size) info->enclosing_symbol_name = "(invalid)"; diff --git a/gold/object.h b/gold/object.h index 9e64277..aaaa48d 100644 --- a/gold/object.h +++ b/gold/object.h @@ -39,6 +39,7 @@ class Task; class Layout; class Output_section; class Output_file; +class Output_symtab_xindex; class Dynobj; class Object_merge_map; class Relocatable_relocs; @@ -127,6 +128,55 @@ struct Read_relocs_data File_view* local_symbols; }; +// The Xindex class manages section indexes for objects with more than +// 0xff00 sections. + +class Xindex +{ + public: + Xindex(int large_shndx_offset) + : large_shndx_offset_(large_shndx_offset), symtab_xindex_() + { } + + // Initialize the symtab_xindex_ array, given the object and the + // section index of the symbol table to use. + template<int size, bool big_endian> + void + initialize_symtab_xindex(Object*, unsigned int symtab_shndx); + + // Read in the symtab_xindex_ array, given its section index. + // PSHDRS may optionally point to the section headers. + template<int size, bool big_endian> + void + read_symtab_xindex(Object*, unsigned int xindex_shndx, + const unsigned char* pshdrs); + + // Symbol SYMNDX in OBJECT has a section of SHN_XINDEX; return the + // real section index. + unsigned int + sym_xindex_to_shndx(Object* object, unsigned int symndx); + + private: + // The type of the array giving the real section index for symbols + // whose st_shndx field holds SHN_XINDEX. + typedef std::vector<unsigned int> Symtab_xindex; + + // Adjust a section index if necessary. This should only be called + // for ordinary section indexes. + unsigned int + adjust_shndx(unsigned int shndx) + { + if (shndx >= elfcpp::SHN_LORESERVE) + shndx += this->large_shndx_offset_; + return shndx; + } + + // Adjust to apply to large section indexes. + int large_shndx_offset_; + // The data from the SHT_SYMTAB_SHNDX section. + Symtab_xindex symtab_xindex_; +}; + // Object is an abstract base class which represents either a 32-bit // or a 64-bit input object. This can be a regular object file // (ET_REL) or a shared object (ET_DYN). @@ -141,7 +191,7 @@ class Object Object(const std::string& name, Input_file* input_file, bool is_dynamic, off_t offset = 0) : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U), - is_dynamic_(is_dynamic), target_(NULL) + is_dynamic_(is_dynamic), target_(NULL), xindex_(NULL) { input_file->file().add_object(); } virtual ~Object() @@ -214,6 +264,29 @@ class Object const unsigned char* section_contents(unsigned int shndx, section_size_type* plen, bool cache); + // Adjust a symbol's section index as needed. SYMNDX is the index + // of the symbol and SHNDX is the symbol's section from + // get_st_shndx. This returns the section index. It sets + // *IS_ORDINARY to indicate whether this is a normal section index, + // rather than a special code between SHN_LORESERVE and + // SHN_HIRESERVE. + unsigned int + adjust_sym_shndx(unsigned int symndx, unsigned int shndx, bool* is_ordinary) + { + if (shndx < elfcpp::SHN_LORESERVE) + *is_ordinary = true; + else if (shndx == elfcpp::SHN_XINDEX) + { + if (this->xindex_ == NULL) + this->xindex_ = this->do_initialize_xindex(); + shndx = this->xindex_->sym_xindex_to_shndx(this, symndx); + *is_ordinary = true; + } + else + *is_ordinary = false; + return shndx; + } + // Return the size of a section given a section index. uint64_t section_size(unsigned int shndx) @@ -399,6 +472,10 @@ class Object virtual uint64_t do_section_addralign(unsigned int shndx) = 0; + // Return the Xindex structure to use. + virtual Xindex* + do_initialize_xindex() = 0; + // Get the file. We pass on const-ness. Input_file* input_file() @@ -426,6 +503,14 @@ class Object read_section_data(elfcpp::Elf_file<size, big_endian, Object>*, Read_symbols_data*); + // Let the child class initialize the xindex object directly. + void + set_xindex(Xindex* xindex) + { + gold_assert(this->xindex_ == NULL); + this->xindex_ = xindex; + } + // If NAME is the name of a special .gnu.warning section, arrange // for the warning to be issued. SHNDX is the section index. // Return whether it is a warning section. @@ -451,6 +536,8 @@ class Object bool is_dynamic_; // Target functions--may be NULL if the target is not known. Target* target_; + // Many sections for objects with more than SHN_LORESERVE sections. + Xindex* xindex_; }; // Implement sized_target inline for efficiency. This approach breaks @@ -774,8 +861,8 @@ class Symbol_value Symbol_value() : output_symtab_index_(0), output_dynsym_index_(-1U), input_shndx_(0), - is_section_symbol_(false), is_tls_symbol_(false), - has_output_value_(true) + is_ordinary_shndx_(false), is_section_symbol_(false), + is_tls_symbol_(false), has_output_value_(true) { this->u_.value = 0; } // Get the value of this symbol. OBJECT is the object in which this @@ -787,8 +874,11 @@ class Symbol_value if (this->has_output_value_) return this->u_.value + addend; else - return this->u_.merged_symbol_value->value(object, this->input_shndx_, - addend); + { + gold_assert(this->is_ordinary_shndx_); + return this->u_.merged_symbol_value->value(object, this->input_shndx_, + addend); + } } // Set the value of this symbol in the output symbol table. @@ -814,7 +904,7 @@ class Symbol_value { if (!this->has_output_value_) { - gold_assert(this->is_section_symbol_); + gold_assert(this->is_section_symbol_ && this->is_ordinary_shndx_); Merged_symbol_value<size>* msv = this->u_.merged_symbol_value; msv->initialize_input_to_output_map(object, this->input_shndx_); } @@ -908,18 +998,22 @@ class Symbol_value // Set the index of the input section in the input file. void - set_input_shndx(unsigned int i) + set_input_shndx(unsigned int i, bool is_ordinary) { this->input_shndx_ = i; // input_shndx_ field is a bitfield, so make sure that the value // fits. gold_assert(this->input_shndx_ == i); + this->is_ordinary_shndx_ = is_ordinary; } // Return the index of the input section in the input file. unsigned int - input_shndx() const - { return this->input_shndx_; } + input_shndx(bool* is_ordinary) const + { + *is_ordinary = this->is_ordinary_shndx_; + return this->input_shndx_; + } // Whether this is a section symbol. bool @@ -953,7 +1047,10 @@ class Symbol_value unsigned int output_dynsym_index_; // The section index in the input file in which this symbol is // defined. - unsigned int input_shndx_ : 29; + unsigned int input_shndx_ : 28; + // Whether the section index is an ordinary index, not a special + // value. + bool is_ordinary_shndx_ : 1; // Whether this is a STT_SECTION symbol. bool is_section_symbol_ : 1; // Whether this is a STT_TLS symbol. @@ -1087,12 +1184,13 @@ class Sized_relobj : public Relobj } // Return the section index of symbol SYM. Set *VALUE to its value - // in the object file. Note that for a symbol which is not defined - // in this object file, this will set *VALUE to 0 and return - // SHN_UNDEF; it will not return the final value of the symbol in - // the link. + // in the object file. Set *IS_ORDINARY if this is an ordinary + // section index, not a special code between SHN_LORESERVE and + // SHN_HIRESERVE. Note that for a symbol which is not defined in + // this object file, this will set *VALUE to 0 and return SHN_UNDEF; + // it will not return the final value of the symbol in the link. unsigned int - symbol_section_and_value(unsigned int sym, Address* value); + symbol_section_and_value(unsigned int sym, Address* value, bool* is_ordinary); // Return a pointer to the Symbol_value structure which holds the // value of a local symbol. @@ -1123,10 +1221,10 @@ class Sized_relobj : public Relobj // Return the input section index of local symbol SYM. unsigned int - local_symbol_input_shndx(unsigned int sym) const + local_symbol_input_shndx(unsigned int sym, bool* is_ordinary) const { gold_assert(sym < this->local_values_.size()); - return this->local_values_[sym].input_shndx(); + return this->local_values_[sym].input_shndx(is_ordinary); } // Return the appropriate Sized_target structure. @@ -1284,6 +1382,10 @@ class Sized_relobj : public Relobj do_section_addralign(unsigned int shndx) { return this->elf_file_.section_addralign(shndx); } + // Return the Xindex structure to use. + Xindex* + do_initialize_xindex(); + private: // For convenience. typedef Sized_relobj<size, big_endian> This; @@ -1292,6 +1394,15 @@ class Sized_relobj : public Relobj static const int sym_size = elfcpp::Elf_sizes<size>::sym_size; typedef elfcpp::Shdr<size, big_endian> Shdr; + // Adjust a section index if necessary. + unsigned int + adjust_shndx(unsigned int shndx) + { + if (shndx >= elfcpp::SHN_LORESERVE) + shndx += this->elf_file_.large_shndx_offset(); + return shndx; + } + // Find the SHT_SYMTAB section, given the section headers. void find_symtab(const unsigned char* pshdrs); @@ -1391,7 +1502,9 @@ class Sized_relobj : public Relobj void write_local_symbols(Output_file*, const Stringpool_template<char>*, - const Stringpool_template<char>*); + const Stringpool_template<char>*, + Output_symtab_xindex*, + Output_symtab_xindex*); // Clear the local symbol information. void diff --git a/gold/output.cc b/gold/output.cc index 09b7312..ded6d42 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -87,12 +87,14 @@ Output_section_headers::Output_section_headers( const Layout::Segment_list* segment_list, const Layout::Section_list* section_list, const Layout::Section_list* unattached_section_list, - const Stringpool* secnamepool) + const Stringpool* secnamepool, + const Output_section* shstrtab_section) : layout_(layout), segment_list_(segment_list), section_list_(section_list), unattached_section_list_(unattached_section_list), - secnamepool_(secnamepool) + secnamepool_(secnamepool), + shstrtab_section_(shstrtab_section) { // Count all the sections. Start with 1 for the null section. off_t count = 1; @@ -175,8 +177,20 @@ Output_section_headers::do_sized_write(Output_file* of) oshdr.put_sh_flags(0); oshdr.put_sh_addr(0); oshdr.put_sh_offset(0); - oshdr.put_sh_size(0); - oshdr.put_sh_link(0); + + size_t section_count = (this->data_size() + / elfcpp::Elf_sizes<size>::shdr_size); + if (section_count < elfcpp::SHN_LORESERVE) + oshdr.put_sh_size(0); + else + oshdr.put_sh_size(section_count); + + unsigned int shstrndx = this->shstrtab_section_->out_shndx(); + if (shstrndx < elfcpp::SHN_LORESERVE) + oshdr.put_sh_link(0); + else + oshdr.put_sh_link(shstrndx); + oshdr.put_sh_info(0); oshdr.put_sh_addralign(0); oshdr.put_sh_entsize(0); @@ -447,9 +461,20 @@ Output_file_header::do_sized_write(Output_file* of) } oehdr.put_e_shentsize(elfcpp::Elf_sizes<size>::shdr_size); - oehdr.put_e_shnum(this->section_header_->data_size() - / elfcpp::Elf_sizes<size>::shdr_size); - oehdr.put_e_shstrndx(this->shstrtab_->out_shndx()); + size_t section_count = (this->section_header_->data_size() + / elfcpp::Elf_sizes<size>::shdr_size); + + if (section_count < elfcpp::SHN_LORESERVE) + oehdr.put_e_shnum(this->section_header_->data_size() + / elfcpp::Elf_sizes<size>::shdr_size); + else + oehdr.put_e_shnum(0); + + unsigned int shstrndx = this->shstrtab_->out_shndx(); + if (shstrndx < elfcpp::SHN_LORESERVE) + oehdr.put_e_shstrndx(this->shstrtab_->out_shndx()); + else + oehdr.put_e_shstrndx(elfcpp::SHN_XINDEX); of->write_output_view(0, ehdr_size, view); } @@ -1478,6 +1503,38 @@ Output_data_dynamic::sized_write(Output_file* of) this->entries_.clear(); } +// Class Output_symtab_xindex. + +void +Output_symtab_xindex::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const off_t oview_size = this->data_size(); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + memset(oview, 0, oview_size); + + if (parameters->target().is_big_endian()) + this->endian_do_write<true>(oview); + else + this->endian_do_write<false>(oview); + + of->write_output_view(offset, oview_size, oview); + + // We no longer need the data. + this->entries_.clear(); +} + +template<bool big_endian> +void +Output_symtab_xindex::endian_do_write(unsigned char* const oview) +{ + for (Xindex_entries::const_iterator p = this->entries_.begin(); + p != this->entries_.end(); + ++p) + elfcpp::Swap<32, big_endian>::writeval(oview + p->first * 4, p->second); +} + // Output_section::Input_section methods. // Return the data size. For an input section we store the size here. diff --git a/gold/output.h b/gold/output.h index 4772cb4a..b6527a3 100644 --- a/gold/output.h +++ b/gold/output.h @@ -384,7 +384,8 @@ class Output_section_headers : public Output_data const Layout::Segment_list*, const Layout::Section_list*, const Layout::Section_list*, - const Stringpool*); + const Stringpool*, + const Output_section*); protected: // Write the data to the file. @@ -407,6 +408,7 @@ class Output_section_headers : public Output_data const Layout::Section_list* section_list_; const Layout::Section_list* unattached_section_list_; const Stringpool* secnamepool_; + const Output_section* shstrtab_section_; }; // Output the segment headers. @@ -1682,6 +1684,41 @@ class Output_data_dynamic : public Output_section_data Stringpool* pool_; }; +// Output_symtab_xindex is used to handle SHT_SYMTAB_SHNDX sections, +// which may be required if the object file has more than +// SHN_LORESERVE sections. + +class Output_symtab_xindex : public Output_section_data +{ + public: + Output_symtab_xindex(size_t symcount) + : Output_section_data(symcount * 4, 4), + entries_() + { } + + // Add an entry: symbol number SYMNDX has section SHNDX. + void + add(unsigned int symndx, unsigned int shndx) + { this->entries_.push_back(std::make_pair(symndx, shndx)); } + + protected: + void + do_write(Output_file*); + + private: + template<bool big_endian> + void + endian_do_write(unsigned char*); + + // It is likely that most symbols will not require entries. Rather + // than keep a vector for all symbols, we keep pairs of symbol index + // and section index. + typedef std::vector<std::pair<unsigned int, unsigned int> > Xindex_entries; + + // The entries we need. + Xindex_entries entries_; +}; + // An output section. We don't expect to have too many output // sections, so we don't bother to do a template on the size. @@ -1861,6 +1898,11 @@ class Output_section : public Output_data set_addralign(uint64_t v) { this->addralign_ = v; } + // Whether the output section index has been set. + bool + has_out_shndx() const + { return this->out_shndx_ != -1U; } + // Indicate that we need a symtab index. void set_needs_symtab_index() diff --git a/gold/reloc.cc b/gold/reloc.cc index 99a736b..b44dd72 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -208,7 +208,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA) continue; - unsigned int shndx = shdr.get_sh_info(); + unsigned int shndx = this->adjust_shndx(shdr.get_sh_info()); if (shndx >= shnum) { this->error(_("relocation section %u has bad info %u"), @@ -233,11 +233,11 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) && !parameters->options().emit_relocs()) continue; - if (shdr.get_sh_link() != this->symtab_shndx_) + if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_) { this->error(_("relocation section %u uses unexpected " "symbol table %u"), - i, shdr.get_sh_link()); + i, this->adjust_shndx(shdr.get_sh_link())); continue; } @@ -507,7 +507,8 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options, } // Write out the local symbols. - this->write_local_symbols(of, layout->sympool(), layout->dynpool()); + this->write_local_symbols(of, layout->sympool(), layout->dynpool(), + layout->symtab_xindex(), layout->dynsym_xindex()); // We should no longer need the local symbol values. this->clear_local_symbols(); @@ -714,7 +715,7 @@ Sized_relobj<size, big_endian>::relocate_sections( if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA) continue; - unsigned int index = shdr.get_sh_info(); + unsigned int index = this->adjust_shndx(shdr.get_sh_info()); if (index >= this->shnum()) { this->error(_("relocation section %u has bad info %u"), @@ -735,11 +736,11 @@ Sized_relobj<size, big_endian>::relocate_sections( if (parameters->options().relocatable()) gold_assert((*pviews)[i].view != NULL); - if (shdr.get_sh_link() != this->symtab_shndx_) + if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_) { gold_error(_("relocation section %u uses unexpected " "symbol table %u"), - i, shdr.get_sh_link()); + i, this->adjust_shndx(shdr.get_sh_link())); continue; } diff --git a/gold/resolve.cc b/gold/resolve.cc index 00e9278..21a7fc6 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -37,6 +37,7 @@ namespace gold template<int size, bool big_endian> void Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary, Object* object, const char* version) { gold_assert(this->source_ == FROM_OBJECT); @@ -46,8 +47,8 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym, gold_assert(this->version() == NULL); this->version_ = version; } - // FIXME: Handle SHN_XINDEX. - this->u_.from_object.shndx = sym.get_st_shndx(); + this->u_.from_object.shndx = st_shndx; + this->is_ordinary_shndx_ = is_ordinary; this->type_ = sym.get_st_type(); this->binding_ = sym.get_st_bind(); this->visibility_ = sym.get_st_visibility(); @@ -64,9 +65,10 @@ template<int size> template<bool big_endian> void Sized_symbol<size>::override(const elfcpp::Sym<size, big_endian>& sym, + unsigned st_shndx, bool is_ordinary, Object* object, const char* version) { - this->override_base(sym, object, version); + this->override_base(sym, st_shndx, is_ordinary, object, version); this->value_ = sym.get_st_value(); this->symsize_ = sym.get_st_size(); } @@ -78,9 +80,10 @@ template<int size, bool big_endian> void Symbol_table::override(Sized_symbol<size>* tosym, const elfcpp::Sym<size, big_endian>& fromsym, + unsigned int st_shndx, bool is_ordinary, Object* object, const char* version) { - tosym->override(fromsym, object, version); + tosym->override(fromsym, st_shndx, is_ordinary, object, version); if (tosym->has_alias()) { Symbol* sym = this->weak_aliases_[tosym]; @@ -88,7 +91,7 @@ Symbol_table::override(Sized_symbol<size>* tosym, Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym); do { - ssym->override(fromsym, object, version); + ssym->override(fromsym, st_shndx, is_ordinary, object, version); sym = this->weak_aliases_[ssym]; gold_assert(sym != NULL); ssym = this->get_sized_symbol<size>(sym); @@ -121,7 +124,7 @@ static const unsigned int common_flag = 2 << def_undef_or_common_shift; static unsigned int symbol_to_bits(elfcpp::STB binding, bool is_dynamic, - unsigned int shndx, elfcpp::STT type) + unsigned int shndx, bool is_ordinary, elfcpp::STT type) { unsigned int bits; @@ -160,7 +163,8 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic, break; case elfcpp::SHN_COMMON: - bits |= common_flag; + if (!is_ordinary) + bits |= common_flag; break; default: @@ -175,17 +179,20 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic, } // Resolve a symbol. This is called the second and subsequent times -// we see a symbol. TO is the pre-existing symbol. ORIG_SYM is the -// new symbol, seen in OBJECT. SYM is almost always identical to -// ORIG_SYM, but may be munged (for instance, if we determine the -// symbol is in a to-be-discarded section, we'll set sym's shndx to -// UNDEFINED). VERSION of the version of SYM. +// we see a symbol. TO is the pre-existing symbol. ST_SHNDX is the +// section index for SYM, possibly adjusted for many sections. +// IS_ORDINARY is whether ST_SHNDX is a normal section index rather +// than a special code. ORIG_ST_SHNDX is the original section index, +// before any munging because of discarded sections, except that all +// non-ordinary section indexes are mapped to SHN_UNDEF. VERSION of +// the version of SYM. template<int size, bool big_endian> void Symbol_table::resolve(Sized_symbol<size>* to, const elfcpp::Sym<size, big_endian>& sym, - const elfcpp::Sym<size, big_endian>& orig_sym, + unsigned int st_shndx, bool is_ordinary, + unsigned int orig_st_shndx, Object* object, const char* version) { if (object->target()->has_resolve()) @@ -209,7 +216,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, unsigned int frombits = symbol_to_bits(sym.get_st_bind(), object->is_dynamic(), - sym.get_st_shndx(), + st_shndx, is_ordinary, sym.get_st_type()); bool adjust_common_sizes; @@ -218,7 +225,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, { typename Sized_symbol<size>::Size_type tosize = to->symsize(); - this->override(to, sym, object, version); + this->override(to, sym, st_shndx, is_ordinary, object, version); if (adjust_common_sizes && tosize > to->symsize()) to->set_symsize(tosize); @@ -236,24 +243,25 @@ Symbol_table::resolve(Sized_symbol<size>* to, // actually refer to the same lines of code. (Note: not all ODR // violations can be found this way, and not everything this finds // is an ODR violation. But it's helpful to warn about.) - // We use orig_sym here because we want the symbol exactly as it - // appears in the object file, not munged via our future processing. + bool to_is_ordinary; if (parameters->options().detect_odr_violations() - && orig_sym.get_st_bind() == elfcpp::STB_WEAK + && sym.get_st_bind() == elfcpp::STB_WEAK && to->binding() == elfcpp::STB_WEAK - && orig_sym.get_st_shndx() != elfcpp::SHN_UNDEF - && to->shndx() != elfcpp::SHN_UNDEF - && orig_sym.get_st_size() != 0 // Ignore weird 0-sized symbols. + && orig_st_shndx != elfcpp::SHN_UNDEF + && to->shndx(&to_is_ordinary) != elfcpp::SHN_UNDEF + && to_is_ordinary + && sym.get_st_size() != 0 // Ignore weird 0-sized symbols. && to->symsize() != 0 - && (orig_sym.get_st_type() != to->type() - || orig_sym.get_st_size() != to->symsize()) + && (sym.get_st_type() != to->type() + || sym.get_st_size() != to->symsize()) // C does not have a concept of ODR, so we only need to do this // on C++ symbols. These have (mangled) names starting with _Z. && to->name()[0] == '_' && to->name()[1] == 'Z') { Symbol_location fromloc - = { object, orig_sym.get_st_shndx(), orig_sym.get_st_value() }; - Symbol_location toloc = { to->object(), to->shndx(), to->value() }; + = { object, orig_st_shndx, sym.get_st_value() }; + Symbol_location toloc = { to->object(), to->shndx(&to_is_ordinary), + to->value() }; this->candidate_odr_violations_[to->name()].insert(fromloc); this->candidate_odr_violations_[to->name()].insert(toloc); } @@ -273,14 +281,19 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, *adjust_common_sizes = false; unsigned int tobits; - if (to->source() == Symbol::FROM_OBJECT) - tobits = symbol_to_bits(to->binding(), - to->object()->is_dynamic(), - to->shndx(), + if (to->source() != Symbol::FROM_OBJECT) + tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false, to->type()); else - tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, - to->type()); + { + bool is_ordinary; + unsigned int shndx = to->shndx(&is_ordinary); + tobits = symbol_to_bits(to->binding(), + to->object()->is_dynamic(), + shndx, + is_ordinary, + to->type()); + } // FIXME: Warn if either but not both of TO and SYM are STT_TLS. @@ -733,7 +746,9 @@ void Symbol_table::resolve<32, false>( Sized_symbol<32>* to, const elfcpp::Sym<32, false>& sym, - const elfcpp::Sym<32, false>& orig_sym, + unsigned int st_shndx, + bool is_ordinary, + unsigned int orig_st_shndx, Object* object, const char* version); #endif @@ -744,7 +759,9 @@ void Symbol_table::resolve<32, true>( Sized_symbol<32>* to, const elfcpp::Sym<32, true>& sym, - const elfcpp::Sym<32, true>& orig_sym, + unsigned int st_shndx, + bool is_ordinary, + unsigned int orig_st_shndx, Object* object, const char* version); #endif @@ -755,7 +772,9 @@ void Symbol_table::resolve<64, false>( Sized_symbol<64>* to, const elfcpp::Sym<64, false>& sym, - const elfcpp::Sym<64, false>& orig_sym, + unsigned int st_shndx, + bool is_ordinary, + unsigned int orig_st_shndx, Object* object, const char* version); #endif @@ -766,7 +785,9 @@ void Symbol_table::resolve<64, true>( Sized_symbol<64>* to, const elfcpp::Sym<64, true>& sym, - const elfcpp::Sym<64, true>& orig_sym, + unsigned int st_shndx, + bool is_ordinary, + unsigned int orig_st_shndx, Object* object, const char* version); #endif diff --git a/gold/sparc.cc b/gold/sparc.cc index 1ae48c3..60e8524 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1737,13 +1737,21 @@ Target_sparc<size, big_endian>::Scan::local( Output_data_got<size, big_endian>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); - got->add_local_pair_with_rela(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - (size == 64 ? - elfcpp::R_SPARC_TLS_DTPMOD64 : - elfcpp::R_SPARC_TLS_DTPMOD32), 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + lsym.get_st_shndx(), + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + (size == 64 + ? elfcpp::R_SPARC_TLS_DTPMOD64 + : elfcpp::R_SPARC_TLS_DTPMOD32), + 0); if (r_type == elfcpp::R_SPARC_TLS_GD_CALL) generate_tls_call(symtab, layout, target); } diff --git a/gold/symtab.cc b/gold/symtab.cc index 517d011..eeb32fd 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -72,6 +72,7 @@ Symbol::init_fields(const char* name, const char* version, this->has_warning_ = false; this->is_copied_from_dynobj_ = false; this->is_forced_local_ = false; + this->is_ordinary_shndx_ = false; } // Return the demangled version of the symbol's name, but only @@ -105,13 +106,14 @@ Symbol::demangled_name() const template<int size, bool big_endian> void Symbol::init_base(const char* name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>& sym) + const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary) { this->init_fields(name, version, sym.get_st_type(), sym.get_st_bind(), sym.get_st_visibility(), sym.get_st_nonvis()); this->u_.from_object.object = object; - // FIXME: Handle SHN_XINDEX. - this->u_.from_object.shndx = sym.get_st_shndx(); + this->u_.from_object.shndx = st_shndx; + this->is_ordinary_shndx_ = is_ordinary; this->source_ = FROM_OBJECT; this->in_reg_ = !object->is_dynamic(); this->in_dyn_ = object->is_dynamic(); @@ -177,9 +179,10 @@ template<int size> template<bool big_endian> void Sized_symbol<size>::init(const char* name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>& sym) + const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary) { - this->init_base(name, version, object, sym); + this->init_base(name, version, object, sym, st_shndx, is_ordinary); this->value_ = sym.get_st_value(); this->symsize_ = sym.get_st_size(); } @@ -309,7 +312,7 @@ Symbol::output_section() const case FROM_OBJECT: { unsigned int shndx = this->u_.from_object.shndx; - if (shndx != elfcpp::SHN_UNDEF && shndx < elfcpp::SHN_LORESERVE) + if (shndx != elfcpp::SHN_UNDEF && this->is_ordinary_shndx_) { gold_assert(!this->u_.from_object.object->is_dynamic()); Relobj* relobj = static_cast<Relobj*>(this->u_.from_object.object); @@ -449,13 +452,15 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from, { unsigned char buf[elfcpp::Elf_sizes<size>::sym_size]; elfcpp::Sym_write<size, big_endian> esym(buf); - // We don't bother to set the st_name field. + // We don't bother to set the st_name or the st_shndx field. esym.put_st_value(from->value()); esym.put_st_size(from->symsize()); esym.put_st_info(from->binding(), from->type()); esym.put_st_other(from->visibility(), from->nonvis()); - esym.put_st_shndx(from->shndx()); - this->resolve(to, esym.sym(), esym.sym(), from->object(), version); + bool is_ordinary; + unsigned int shndx = from->shndx(&is_ordinary); + this->resolve(to, esym.sym(), shndx, is_ordinary, shndx, from->object(), + version); if (from->in_reg()) to->set_in_reg(); if (from->in_dyn()) @@ -528,7 +533,9 @@ Symbol_table::wrap_symbol(Object* object, const char* name, // Add one symbol from OBJECT to the symbol table. NAME is symbol // name and VERSION is the version; both are canonicalized. DEF is -// whether this is the default version. +// whether this is the default version. ST_SHNDX is the symbol's +// section index; IS_ORDINARY is whether this is a normal section +// rather than a special code. // If DEF is true, then this is the definition of a default version of // a symbol. That means that any lookup of NAME/NULL and any lookup @@ -549,10 +556,10 @@ Symbol_table::wrap_symbol(Object* object, const char* name, // Note that entries in the hash table will never be marked as // forwarders. // -// SYM and ORIG_SYM are almost always the same. ORIG_SYM is the -// symbol exactly as it existed in the input file. SYM is usually -// that as well, but can be modified, for instance if we determine -// it's in a to-be-discarded section. +// ORIG_ST_SHNDX and ST_SHNDX are almost always the same. +// ORIG_ST_SHNDX is the section index in the input file, or SHN_UNDEF +// for a special section code. ST_SHNDX may be modified if the symbol +// is defined in a section being discarded. template<int size, bool big_endian> Sized_symbol<size>* @@ -563,12 +570,14 @@ Symbol_table::add_from_object(Object* object, Stringpool::Key version_key, bool def, const elfcpp::Sym<size, big_endian>& sym, - const elfcpp::Sym<size, big_endian>& orig_sym) + unsigned int st_shndx, + bool is_ordinary, + unsigned int orig_st_shndx) { // Print a message if this symbol is being traced. if (parameters->options().is_trace_symbol(name)) { - if (orig_sym.get_st_shndx() == elfcpp::SHN_UNDEF) + if (orig_st_shndx == elfcpp::SHN_UNDEF) gold_info(_("%s: reference to %s"), object->name().c_str(), name); else gold_info(_("%s: definition of %s"), object->name().c_str(), name); @@ -576,7 +585,7 @@ Symbol_table::add_from_object(Object* object, // For an undefined symbol, we may need to adjust the name using // --wrap. - if (orig_sym.get_st_shndx() == elfcpp::SHN_UNDEF + if (orig_st_shndx == elfcpp::SHN_UNDEF && parameters->options().any_wrap()) { const char* wrap_name = this->wrap_symbol(object, name, &name_key); @@ -625,7 +634,8 @@ Symbol_table::add_from_object(Object* object, was_undefined = ret->is_undefined(); was_common = ret->is_common(); - this->resolve(ret, sym, orig_sym, object, version); + this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object, + version); if (def) { @@ -671,7 +681,8 @@ Symbol_table::add_from_object(Object* object, was_undefined = ret->is_undefined(); was_common = ret->is_common(); - this->resolve(ret, sym, orig_sym, object, version); + this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object, + version); ins.first->second = ret; } else @@ -703,7 +714,7 @@ Symbol_table::add_from_object(Object* object, } } - ret->init(name, version, object, sym); + ret->init(name, version, object, sym, st_shndx, is_ordinary); ins.first->second = ret; if (def) @@ -744,6 +755,7 @@ Symbol_table::add_from_relobj( Sized_relobj<size, big_endian>* relobj, const unsigned char* syms, size_t count, + size_t symndx_offset, const char* sym_names, size_t sym_name_size, typename Sized_relobj<size, big_endian>::Symbols* sympointers) @@ -759,9 +771,8 @@ Symbol_table::add_from_relobj( for (size_t i = 0; i < count; ++i, p += sym_size) { elfcpp::Sym<size, big_endian> sym(p); - elfcpp::Sym<size, big_endian>* psym = &sym; - unsigned int st_name = psym->get_st_name(); + unsigned int st_name = sym.get_st_name(); if (st_name >= sym_name_size) { relobj->error(_("bad global symbol name offset %u at %zu"), @@ -771,20 +782,20 @@ Symbol_table::add_from_relobj( const char* name = sym_names + st_name; + bool is_ordinary; + unsigned int st_shndx = relobj->adjust_sym_shndx(i + symndx_offset, + sym.get_st_shndx(), + &is_ordinary); + unsigned int orig_st_shndx = st_shndx; + if (!is_ordinary) + orig_st_shndx = elfcpp::SHN_UNDEF; + // A symbol defined in a section which we are not including must // be treated as an undefined symbol. - unsigned char symbuf[sym_size]; - elfcpp::Sym<size, big_endian> sym2(symbuf); - unsigned int st_shndx = psym->get_st_shndx(); if (st_shndx != elfcpp::SHN_UNDEF - && st_shndx < elfcpp::SHN_LORESERVE + && is_ordinary && !relobj->is_section_included(st_shndx)) - { - memcpy(symbuf, p, sym_size); - elfcpp::Sym_write<size, big_endian> sw(symbuf); - sw.put_st_shndx(elfcpp::SHN_UNDEF); - psym = &sym2; - } + st_shndx = elfcpp::SHN_UNDEF; // In an object file, an '@' in the name separates the symbol // name from the version name. If there are two '@' characters, @@ -810,7 +821,7 @@ Symbol_table::add_from_relobj( // even if it is listed in the version script. FIXME: What // about a common symbol? else if (!version_script_.empty() - && psym->get_st_shndx() != elfcpp::SHN_UNDEF) + && st_shndx != elfcpp::SHN_UNDEF) { // The symbol name did not have a version, but // the version script may assign a version anyway. @@ -826,14 +837,14 @@ Symbol_table::add_from_relobj( local = true; } + elfcpp::Sym<size, big_endian>* psym = &sym; + unsigned char symbuf[sym_size]; + elfcpp::Sym<size, big_endian> sym2(symbuf); if (just_symbols) { - if (psym != &sym2) - memcpy(symbuf, p, sym_size); + memcpy(symbuf, p, sym_size); elfcpp::Sym_write<size, big_endian> sw(symbuf); - sw.put_st_shndx(elfcpp::SHN_ABS); - if (st_shndx != elfcpp::SHN_UNDEF - && st_shndx < elfcpp::SHN_LORESERVE) + if (orig_st_shndx != elfcpp::SHN_UNDEF && is_ordinary) { // Symbol values in object files are section relative. // This is normally what we want, but since here we are @@ -841,9 +852,11 @@ Symbol_table::add_from_relobj( // section address. The section address in an object // file is normally zero, but people can use a linker // script to change it. - sw.put_st_value(sym2.get_st_value() - + relobj->section_address(st_shndx)); + sw.put_st_value(sym.get_st_value() + + relobj->section_address(orig_st_shndx)); } + st_shndx = elfcpp::SHN_ABS; + is_ordinary = false; psym = &sym2; } @@ -853,7 +866,8 @@ Symbol_table::add_from_relobj( Stringpool::Key name_key; name = this->namepool_.add(name, true, &name_key); res = this->add_from_object(relobj, name, name_key, NULL, 0, - false, *psym, sym); + false, *psym, st_shndx, is_ordinary, + orig_st_shndx); if (local) this->force_local(res); } @@ -866,7 +880,8 @@ Symbol_table::add_from_relobj( ver = this->namepool_.add(ver, true, &ver_key); res = this->add_from_object(relobj, name, name_key, ver, ver_key, - def, *psym, sym); + def, *psym, st_shndx, is_ordinary, + orig_st_shndx); } (*sympointers)[i] = res; @@ -937,6 +952,10 @@ Symbol_table::add_from_dynobj( const char* name = sym_names + st_name; + bool is_ordinary; + unsigned int st_shndx = dynobj->adjust_sym_shndx(i, sym.get_st_shndx(), + &is_ordinary); + Sized_symbol<size>* res; if (versym == NULL) @@ -944,7 +963,8 @@ Symbol_table::add_from_dynobj( Stringpool::Key name_key; name = this->namepool_.add(name, true, &name_key); res = this->add_from_object(dynobj, name, name_key, NULL, 0, - false, sym, sym); + false, sym, st_shndx, is_ordinary, + st_shndx); } else { @@ -963,7 +983,7 @@ Symbol_table::add_from_dynobj( // linker will generate. if (v == static_cast<unsigned int>(elfcpp::VER_NDX_LOCAL) - && sym.get_st_shndx() != elfcpp::SHN_UNDEF) + && st_shndx != elfcpp::SHN_UNDEF) { // This symbol should not be visible outside the object. continue; @@ -978,7 +998,8 @@ Symbol_table::add_from_dynobj( { // This symbol does not have a version. res = this->add_from_object(dynobj, name, name_key, NULL, 0, - false, sym, sym); + false, sym, st_shndx, is_ordinary, + st_shndx); } else { @@ -1005,24 +1026,27 @@ Symbol_table::add_from_dynobj( // version definition symbol. These symbols exist to // support using -u to pull in particular versions. We // do not want to record a version for them. - if (sym.get_st_shndx() == elfcpp::SHN_ABS + if (st_shndx == elfcpp::SHN_ABS + && !is_ordinary && name_key == version_key) res = this->add_from_object(dynobj, name, name_key, NULL, 0, - false, sym, sym); + false, sym, st_shndx, is_ordinary, + st_shndx); else { const bool def = (!hidden - && (sym.get_st_shndx() - != elfcpp::SHN_UNDEF)); + && st_shndx != elfcpp::SHN_UNDEF); res = this->add_from_object(dynobj, name, name_key, version, - version_key, def, sym, sym); + version_key, def, sym, st_shndx, + is_ordinary, st_shndx); } } } // Note that it is possible that RES was overridden by an // earlier object, in which case it can't be aliased here. - if (sym.get_st_shndx() != elfcpp::SHN_UNDEF + if (st_shndx != elfcpp::SHN_UNDEF + && is_ordinary && sym.get_st_type() == elfcpp::STT_OBJECT && res->source() == Symbol::FROM_OBJECT && res->object() == dynobj) @@ -1047,8 +1071,14 @@ bool Weak_alias_sorter<size>::operator()(const Sized_symbol<size>* s1, const Sized_symbol<size>* s2) const { - if (s1->shndx() != s2->shndx()) - return s1->shndx() < s2->shndx(); + bool is_ordinary; + unsigned int s1_shndx = s1->shndx(&is_ordinary); + gold_assert(is_ordinary); + unsigned int s2_shndx = s2->shndx(&is_ordinary); + gold_assert(is_ordinary); + if (s1_shndx != s2_shndx) + return s1_shndx < s2_shndx; + if (s1->value() != s2->value()) return s1->value() < s2->value(); if (s1->binding() != s2->binding()) @@ -1091,7 +1121,8 @@ Symbol_table::record_weak_aliases(std::vector<Sized_symbol<size>*>* symbols) typename std::vector<Sized_symbol<size>*>::const_iterator q; for (q = p + 1; q != symbols->end(); ++q) { - if ((*q)->shndx() != from_sym->shndx() + bool dummy; + if ((*q)->shndx(&dummy) != from_sym->shndx(&dummy) || (*q)->value() != from_sym->value()) break; @@ -1798,10 +1829,11 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) { case Symbol::FROM_OBJECT: { - unsigned int shndx = sym->shndx(); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); // FIXME: We need some target specific support here. - if (shndx >= elfcpp::SHN_LORESERVE + if (!is_ordinary && shndx != elfcpp::SHN_ABS && shndx != elfcpp::SHN_COMMON) { @@ -1818,7 +1850,8 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) } else if (shndx == elfcpp::SHN_UNDEF) value = 0; - else if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON) + else if (!is_ordinary + && (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON)) value = sym->value(); else { @@ -1904,32 +1937,39 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) void Symbol_table::write_globals(const Input_objects* input_objects, const Stringpool* sympool, - const Stringpool* dynpool, Output_file* of) const + const Stringpool* dynpool, + Output_symtab_xindex* symtab_xindex, + Output_symtab_xindex* dynsym_xindex, + Output_file* of) const { switch (parameters->size_and_endianness()) { #ifdef HAVE_TARGET_32_LITTLE case Parameters::TARGET_32_LITTLE: this->sized_write_globals<32, false>(input_objects, sympool, - dynpool, of); + dynpool, symtab_xindex, + dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_32_BIG case Parameters::TARGET_32_BIG: this->sized_write_globals<32, true>(input_objects, sympool, - dynpool, of); + dynpool, symtab_xindex, + dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_64_LITTLE case Parameters::TARGET_64_LITTLE: this->sized_write_globals<64, false>(input_objects, sympool, - dynpool, of); + dynpool, symtab_xindex, + dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_64_BIG case Parameters::TARGET_64_BIG: this->sized_write_globals<64, true>(input_objects, sympool, - dynpool, of); + dynpool, symtab_xindex, + dynsym_xindex, of); break; #endif default: @@ -1944,6 +1984,8 @@ void Symbol_table::sized_write_globals(const Input_objects* input_objects, const Stringpool* sympool, const Stringpool* dynpool, + Output_symtab_xindex* symtab_xindex, + Output_symtab_xindex* dynsym_xindex, Output_file* of) const { const Target& target = parameters->target(); @@ -1998,10 +2040,11 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, { case Symbol::FROM_OBJECT: { - unsigned int in_shndx = sym->shndx(); + bool is_ordinary; + unsigned int in_shndx = sym->shndx(&is_ordinary); // FIXME: We need some target specific support here. - if (in_shndx >= elfcpp::SHN_LORESERVE + if (!is_ordinary && in_shndx != elfcpp::SHN_ABS && in_shndx != elfcpp::SHN_COMMON) { @@ -2019,8 +2062,9 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, shndx = elfcpp::SHN_UNDEF; } else if (in_shndx == elfcpp::SHN_UNDEF - || in_shndx == elfcpp::SHN_ABS - || in_shndx == elfcpp::SHN_COMMON) + || (!is_ordinary + && (in_shndx == elfcpp::SHN_ABS + || in_shndx == elfcpp::SHN_COMMON))) shndx = in_shndx; else { @@ -2031,6 +2075,15 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, gold_assert(os != NULL); shndx = os->out_shndx(); + if (shndx >= elfcpp::SHN_LORESERVE) + { + if (sym_index != -1U) + symtab_xindex->add(sym_index, shndx); + if (dynsym_index != -1U) + dynsym_xindex->add(dynsym_index, shndx); + shndx = elfcpp::SHN_XINDEX; + } + // In object files symbol values are section // relative. if (parameters->options().relocatable()) @@ -2042,6 +2095,14 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, case Symbol::IN_OUTPUT_DATA: shndx = sym->output_data()->out_shndx(); + if (shndx >= elfcpp::SHN_LORESERVE) + { + if (sym_index != -1U) + symtab_xindex->add(sym_index, shndx); + if (dynsym_index != -1U) + dynsym_xindex->add(dynsym_index, shndx); + shndx = elfcpp::SHN_XINDEX; + } break; case Symbol::IN_OUTPUT_SEGMENT: @@ -2125,9 +2186,10 @@ Symbol_table::warn_about_undefined_dynobj_symbol( const Input_objects* input_objects, Symbol* sym) const { + bool dummy; if (sym->source() == Symbol::FROM_OBJECT && sym->object()->is_dynamic() - && sym->shndx() == elfcpp::SHN_UNDEF + && sym->shndx(&dummy) == elfcpp::SHN_UNDEF && sym->binding() != elfcpp::STB_WEAK && !parameters->options().allow_shlib_undefined() && !parameters->target().is_defined_by_abi(sym) @@ -2146,6 +2208,7 @@ Symbol_table::warn_about_undefined_dynobj_symbol( void Symbol_table::write_section_symbol(const Output_section *os, + Output_symtab_xindex* symtab_xindex, Output_file* of, off_t offset) const { @@ -2153,22 +2216,26 @@ Symbol_table::write_section_symbol(const Output_section *os, { #ifdef HAVE_TARGET_32_LITTLE case Parameters::TARGET_32_LITTLE: - this->sized_write_section_symbol<32, false>(os, of, offset); + this->sized_write_section_symbol<32, false>(os, symtab_xindex, of, + offset); break; #endif #ifdef HAVE_TARGET_32_BIG case Parameters::TARGET_32_BIG: - this->sized_write_section_symbol<32, true>(os, of, offset); + this->sized_write_section_symbol<32, true>(os, symtab_xindex, of, + offset); break; #endif #ifdef HAVE_TARGET_64_LITTLE case Parameters::TARGET_64_LITTLE: - this->sized_write_section_symbol<64, false>(os, of, offset); + this->sized_write_section_symbol<64, false>(os, symtab_xindex, of, + offset); break; #endif #ifdef HAVE_TARGET_64_BIG case Parameters::TARGET_64_BIG: - this->sized_write_section_symbol<64, true>(os, of, offset); + this->sized_write_section_symbol<64, true>(os, symtab_xindex, of, + offset); break; #endif default: @@ -2181,6 +2248,7 @@ Symbol_table::write_section_symbol(const Output_section *os, template<int size, bool big_endian> void Symbol_table::sized_write_section_symbol(const Output_section* os, + Output_symtab_xindex* symtab_xindex, Output_file* of, off_t offset) const { @@ -2195,7 +2263,14 @@ Symbol_table::sized_write_section_symbol(const Output_section* os, osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, elfcpp::STT_SECTION)); osym.put_st_other(elfcpp::elf_st_other(elfcpp::STV_DEFAULT, 0)); - osym.put_st_shndx(os->out_shndx()); + + unsigned int shndx = os->out_shndx(); + if (shndx >= elfcpp::SHN_LORESERVE) + { + symtab_xindex->add(os->symtab_index(), shndx); + shndx = elfcpp::SHN_XINDEX; + } + osym.put_st_shndx(shndx); of->write_output_view(offset, sym_size, pov); } @@ -2359,6 +2434,7 @@ Symbol_table::add_from_relobj<32, false>( Sized_relobj<32, false>* relobj, const unsigned char* syms, size_t count, + size_t symndx_offset, const char* sym_names, size_t sym_name_size, Sized_relobj<32, true>::Symbols* sympointers); @@ -2371,6 +2447,7 @@ Symbol_table::add_from_relobj<32, true>( Sized_relobj<32, true>* relobj, const unsigned char* syms, size_t count, + size_t symndx_offset, const char* sym_names, size_t sym_name_size, Sized_relobj<32, false>::Symbols* sympointers); @@ -2383,6 +2460,7 @@ Symbol_table::add_from_relobj<64, false>( Sized_relobj<64, false>* relobj, const unsigned char* syms, size_t count, + size_t symndx_offset, const char* sym_names, size_t sym_name_size, Sized_relobj<64, true>::Symbols* sympointers); @@ -2395,6 +2473,7 @@ Symbol_table::add_from_relobj<64, true>( Sized_relobj<64, true>* relobj, const unsigned char* syms, size_t count, + size_t symndx_offset, const char* sym_names, size_t sym_name_size, Sized_relobj<64, false>::Symbols* sympointers); diff --git a/gold/symtab.h b/gold/symtab.h index a4c1e78..1ee3131 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -52,6 +52,7 @@ class Output_data; class Output_section; class Output_segment; class Output_file; +class Output_symtab_xindex; // The base class of an entry in the symbol table. The symbol table // can have a lot of entries, so we don't want this class to big. @@ -142,9 +143,10 @@ class Symbol // Return the index of the section in the input relocatable or // dynamic object file. unsigned int - shndx() const + shndx(bool* is_ordinary) const { gold_assert(this->source_ == FROM_OBJECT); + *is_ordinary = this->is_ordinary_shndx_; return this->u_.from_object.shndx; } @@ -386,9 +388,13 @@ class Symbol bool is_defined() const { - return (this->source_ != FROM_OBJECT - || (this->shndx() != elfcpp::SHN_UNDEF - && this->shndx() != elfcpp::SHN_COMMON)); + bool is_ordinary; + if (this->source_ != FROM_OBJECT) + return true; + unsigned int shndx = this->shndx(&is_ordinary); + return (is_ordinary + ? shndx != elfcpp::SHN_UNDEF + : shndx != elfcpp::SHN_COMMON); } // Return true if this symbol is from a dynamic object. @@ -402,31 +408,41 @@ class Symbol bool is_undefined() const { - return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_UNDEF; + bool is_ordinary; + return (this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF + && is_ordinary); } // Return whether this is a weak undefined symbol. bool is_weak_undefined() const { + bool is_ordinary; return (this->source_ == FROM_OBJECT && this->binding() == elfcpp::STB_WEAK - && this->shndx() == elfcpp::SHN_UNDEF); + && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF + && is_ordinary); } // Return whether this is an absolute symbol. bool is_absolute() const { - return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_ABS; + bool is_ordinary; + return (this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_ABS + && !is_ordinary); } // Return whether this is a common symbol. bool is_common() const { + bool is_ordinary; return (this->source_ == FROM_OBJECT - && (this->shndx() == elfcpp::SHN_COMMON + && ((this->shndx(&is_ordinary) == elfcpp::SHN_COMMON + && !is_ordinary) || this->type_ == elfcpp::STT_COMMON)); } @@ -619,11 +635,14 @@ class Symbol elfcpp::STT type, elfcpp::STB binding, elfcpp::STV visibility, unsigned char nonvis); - // Initialize fields from an ELF symbol in OBJECT. + // Initialize fields from an ELF symbol in OBJECT. ST_SHNDX is the + // section index, IS_ORDINARY is whether it is a normal section + // index rather than a special code. template<int size, bool big_endian> void init_base(const char *name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>&); + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); // Initialize fields for an Output_data. void @@ -644,8 +663,8 @@ class Symbol // Override existing symbol. template<int size, bool big_endian> void - override_base(const elfcpp::Sym<size, big_endian>&, Object* object, - const char* version); + override_base(const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary, Object* object, const char* version); // Override existing symbol with a special symbol. void @@ -725,20 +744,20 @@ class Symbol // section. unsigned int plt_offset_; - // Symbol type. + // Symbol type (bits 0 to 3). elfcpp::STT type_ : 4; - // Symbol binding. + // Symbol binding (bits 4 to 7). elfcpp::STB binding_ : 4; - // Symbol visibility. + // Symbol visibility (bits 8 to 9). elfcpp::STV visibility_ : 2; - // Rest of symbol st_other field. + // Rest of symbol st_other field (bits 10 to 15). unsigned int nonvis_ : 6; - // The type of symbol. + // The type of symbol (bits 16 to 18). Source source_ : 3; // True if this symbol always requires special target-specific - // handling. + // handling (bit 19). bool is_target_special_ : 1; - // True if this is the default version of the symbol. + // True if this is the default version of the symbol (bit 20). bool is_def_ : 1; // True if this symbol really forwards to another symbol. This is // used when we discover after the fact that two different entries @@ -746,30 +765,35 @@ class Symbol // never be set for a symbol found in the hash table, but may be set // for a symbol found in the list of symbols attached to an Object. // It forwards to the symbol found in the forwarders_ map of - // Symbol_table. + // Symbol_table (bit 21). bool is_forwarder_ : 1; // True if the symbol has an alias in the weak_aliases table in - // Symbol_table. + // Symbol_table (bit 22). bool has_alias_ : 1; - // True if this symbol needs to be in the dynamic symbol table. + // True if this symbol needs to be in the dynamic symbol table (bit + // 23). bool needs_dynsym_entry_ : 1; - // True if we've seen this symbol in a regular object. + // True if we've seen this symbol in a regular object (bit 24). bool in_reg_ : 1; - // True if we've seen this symbol in a dynamic object. + // True if we've seen this symbol in a dynamic object (bit 25). bool in_dyn_ : 1; - // True if the symbol has an entry in the PLT section. + // True if the symbol has an entry in the PLT section (bit 26). bool has_plt_offset_ : 1; // True if this is a dynamic symbol which needs a special value in - // the dynamic symbol table. + // the dynamic symbol table (bit 27). bool needs_dynsym_value_ : 1; - // True if there is a warning for this symbol. + // True if there is a warning for this symbol (bit 28). bool has_warning_ : 1; // True if we are using a COPY reloc for this symbol, so that the - // real definition lives in a dynamic object. + // real definition lives in a dynamic object (bit 29). bool is_copied_from_dynobj_ : 1; // True if this symbol was forced to local visibility by a version - // script. + // script (bit 30). bool is_forced_local_ : 1; + // True if the field u_.from_object.shndx is an ordinary section + // index, not one of the special codes from SHN_LORESERVE to + // SHN_HIRESERVE. + bool is_ordinary_shndx_ : 1; }; // The parts of a symbol which are size specific. Using a template @@ -785,11 +809,14 @@ class Sized_symbol : public Symbol Sized_symbol() { } - // Initialize fields from an ELF symbol in OBJECT. + // Initialize fields from an ELF symbol in OBJECT. ST_SHNDX is the + // section index, IS_ORDINARY is whether it is a normal section + // index rather than a special code. template<bool big_endian> void init(const char *name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>&); + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); // Initialize fields for an Output_data. void @@ -811,8 +838,8 @@ class Sized_symbol : public Symbol // Override existing symbol. template<bool big_endian> void - override(const elfcpp::Sym<size, big_endian>&, Object* object, - const char* version); + override(const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary, Object* object, const char* version); // Override existing symbol with a special symbol. void @@ -1011,14 +1038,16 @@ class Symbol_table ~Symbol_table(); // Add COUNT external symbols from the relocatable object RELOBJ to - // the symbol table. SYMS is the symbols, SYM_NAMES is their names, - // SYM_NAME_SIZE is the size of SYM_NAMES. This sets SYMPOINTERS to - // point to the symbols in the symbol table. + // the symbol table. SYMS is the symbols, SYMNDX_OFFSET is the + // offset in the symbol table of the first symbol, SYM_NAMES is + // their names, SYM_NAME_SIZE is the size of SYM_NAMES. This sets + // SYMPOINTERS to point to the symbols in the symbol table. template<int size, bool big_endian> void add_from_relobj(Sized_relobj<size, big_endian>* relobj, const unsigned char* syms, size_t count, - const char* sym_names, size_t sym_name_size, + size_t symndx_offset, const char* sym_names, + size_t sym_name_size, typename Sized_relobj<size, big_endian>::Symbols*); // Add COUNT dynamic symbols from the dynamic object DYNOBJ to the @@ -1161,11 +1190,13 @@ class Symbol_table // Write out the global symbols. void write_globals(const Input_objects*, const Stringpool*, const Stringpool*, + Output_symtab_xindex*, Output_symtab_xindex*, Output_file*) const; // Write out a section symbol. Return the updated offset. void - write_section_symbol(const Output_section*, Output_file*, off_t) const; + write_section_symbol(const Output_section*, Output_symtab_xindex*, + Output_file*, off_t) const; // Dump statistical information to stderr. void @@ -1193,14 +1224,16 @@ class Symbol_table add_from_object(Object*, const char *name, Stringpool::Key name_key, const char *version, Stringpool::Key version_key, bool def, const elfcpp::Sym<size, big_endian>& sym, - const elfcpp::Sym<size, big_endian>& orig_sym); + unsigned int st_shndx, bool is_ordinary, + unsigned int orig_st_shndx); // Resolve symbols. template<int size, bool big_endian> void resolve(Sized_symbol<size>* to, const elfcpp::Sym<size, big_endian>& sym, - const elfcpp::Sym<size, big_endian>& orig_sym, + unsigned int st_shndx, bool is_ordinary, + unsigned int orig_st_shndx, Object*, const char* version); template<int size, bool big_endian> @@ -1226,6 +1259,7 @@ class Symbol_table void override(Sized_symbol<size>* tosym, const elfcpp::Sym<size, big_endian>& fromsym, + unsigned int st_shndx, bool is_ordinary, Object* object, const char* version); // Whether we should override a symbol with a special symbol which @@ -1317,7 +1351,8 @@ class Symbol_table template<int size, bool big_endian> void sized_write_globals(const Input_objects*, const Stringpool*, - const Stringpool*, Output_file*) const; + const Stringpool*, Output_symtab_xindex*, + Output_symtab_xindex*, Output_file*) const; // Write out a symbol to P. template<int size, bool big_endian> @@ -1334,7 +1369,8 @@ class Symbol_table // Write out a section symbol, specialized for size and endianness. template<int size, bool big_endian> void - sized_write_section_symbol(const Output_section*, Output_file*, off_t) const; + sized_write_section_symbol(const Output_section*, Output_symtab_xindex*, + Output_file*, off_t) const; // The type of the symbol hash table. diff --git a/gold/target-reloc.h b/gold/target-reloc.h index eab3c37..b0d71f5 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -78,10 +78,12 @@ scan_relocs( gold_assert(plocal_syms != NULL); typename elfcpp::Sym<size, big_endian> lsym(plocal_syms + r_sym * sym_size); - const unsigned int shndx = lsym.get_st_shndx(); - if (shndx < elfcpp::SHN_LORESERVE + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(lsym.get_st_shndx())) + && !object->is_section_included(shndx)) { // RELOC is a relocation against a local symbol in a // section we are discarding. We can ignore this @@ -333,10 +335,12 @@ scan_relocatable_relocs( gold_assert(plocal_syms != NULL); typename elfcpp::Sym<size, big_endian> lsym(plocal_syms + r_sym * sym_size); - const unsigned int shndx = lsym.get_st_shndx(); - if (shndx < elfcpp::SHN_LORESERVE + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(lsym.get_st_shndx())) + && !object->is_section_included(shndx)) { // RELOC is a relocation against a local symbol // defined in a section we are discarding. Discard @@ -428,7 +432,10 @@ relocate_for_relocatable( // the output section corresponding to input section // in which this symbol is defined. gold_assert(r_sym < local_count); - unsigned int shndx = object->local_symbol_input_shndx(r_sym); + bool is_ordinary; + unsigned int shndx = + object->local_symbol_input_shndx(r_sym, &is_ordinary); + gold_assert(is_ordinary); section_offset_type dummy; Output_section* os = object->output_section(shndx, &dummy); gold_assert(os != NULL); diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index fc4e78b..c538aca 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -43,6 +43,8 @@ MOSTLYCLEANFILES = *.so check_SCRIPTS = check_DATA = check_PROGRAMS = +BUILT_SOURCES = + TESTS = $(check_SCRIPTS) $(check_PROGRAMS) # --------------------------------------------------------------------- @@ -548,6 +550,32 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC endif TLS +check_PROGRAMS += many_sections_test +many_sections_test_SOURCES = many_sections_test.cc +many_sections_test_DEPENDENCIES = gcctestdir/ld +many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic + +BUILT_SOURCES += many_sections_define.h +many_sections_define.h: + (for i in `seq 1 70000`; do \ + echo "int var_$$i __attribute__((section(\"section_$$i\"))) = $$i;"; \ + done) > $@.tmp + mv -f $@.tmp $@ + +BUILT_SOURCES += many_sections_check.h +many_sections_check.h: + (for i in `seq 1 70000`; do \ + echo "assert(var_$$i == $$i);"; \ + done) > $@.tmp + mv -f $@.tmp $@ + +check_PROGRAMS += many_sections_r_test +many_sections_r_test_SOURCES = +many_sections_r_test_DEPENDENCIES = gcctestdir/ld many_sections_r_test.o +many_sections_r_test_LDFLAGS = -Bgcctestdir/ +many_sections_r_test_LDADD = many_sections_r_test.o +many_sections_r_test.o: many_sections_test.o gcctestdir/ld + gcctestdir/ld -r -o $@ many_sections_test.o if CONSTRUCTOR_PRIORITY diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 8896a3f..c47de28 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -47,7 +47,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \ - $(am__EXEEXT_13) $(am__EXEEXT_14) + $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = basic_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test basic_pic_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test \ @@ -155,7 +155,18 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__append_9 = tls_static_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@ tls_static_pic_test @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_10 = tls_shared_nonpic_test -@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_11 = initpri1 +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_11 = many_sections_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test +@GCC_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ +@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_12 = many_sections_define.h \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_13 = initpri1 @CONSTRUCTOR_PRIORITY_FALSE@initpri1_DEPENDENCIES = libgoldtest.a \ @CONSTRUCTOR_PRIORITY_FALSE@ ../libgold.a \ @CONSTRUCTOR_PRIORITY_FALSE@ ../../libiberty/libiberty.a \ @@ -172,7 +183,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ # Test --detect-odr-violations # Similar to --detect-odr-violations: check for undefined symbols in .so's -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_12 = debug_msg.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = debug_msg.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh \ @@ -186,7 +197,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ # We also want to make sure we do something reasonable when there's no # debug info available. For the best test, we use .so's. -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_13 = debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = debug_msg.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_2.syms \ @@ -195,7 +206,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = debug_msg.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err \ @@ -204,17 +215,17 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout # Test -o when emitting to a special file (such as something in /dev). -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = flagstest_o_specialfile +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = flagstest_o_specialfile # Test --compress-debug-sections. FIXME: check we actually compress. # The specialfile output has a tricky case when we also compress debug # sections, because it requires output-file resizing. -@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = flagstest_compress_debug_sections \ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_18 = flagstest_compress_debug_sections \ @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections # Test symbol versioning. -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = ver_test ver_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = ver_test ver_test_2 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6 script_test_1 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test script_test_3 @@ -318,11 +329,14 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__EXEEXT_9 = tls_static_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@ tls_static_pic_test$(EXEEXT) @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__EXEEXT_10 = tls_shared_nonpic_test$(EXEEXT) -@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_11 = initpri1$(EXEEXT) -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_12 = flagstest_o_specialfile$(EXEEXT) -@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_13 = flagstest_compress_debug_sections$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_11 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test$(EXEEXT) +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_12 = initpri1$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_13 = flagstest_o_specialfile$(EXEEXT) +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_14 = flagstest_compress_debug_sections$(EXEEXT) \ @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_14 = ver_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_15 = ver_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT) \ @@ -464,6 +478,13 @@ am__justsyms_SOURCES_DIST = justsyms_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT) justsyms_OBJECTS = $(am_justsyms_OBJECTS) justsyms_LDADD = $(LDADD) +am_many_sections_r_test_OBJECTS = +many_sections_r_test_OBJECTS = $(am_many_sections_r_test_OBJECTS) +am__many_sections_test_SOURCES_DIST = many_sections_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_many_sections_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_test.$(OBJEXT) +many_sections_test_OBJECTS = $(am_many_sections_test_OBJECTS) +many_sections_test_LDADD = $(LDADD) am_object_unittest_OBJECTS = object_unittest.$(OBJEXT) object_unittest_OBJECTS = $(am_object_unittest_OBJECTS) object_unittest_LDADD = $(LDADD) @@ -710,6 +731,7 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ flagstest_o_specialfile_and_compress_debug_sections.c \ $(initpri1_SOURCES) $(justsyms_SOURCES) \ + $(many_sections_r_test_SOURCES) $(many_sections_test_SOURCES) \ $(object_unittest_SOURCES) $(script_test_1_SOURCES) \ $(script_test_2_SOURCES) script_test_3.c \ $(tls_pic_test_SOURCES) $(tls_shared_gd_to_ie_test_SOURCES) \ @@ -755,6 +777,8 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ flagstest_o_specialfile_and_compress_debug_sections.c \ $(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \ + $(many_sections_r_test_SOURCES) \ + $(am__many_sections_test_SOURCES_DIST) \ $(object_unittest_SOURCES) $(am__script_test_1_SOURCES_DIST) \ $(am__script_test_2_SOURCES_DIST) script_test_3.c \ $(am__tls_pic_test_SOURCES_DIST) \ @@ -956,13 +980,14 @@ TEST_STRIP = $(top_builddir)/../binutils/strip-new # .o's), but not all of them (such as .so's and .err files). We # improve on that here. automake-1.9 info docs say "mostlyclean" is # the right choice for files 'make' builds that people rebuild. -MOSTLYCLEANFILES = *.so $(am__append_14) +MOSTLYCLEANFILES = *.so $(am__append_16) # We will add to these later, for each individual test. Note # that we add each test under check_SCRIPTS or check_PROGRAMS; # the TESTS variable is automatically populated from these. -check_SCRIPTS = $(am__append_12) -check_DATA = $(am__append_13) +check_SCRIPTS = $(am__append_14) +check_DATA = $(am__append_15) +BUILT_SOURCES = $(am__append_12) TESTS = $(check_SCRIPTS) $(check_PROGRAMS) # --------------------------------------------------------------------- @@ -1216,6 +1241,13 @@ binary_unittest_SOURCES = binary_unittest.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_DEPENDENCIES = gcctestdir/ld tls_test_shared_nonpic.so @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_LDADD = tls_test_shared_nonpic.so -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_SOURCES = many_sections_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test_SOURCES = +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test_DEPENDENCIES = gcctestdir/ld many_sections_r_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test_LDADD = many_sections_r_test.o @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_SOURCES = initpri1.c @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_DEPENDENCIES = gcctestdir/ld @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_LDFLAGS = -Bgcctestdir/ @@ -1243,7 +1275,8 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_SOURCES = binary_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_DEPENDENCIES = gcctestdir/ld binary.txt @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_LDFLAGS = -Bgcctestdir/ -Wl,--format,binary,binary.txt,--format,elf -all: all-am +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .cc .o .obj @@ -1376,6 +1409,12 @@ initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES) justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES) @rm -f justsyms$(EXEEXT) $(CXXLINK) $(justsyms_LDFLAGS) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS) +many_sections_r_test$(EXEEXT): $(many_sections_r_test_OBJECTS) $(many_sections_r_test_DEPENDENCIES) + @rm -f many_sections_r_test$(EXEEXT) + $(LINK) $(many_sections_r_test_LDFLAGS) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) +many_sections_test$(EXEEXT): $(many_sections_test_OBJECTS) $(many_sections_test_DEPENDENCIES) + @rm -f many_sections_test$(EXEEXT) + $(CXXLINK) $(many_sections_test_LDFLAGS) $(many_sections_test_OBJECTS) $(many_sections_test_LDADD) $(LIBS) object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES) @rm -f object_unittest$(EXEEXT) $(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS) @@ -1528,6 +1567,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2.Po@am__quote@ @@ -1733,10 +1773,12 @@ check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LIBRARIES) $(check_PROGRAMS) \ $(check_SCRIPTS) $(check_DATA) $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: -install: install-am +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am @@ -1761,6 +1803,7 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-checkLIBRARIES clean-checkPROGRAMS clean-generic \ @@ -1965,6 +2008,18 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared_nonpic.so: tls_test.o tls_test_file2.o tls_test_c.o gcctestdir/ld @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test.o tls_test_file2.o tls_test_c.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_define.h: +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (for i in `seq 1 70000`; do \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "int var_$$i __attribute__((section(\"section_$$i\"))) = $$i;"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ done) > $@.tmp +@GCC_TRUE@@NATIVE_LINKER_TRUE@ mv -f $@.tmp $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_check.h: +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (for i in `seq 1 70000`; do \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "assert(var_$$i == $$i);"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ done) > $@.tmp +@GCC_TRUE@@NATIVE_LINKER_TRUE@ mv -f $@.tmp $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test.o: many_sections_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -r -o $@ many_sections_test.o @GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.o: debug_msg.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation1.o: odr_violation1.cc diff --git a/gold/testsuite/binary_unittest.cc b/gold/testsuite/binary_unittest.cc index 229be7e..44db01e 100644 --- a/gold/testsuite/binary_unittest.cc +++ b/gold/testsuite/binary_unittest.cc @@ -94,13 +94,19 @@ Sized_binary_test(Target* target) Sized_relobj<size, big_endian>* relobj = static_cast<Sized_relobj<size, big_endian>*>(object); typename Sized_relobj<size, big_endian>::Address value; - CHECK(relobj->symbol_section_and_value(0, &value) == 0); + bool is_ordinary; + CHECK(relobj->symbol_section_and_value(0, &value, &is_ordinary) == 0); + CHECK(is_ordinary); CHECK(value == 0); - CHECK(relobj->symbol_section_and_value(1, &value) == 1); + CHECK(relobj->symbol_section_and_value(1, &value, &is_ordinary) == 1); + CHECK(is_ordinary); CHECK(value == 0); - CHECK(relobj->symbol_section_and_value(2, &value) == 1); + CHECK(relobj->symbol_section_and_value(2, &value, &is_ordinary) == 1); + CHECK(is_ordinary); CHECK(static_cast<off_t>(value) == st.st_size); - CHECK(relobj->symbol_section_and_value(3, &value) == elfcpp::SHN_ABS); + CHECK(relobj->symbol_section_and_value(3, &value, &is_ordinary) + == elfcpp::SHN_ABS); + CHECK(!is_ordinary); CHECK(static_cast<off_t>(value) == st.st_size); object->unlock(task); diff --git a/gold/testsuite/many_sections_test.cc b/gold/testsuite/many_sections_test.cc new file mode 100644 index 0000000..dcb1cd2 --- /dev/null +++ b/gold/testsuite/many_sections_test.cc @@ -0,0 +1,37 @@ +// many_sections_test.cc -- test lots of sections for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This program tests having many sections. It uses a generated .h +// files to define 70,000 variables, each in a different section. It +// uses another generated .h file to verify that they all have the +// right value. + +#include <cassert> + +#include "many_sections_define.h" + +int +main(int, char**) +{ +#include "many_sections_check.h" + return 0; +} diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 247f9d0..927ed39 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -998,20 +998,26 @@ Target_x86_64::Scan::local(const General_options&, this->check_non_pic(object, r_type); Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); if (lsym.get_st_type() != elfcpp::STT_SECTION) - { - unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); - rela_dyn->add_local(object, r_sym, r_type, output_section, - data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); - } + rela_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); else { gold_assert(lsym.get_st_value() == 0); - rela_dyn->add_local_section(object, lsym.get_st_shndx(), - r_type, output_section, - data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, + &is_ordinary); + if (!is_ordinary) + object->error(_("section symbol %u has bad shndx %u"), + r_sym, shndx); + else + rela_dyn->add_local_section(object, shndx, + r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); } } break; @@ -1109,11 +1115,18 @@ Target_x86_64::Scan::local(const General_options&, Output_data_got<64, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); - got->add_local_pair_with_rela(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_DTPMOD64, 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + shndx, + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_DTPMOD64, 0); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -1130,11 +1143,18 @@ Target_x86_64::Scan::local(const General_options&, Output_data_got<64, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); - got->add_local_pair_with_rela(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_DESC, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TLSDESC, 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + shndx, + GOT_TYPE_TLS_DESC, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TLSDESC, 0); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); |