This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[gold commit] PR gold/13597: Fix SysV-style hash table when --hash-style=both
- From: Cary Coutant <ccoutant at google dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: kito at 0xlab dot org
- Date: Tue, 30 Sep 2014 14:39:33 -0700
- Subject: [gold commit] PR gold/13597: Fix SysV-style hash table when --hash-style=both
- Authentication-results: sourceware.org; auth=none
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.
I've committed this patch on behalf of Kito Cheng, who proposed the
fix over 2 years ago. (Thanks, Kito!)
-cary
2014-09-30 Kito Cheng <kito@0xlab.org>
gold/
PR gold/13597
* layout.cc (Layout::create_dynamic_symtab): Build gnu-style
hash table before sysv-style hash table.
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);
}
}