From cd6da0366dc6684d32f349b729b5558258fc3af4 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Tue, 30 Sep 2014 14:36:46 -0700 Subject: [PATCH] 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. --- gold/ChangeLog | 6 +++++ gold/layout.cc | 66 ++++++++++++++++++++++++++------------------------ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 884feb8a13..20f84af51a 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 ef0a879b41..7cbbe39b87 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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.