Fix SysV-style hash table when --hash-style=both.

When --hash-style-both is used, gold currently builds the sysv hash
table first, then the gnu hash table. Building the gnu hash table
renumbers the dynamic symbol table, invalidating the sysv hash
table. This patch reverses the order in which the hash tables are
build so that both hash tables are correct.

gold/
	PR gold/13597
	* layout.cc (Layout::create_dynamic_symtab): Build gnu-style
	hash table before sysv-style hash table.
This commit is contained in:
Kito Cheng 2014-09-30 14:36:46 -07:00 committed by Cary Coutant
parent d83ad864a2
commit cd6da0366d
2 changed files with 40 additions and 32 deletions

View File

@ -1,3 +1,9 @@
2014-09-30 Kito Cheng <kito@0xlab.org>
PR gold/13597
* layout.cc (Layout::create_dynamic_symtab): Build gnu-style
hash table before sysv-style hash table.
2014-09-29 Sriraman Tallam <tmsriram@google.com>
* options.h (--pic-executable): Add negative to alias to -no-pie.

View File

@ -4308,38 +4308,9 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
}
}
// Create the hash tables.
if (strcmp(parameters->options().hash_style(), "sysv") == 0
|| strcmp(parameters->options().hash_style(), "both") == 0)
{
unsigned char* phash;
unsigned int hashlen;
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
Output_section* hashsec =
this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH,
elfcpp::SHF_ALLOC, false,
ORDER_DYNAMIC_LINKER, false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
align,
"** hash");
if (hashsec != NULL && hashdata != NULL)
hashsec->add_output_section_data(hashdata);
if (hashsec != NULL)
{
if (dynsym != NULL)
hashsec->set_link_section(dynsym);
hashsec->set_entsize(4);
}
if (odyn != NULL)
odyn->add_section_address(elfcpp::DT_HASH, hashsec);
}
// Create the hash tables. The Gnu-style hash table must be
// built first, because it changes the order of the symbols
// in the dynamic symbol table.
if (strcmp(parameters->options().hash_style(), "gnu") == 0
|| strcmp(parameters->options().hash_style(), "both") == 0)
@ -4376,6 +4347,37 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
}
}
if (strcmp(parameters->options().hash_style(), "sysv") == 0
|| strcmp(parameters->options().hash_style(), "both") == 0)
{
unsigned char* phash;
unsigned int hashlen;
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
Output_section* hashsec =
this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH,
elfcpp::SHF_ALLOC, false,
ORDER_DYNAMIC_LINKER, false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
align,
"** hash");
if (hashsec != NULL && hashdata != NULL)
hashsec->add_output_section_data(hashdata);
if (hashsec != NULL)
{
if (dynsym != NULL)
hashsec->set_link_section(dynsym);
hashsec->set_entsize(4);
}
if (odyn != NULL)
odyn->add_section_address(elfcpp::DT_HASH, hashsec);
}
}
// Assign offsets to each local portion of the dynamic symbol table.