diff options
author | Kito Cheng <kito@0xlab.org> | 2014-09-30 14:36:46 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2014-09-30 14:36:46 -0700 |
commit | cd6da0366dc6684d32f349b729b5558258fc3af4 (patch) | |
tree | 46eeee4b1d28fffb526e73cff7b068c737355ac7 /gold/layout.cc | |
parent | d83ad864a285fe3127e1a98830197e8461ad2745 (diff) | |
download | gdb-cd6da0366dc6684d32f349b729b5558258fc3af4.zip gdb-cd6da0366dc6684d32f349b729b5558258fc3af4.tar.gz gdb-cd6da0366dc6684d32f349b729b5558258fc3af4.tar.bz2 |
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.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/gold/layout.cc b/gold/layout.cc index ef0a879..7cbbe39 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); } } |