* 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.
This commit is contained in:
Ian Lance Taylor 2008-04-19 18:30:58 +00:00
parent 8e91f0232c
commit d491d34e93
26 changed files with 1402 additions and 358 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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_;

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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))
{

View File

@ -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(),

View File

@ -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);

View File

@ -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.

View File

@ -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_;

View File

@ -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)";

View File

@ -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

View File

@ -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.

View File

@ -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()

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);