From: Kito Cheng Date: Tue, 30 Sep 2014 21:36:46 +0000 (-0700) Subject: Fix SysV-style hash table when --hash-style=both. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cd6da0366dc6684d32f349b729b5558258fc3af4;p=binutils-gdb.git 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. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index 884feb8a131..20f84af51af 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,9 @@ +2014-09-30 Kito Cheng + + PR gold/13597 + * layout.cc (Layout::create_dynamic_symtab): Build gnu-style + hash table before sysv-style hash table. + 2014-09-29 Sriraman Tallam * options.h (--pic-executable): Add negative to alias to -no-pie. diff --git a/gold/layout.cc b/gold/layout.cc index ef0a879b41c..7cbbe39b87d 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -4308,18 +4308,20 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, } } - // Create the hash tables. + // 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(), "sysv") == 0 + if (strcmp(parameters->options().hash_style(), "gnu") == 0 || strcmp(parameters->options().hash_style(), "both") == 0) { unsigned char* phash; unsigned int hashlen; - Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount, + Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); Output_section* hashsec = - this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, + this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); @@ -4334,23 +4336,28 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, { if (dynsym != NULL) hashsec->set_link_section(dynsym); - hashsec->set_entsize(4); - } - if (odyn != NULL) - odyn->add_section_address(elfcpp::DT_HASH, hashsec); + // For a 64-bit target, the entries in .gnu.hash do not have + // a uniform size, so we only set the entry size for a + // 32-bit target. + if (parameters->target().get_size() == 32) + hashsec->set_entsize(4); + + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + } } - if (strcmp(parameters->options().hash_style(), "gnu") == 0 + if (strcmp(parameters->options().hash_style(), "sysv") == 0 || strcmp(parameters->options().hash_style(), "both") == 0) { unsigned char* phash; unsigned int hashlen; - Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount, + Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); Output_section* hashsec = - this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, + this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); @@ -4365,16 +4372,11 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, { if (dynsym != NULL) hashsec->set_link_section(dynsym); - - // For a 64-bit target, the entries in .gnu.hash do not have - // a uniform size, so we only set the entry size for a - // 32-bit target. - if (parameters->target().get_size() == 32) - hashsec->set_entsize(4); - - if (odyn != NULL) - odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + hashsec->set_entsize(4); } + + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_HASH, hashsec); } }