This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold commit] PR gold/13597: 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.

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);
     }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]