From 13670ee6693f100f4b0b11b3a700d129b9bd67be Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 6 Mar 2008 00:15:04 +0000 Subject: Support --hash-style=gnu. --- elfcpp/elfcpp.h | 4 ++++ gold/layout.cc | 58 +++++++++++++++++++++++++++++++++++++++++---------------- gold/options.h | 4 ++++ 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index 64f7c6c..dae0434 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 1591cfb..124d3bc 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 30ffb8c..7f5a561 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")); -- cgit v1.1