summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-03-06 00:15:04 +0000
committerIan Lance Taylor <iant@google.com>2008-03-06 00:15:04 +0000
commit9c17be7085ba9e0241709d9835e93d7834d9d49d (patch)
treebb1f84ec6a7d4832b58039b4f976b92261bf3ac3
parent49fce8a79633d21d9f09d13168d0fa229a2eb670 (diff)
downloadbinutils-redhat-9c17be7085ba9e0241709d9835e93d7834d9d49d.tar.gz
Support --hash-style=gnu.
-rw-r--r--elfcpp/elfcpp.h4
-rw-r--r--gold/layout.cc58
-rw-r--r--gold/options.h4
3 files changed, 50 insertions, 16 deletions
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index 64f7c6c2d1..dae0434699 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -346,6 +346,10 @@ enum SHT
SHT_LOUSER = 0x80000000,
SHT_HIUSER = 0xffffffff,
// The remaining values are not in the standard.
+ // Object attributes.
+ SHT_GNU_ATTRIBUTES = 0x6ffffff5,
+ // GNU style dynamic hash table.
+ SHT_GNU_HASH = 0x6ffffff6,
// List of prelink dependencies.
SHT_GNU_LIBLIST = 0x6ffffff7,
// Versions defined by file.
diff --git a/gold/layout.cc b/gold/layout.cc
index 1591cfb5c9..124d3bcafe 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1924,27 +1924,53 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
// Create the hash tables.
- // FIXME: We need an option to create a GNU hash table.
+ 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);
+
+ Output_section_data* hashdata = new Output_data_const_buffer(phash,
+ hashlen,
+ align);
+ hashsec->add_output_section_data(hashdata);
+
+ hashsec->set_link_section(dynsym);
+ hashsec->set_entsize(4);
- unsigned char* phash;
- unsigned int hashlen;
- Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
- &phash, &hashlen);
+ odyn->add_section_address(elfcpp::DT_HASH, hashsec);
+ }
+
+ if (strcmp(parameters->options().hash_style(), "gnu") == 0
+ || strcmp(parameters->options().hash_style(), "both") == 0)
+ {
+ unsigned char* phash;
+ unsigned int hashlen;
+ Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount,
+ &phash, &hashlen);
- Output_section* hashsec = this->choose_output_section(NULL, ".hash",
- elfcpp::SHT_HASH,
- elfcpp::SHF_ALLOC,
- false);
+ Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
+ elfcpp::SHT_GNU_HASH,
+ elfcpp::SHF_ALLOC,
+ false);
- Output_section_data* hashdata = new Output_data_const_buffer(phash,
- hashlen,
- align);
- hashsec->add_output_section_data(hashdata);
+ Output_section_data* hashdata = new Output_data_const_buffer(phash,
+ hashlen,
+ align);
+ hashsec->add_output_section_data(hashdata);
- hashsec->set_link_section(dynsym);
- hashsec->set_entsize(4);
+ hashsec->set_link_section(dynsym);
+ hashsec->set_entsize(4);
- odyn->add_section_address(elfcpp::DT_HASH, hashsec);
+ odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
+ }
}
// Assign offsets to each local portion of the dynamic symbol table.
diff --git a/gold/options.h b/gold/options.h
index 30ffb8c546..7f5a561130 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -465,6 +465,10 @@ class General_options
DEFINE_string(soname, options::ONE_DASH, 'h', NULL,
_("Set shared library name"), _("FILENAME"));
+ DEFINE_enum(hash_style, options::TWO_DASHES, '\0', "sysv",
+ _("Dynamic hash style"), _("[sysv,gnu,both]"),
+ {"sysv", "gnu", "both"});
+
DEFINE_string(dynamic_linker, options::TWO_DASHES, 'I', NULL,
_("Set dynamic linker path"), _("PROGRAM"));