SOURCES: gdb-gnu_hash.patch (NEW) - support for .gnu.hash.
pluto
pluto at pld-linux.org
Mon Oct 9 20:42:45 CEST 2006
Author: pluto Date: Mon Oct 9 18:42:45 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- support for .gnu.hash.
---- Files affected:
SOURCES:
gdb-gnu_hash.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/gdb-gnu_hash.patch
diff -u /dev/null SOURCES/gdb-gnu_hash.patch:1.1
--- /dev/null Mon Oct 9 20:42:45 2006
+++ SOURCES/gdb-gnu_hash.patch Mon Oct 9 20:42:40 2006
@@ -0,0 +1,880 @@
+2006-07-10 Jakub Jelinek <jakub at redhat.com>
+
+include/
+ * bfdlink.h (struct bfd_link_info): Add emit_hash and
+ emit_gnu_hash bitfields.
+include/elf/
+ * common.h (SHT_GNU_HASH, DT_GNU_HASH): Define.
+bfd/
+ * elf.c (_bfd_elf_print_private_bfd_data): Handle DT_GNU_HASH.
+ (bfd_section_from_shdr, elf_fake_sections, assign_section_numbers):
+ Handle SHT_GNU_HASH.
+ (special_sections_g): Include .gnu.hash section.
+ (bfd_elf_gnu_hash): New function.
+ * elf-bfd.h (bfd_elf_gnu_hash, _bfd_elf_hash_symbol): New prototypes.
+ (struct elf_backend_data): Add elf_hash_symbol method.
+ * elflink.c (_bfd_elf_link_create_dynamic_sections): Create .hash
+ only if info->emit_hash, create .gnu.hash section if
+ info->emit_gnu_hash.
+ (struct collect_gnu_hash_codes): New type.
+ (elf_collect_gnu_hash_codes, elf_renumber_gnu_hash_syms,
+ _bfd_elf_hash_symbol): New functions.
+ (compute_bucket_count): Don't compute HASHCODES array, instead add
+ that and NSYMS as arguments. Use bed->s->sizeof_hash_entry
+ instead of bed->s->arch_size / 8. Fix .hash size estimation.
+ When not optimizing, use the number of hashed symbols rather than
+ dynsymcount.
+ (bfd_elf_size_dynamic_sections): Only add DT_HASH if info->emit_hash,
+ and ADD DT_GNU_HASH if info->emit_gnu_hash.
+ (bfd_elf_size_dynsym_hash_dynstr): Size .hash only if info->emit_hash,
+ adjust compute_bucket_count caller. Create and populate .gnu.hash
+ section if info->emit_gnu_hash.
+ (elf_link_output_extsym): Only populate .hash section if
+ finfo->hash_sec != NULL.
+ (bfd_elf_final_link): Adjust assertion. Handle DT_GNU_HASH.
+ * elfxx-target.h (elf_backend_hash_symbol): Define if not yet defined.
+ (elfNN_bed): Add elf_backend_hash_symbol.
+ * elf64-x86-64.c (elf64_x86_64_hash_symbol): New function.
+ (elf_backend_hash_symbol): Define.
+ * elf32-i386.c (elf_i386_hash_symbol): New function.
+ (elf_backend_hash_symbol): Define.
+
+Index: gdb-6.5/bfd/elf-bfd.h
+===================================================================
+--- gdb-6.5.orig/bfd/elf-bfd.h 2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elf-bfd.h 2006-07-14 01:31:25.000000000 -0300
+@@ -1022,6 +1022,9 @@ struct elf_backend_data
+ bfd_boolean *, bfd_boolean *,
+ bfd *, asection **);
+
++ /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
++ bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *);
++
+ /* Used to handle bad SHF_LINK_ORDER input. */
+ bfd_error_handler_type link_order_error_handler;
+
+@@ -1462,6 +1465,8 @@ extern bfd_vma _bfd_elf_section_offset
+
+ extern unsigned long bfd_elf_hash
+ (const char *);
++extern unsigned long bfd_elf_gnu_hash
++ (const char *);
+
+ extern bfd_reloc_status_type bfd_elf_generic_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+@@ -1632,6 +1637,8 @@ extern bfd_boolean _bfd_elf_merge_symbol
+ struct elf_link_hash_entry **, bfd_boolean *,
+ bfd_boolean *, bfd_boolean *, bfd_boolean *);
+
++extern bfd_boolean _bfd_elf_hash_symbol (struct elf_link_hash_entry *);
++
+ extern bfd_boolean _bfd_elf_add_default_symbol
+ (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ const char *, Elf_Internal_Sym *, asection **, bfd_vma *,
+Index: gdb-6.5/bfd/elf64-x86-64.c
+===================================================================
+--- gdb-6.5.orig/bfd/elf64-x86-64.c 2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elf64-x86-64.c 2006-07-14 01:31:26.000000000 -0300
+@@ -3614,6 +3614,19 @@ elf64_x86_64_additional_program_headers
+ return count;
+ }
+
++/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
++
++static bfd_boolean
++elf64_x86_64_hash_symbol (struct elf_link_hash_entry *h)
++{
++ if (h->plt.offset != (bfd_vma) -1
++ && !h->def_regular
++ && !h->pointer_equality_needed)
++ return FALSE;
++
++ return _bfd_elf_hash_symbol (h);
++}
++
+ static const struct bfd_elf_special_section
+ elf64_x86_64_special_sections[]=
+ {
+@@ -3685,5 +3698,7 @@ static const struct bfd_elf_special_sect
+ elf64_x86_64_special_sections
+ #define elf_backend_additional_program_headers \
+ elf64_x86_64_additional_program_headers
++#define elf_backend_hash_symbol \
++ elf64_x86_64_hash_symbol
+
+ #include "elf64-target.h"
+Index: gdb-6.5/bfd/elf.c
+===================================================================
+--- gdb-6.5.orig/bfd/elf.c 2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elf.c 2006-07-14 01:31:26.000000000 -0300
+@@ -206,6 +206,21 @@ bfd_elf_hash (const char *namearg)
+ return h & 0xffffffff;
+ }
+
++/* DT_GNU_HASH hash function. Do not change this function; you will
++ cause invalid hash tables to be generated. */
++
++unsigned long
++bfd_elf_gnu_hash (const char *namearg)
++{
++ const unsigned char *name = (const unsigned char *) namearg;
++ unsigned long h = 5381;
++ unsigned char ch;
++
++ while ((ch = *name++) != '\0')
++ h = (h << 5) + h + ch;
++ return h & 0xffffffff;
++}
++
+ bfd_boolean
+ bfd_elf_mkobject (bfd *abfd)
+ {
+@@ -1239,6 +1254,7 @@ _bfd_elf_print_private_bfd_data (bfd *ab
+ case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
+ case DT_USED: name = "USED"; break;
+ case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
++ case DT_GNU_HASH: name = "GNU_HASH"; break;
+ }
+
+ fprintf (f, " %-11s ", name);
+@@ -1822,6 +1838,7 @@ bfd_section_from_shdr (bfd *abfd, unsign
+ case SHT_FINI_ARRAY: /* .fini_array section. */
+ case SHT_PREINIT_ARRAY: /* .preinit_array section. */
+ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
++ case SHT_GNU_HASH: /* .gnu.hash section. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+
+ case SHT_DYNAMIC: /* Dynamic linking information. */
+@@ -2294,6 +2311,7 @@ static const struct bfd_elf_special_sect
+ { ".gnu.version_r", 14, 0, SHT_GNU_verneed, 0 },
+ { ".gnu.liblist", 12, 0, SHT_GNU_LIBLIST, SHF_ALLOC },
+ { ".gnu.conflict", 13, 0, SHT_RELA, SHF_ALLOC },
++ { ".gnu.hash", 9, 0, SHT_GNU_HASH, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
+ };
+
+@@ -2810,6 +2828,10 @@ elf_fake_sections (bfd *abfd, asection *
+ case SHT_GROUP:
+ this_hdr->sh_entsize = 4;
+ break;
++
++ case SHT_GNU_HASH:
++ this_hdr->sh_entsize = bed->s->arch_size == 64 ? 0 : 4;
++ break;
+ }
+
+ if ((asect->flags & SEC_ALLOC) != 0)
+@@ -3255,6 +3277,7 @@ assign_section_numbers (bfd *abfd, struc
+ break;
+
+ case SHT_HASH:
++ case SHT_GNU_HASH:
+ case SHT_GNU_versym:
+ /* sh_link is the section header index of the symbol table
+ this hash table or version table is for. */
+Index: gdb-6.5/bfd/elf32-i386.c
+===================================================================
+--- gdb-6.5.orig/bfd/elf32-i386.c 2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elf32-i386.c 2006-07-14 01:31:26.000000000 -0300
+@@ -3872,6 +3872,18 @@ elf_i386_plt_sym_val (bfd_vma i, const a
+ return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
+ }
+
++/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
++
++static bfd_boolean
++elf_i386_hash_symbol (struct elf_link_hash_entry *h)
++{
++ if (h->plt.offset != (bfd_vma) -1
++ && !h->def_regular
++ && !h->pointer_equality_needed)
++ return FALSE;
++
++ return _bfd_elf_hash_symbol (h);
++}
+
+ #define TARGET_LITTLE_SYM bfd_elf32_i386_vec
+ #define TARGET_LITTLE_NAME "elf32-i386"
+@@ -3912,6 +3924,7 @@ elf_i386_plt_sym_val (bfd_vma i, const a
+ #define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
+ #define elf_backend_always_size_sections elf_i386_always_size_sections
+ #define elf_backend_plt_sym_val elf_i386_plt_sym_val
++#define elf_backend_hash_symbol elf_i386_hash_symbol
+
+ #include "elf32-target.h"
+
+Index: gdb-6.5/bfd/elflink.c
+===================================================================
+--- gdb-6.5.orig/bfd/elflink.c 2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elflink.c 2006-07-14 01:31:26.000000000 -0300
+@@ -240,12 +240,30 @@ _bfd_elf_link_create_dynamic_sections (b
+ if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"))
+ return FALSE;
+
+- s = bfd_make_section_with_flags (abfd, ".hash",
+- flags | SEC_READONLY);
+- if (s == NULL
+- || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+- return FALSE;
+- elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
++ if (info->emit_hash)
++ {
++ s = bfd_make_section_with_flags (abfd, ".hash", flags | SEC_READONLY);
++ if (s == NULL
++ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
++ return FALSE;
++ elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
++ }
++
++ if (info->emit_gnu_hash)
++ {
++ s = bfd_make_section_with_flags (abfd, ".gnu.hash",
++ flags | SEC_READONLY);
++ if (s == NULL
++ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
++ return FALSE;
++ /* For 64-bit ELF, .gnu.hash is a non-uniform entity size section:
++ 4 32-bit words followed by variable count of 64-bit words, then
++ variable count of 32-bit words. */
++ if (bed->s->arch_size == 64)
++ elf_section_data (s)->this_hdr.sh_entsize = 0;
++ else
++ elf_section_data (s)->this_hdr.sh_entsize = 4;
++ }
+
+ /* Let the backend create the rest of the sections. This lets the
+ backend set the right flags. The backend will normally create
+@@ -4795,6 +4813,131 @@ elf_collect_hash_codes (struct elf_link_
+ return TRUE;
+ }
+
++struct collect_gnu_hash_codes
++{
++ bfd *output_bfd;
++ const struct elf_backend_data *bed;
++ unsigned long int nsyms;
++ unsigned long int maskbits;
++ unsigned long int *hashcodes;
++ unsigned long int *hashval;
++ unsigned long int *indx;
++ unsigned long int *counts;
++ bfd_vma *bitmask;
++ bfd_byte *contents;
++ long int min_dynindx;
++ unsigned long int bucketcount;
++ unsigned long int symindx;
++ long int local_indx;
++ long int shift1, shift2;
++ unsigned long int mask;
++};
++
++/* This function will be called though elf_link_hash_traverse to store
++ all hash value of the exported symbols in an array. */
++
++static bfd_boolean
++elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
++{
++ struct collect_gnu_hash_codes *s = data;
++ const char *name;
++ char *p;
++ unsigned long ha;
++ char *alc = NULL;
++
++ if (h->root.type == bfd_link_hash_warning)
++ h = (struct elf_link_hash_entry *) h->root.u.i.link;
++
++ /* Ignore indirect symbols. These are added by the versioning code. */
++ if (h->dynindx == -1)
++ return TRUE;
++
++ /* Ignore also local symbols and undefined symbols. */
++ if (! (*s->bed->elf_hash_symbol) (h))
++ return TRUE;
++
++ name = h->root.root.string;
++ p = strchr (name, ELF_VER_CHR);
++ if (p != NULL)
++ {
++ alc = bfd_malloc (p - name + 1);
++ memcpy (alc, name, p - name);
++ alc[p - name] = '\0';
++ name = alc;
++ }
++
++ /* Compute the hash value. */
++ ha = bfd_elf_gnu_hash (name);
++
++ /* Store the found hash value in the array for compute_bucket_count,
++ and also for .dynsym reordering purposes. */
++ s->hashcodes[s->nsyms] = ha;
++ s->hashval[h->dynindx] = ha;
++ ++s->nsyms;
++ if (s->min_dynindx < 0 || s->min_dynindx > h->dynindx)
++ s->min_dynindx = h->dynindx;
++
++ if (alc != NULL)
++ free (alc);
++
++ return TRUE;
++}
++
++/* This function will be called though elf_link_hash_traverse to do
++ final dynaminc symbol renumbering. */
++
++static bfd_boolean
++elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
++{
++ struct collect_gnu_hash_codes *s = data;
++ unsigned long int bucket;
++ unsigned long int val;
++
++ if (h->root.type == bfd_link_hash_warning)
++ h = (struct elf_link_hash_entry *) h->root.u.i.link;
++
++ /* Ignore indirect symbols. */
++ if (h->dynindx == -1)
++ return TRUE;
++
++ /* Ignore also local symbols and undefined symbols. */
++ if (! (*s->bed->elf_hash_symbol) (h))
++ {
++ if (h->dynindx >= s->min_dynindx)
++ h->dynindx = s->local_indx++;
++ return TRUE;
++ }
++
++ bucket = s->hashval[h->dynindx] % s->bucketcount;
++ val = (s->hashval[h->dynindx] >> s->shift1)
++ & ((s->maskbits >> s->shift1) - 1);
++ s->bitmask[val] |= ((bfd_vma) 1) << (s->hashval[h->dynindx] & s->mask);
++ s->bitmask[val]
++ |= ((bfd_vma) 1) << ((s->hashval[h->dynindx] >> s->shift2) & s->mask);
++ val = s->hashval[h->dynindx] & ~(unsigned long int) 1;
++ if (s->counts[bucket] == 1)
++ /* Last element terminates the chain. */
++ val |= 1;
++ bfd_put_32 (s->output_bfd, val,
++ s->contents + (s->indx[bucket] - s->symindx) * 4);
++ --s->counts[bucket];
++ h->dynindx = s->indx[bucket]++;
++ return TRUE;
++}
++
++/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
++
++bfd_boolean
++_bfd_elf_hash_symbol (struct elf_link_hash_entry *h)
++{
++ return !(h->forced_local
++ || h->root.type == bfd_link_hash_undefined
++ || h->root.type == bfd_link_hash_undefweak
++ || ((h->root.type == bfd_link_hash_defined
++ || h->root.type == bfd_link_hash_defweak)
++ && h->root.u.def.section->output_section == NULL));
++}
++
+ /* Array used to determine the number of hash table buckets to use
+ based on the number of symbols there are. If there are fewer than
+ 3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets,
+@@ -4816,42 +4959,26 @@ static const size_t elf_buckets[] =
+ Therefore the result is always a good payoff between few collisions
+ (= short chain lengths) and table size. */
+ static size_t
+-compute_bucket_count (struct bfd_link_info *info)
++compute_bucket_count (struct bfd_link_info *info, unsigned long int *hashcodes,
++ unsigned long int nsyms, int gnu_hash)
+ {
+ size_t dynsymcount = elf_hash_table (info)->dynsymcount;
+ size_t best_size = 0;
+- unsigned long int *hashcodes;
+- unsigned long int *hashcodesp;
+ unsigned long int i;
+ bfd_size_type amt;
+
+- /* Compute the hash values for all exported symbols. At the same
+- time store the values in an array so that we could use them for
+- optimizations. */
+- amt = dynsymcount;
+- amt *= sizeof (unsigned long int);
+- hashcodes = bfd_malloc (amt);
+- if (hashcodes == NULL)
+- return 0;
+- hashcodesp = hashcodes;
+-
+- /* Put all hash values in HASHCODES. */
+- elf_link_hash_traverse (elf_hash_table (info),
+- elf_collect_hash_codes, &hashcodesp);
+-
+ /* We have a problem here. The following code to optimize the table
+ size requires an integer type with more the 32 bits. If
+ BFD_HOST_U_64_BIT is set we know about such a type. */
+ #ifdef BFD_HOST_U_64_BIT
+ if (info->optimize)
+ {
+- unsigned long int nsyms = hashcodesp - hashcodes;
+ size_t minsize;
+ size_t maxsize;
+ BFD_HOST_U_64_BIT best_chlen = ~((BFD_HOST_U_64_BIT) 0);
+- unsigned long int *counts ;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
++ unsigned long int *counts;
+
+ /* Possible optimization parameters: if we have NSYMS symbols we say
+ that the hashing table must at least have NSYMS/4 and at most
+@@ -4860,6 +4987,13 @@ compute_bucket_count (struct bfd_link_in
+ if (minsize == 0)
+ minsize = 1;
+ best_size = maxsize = nsyms * 2;
++ if (gnu_hash)
++ {
++ if (minsize < 2)
++ minsize = 2;
++ if ((best_size & 31) == 0)
++ ++best_size;
++ }
+
+ /* Create array where we count the collisions in. We must use bfd_malloc
+ since the size could be large. */
+@@ -4867,10 +5001,7 @@ compute_bucket_count (struct bfd_link_in
+ amt *= sizeof (unsigned long int);
+ counts = bfd_malloc (amt);
+ if (counts == NULL)
+- {
+- free (hashcodes);
+- return 0;
+- }
++ return 0;
+
+ /* Compute the "optimal" size for the hash table. The criteria is a
+ minimal chain length. The minor criteria is (of course) the size
+@@ -4882,6 +5013,9 @@ compute_bucket_count (struct bfd_link_in
+ unsigned long int j;
+ unsigned long int fact;
+
++ if (gnu_hash && (i & 31) == 0)
++ continue;
++
+ memset (counts, '\0', i * sizeof (unsigned long int));
+
+ /* Determine how often each hash bucket is used. */
+@@ -4897,9 +5031,9 @@ compute_bucket_count (struct bfd_link_in
+ # define BFD_TARGET_PAGESIZE (4096)
+ # endif
+
+- /* We in any case need 2 + NSYMS entries for the size values and
+- the chains. */
+- max = (2 + nsyms) * (bed->s->arch_size / 8);
++ /* We in any case need 2 + DYNSYMCOUNT entries for the size values
++ and the chains. */
++ max = (2 + dynsymcount) * bed->s->sizeof_hash_entry;
+
+ # if 1
+ /* Variant 1: optimize for short chains. We add the squares
+@@ -4909,7 +5043,7 @@ compute_bucket_count (struct bfd_link_in
+ max += counts[j] * counts[j];
+
+ /* This adds penalties for the overall size of the table. */
+- fact = i / (BFD_TARGET_PAGESIZE / (bed->s->arch_size / 8)) + 1;
++ fact = i / (BFD_TARGET_PAGESIZE / bed->s->sizeof_hash_entry) + 1;
+ max *= fact * fact;
+ # else
+ /* Variant 2: Optimize a lot more for small table. Here we
+@@ -4920,7 +5054,7 @@ compute_bucket_count (struct bfd_link_in
+
+ /* The overall size of the table is considered, but not as
+ strong as in variant 1, where it is squared. */
+- fact = i / (BFD_TARGET_PAGESIZE / (bed->s->arch_size / 8)) + 1;
++ fact = i / (BFD_TARGET_PAGESIZE / bed->s->sizeof_hash_entry) + 1;
+ max *= fact;
+ # endif
+
+@@ -4943,14 +5077,13 @@ compute_bucket_count (struct bfd_link_in
+ for (i = 0; elf_buckets[i] != 0; i++)
+ {
+ best_size = elf_buckets[i];
+- if (dynsymcount < elf_buckets[i + 1])
++ if (nsyms < elf_buckets[i + 1])
+ break;
+ }
++ if (gnu_hash && best_size < 2)
++ best_size = 2;
+ }
+
+- /* Free the arrays we needed. */
+- free (hashcodes);
+-
+ return best_size;
+ }
+
+@@ -5308,7 +5441,10 @@ bfd_elf_size_dynamic_sections (bfd *outp
+ bfd_size_type strsize;
+
+ strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+- if (!_bfd_elf_add_dynamic_entry (info, DT_HASH, 0)
++ if ((info->emit_hash
++ && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
++ || (info->emit_gnu_hash
++ && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
+ || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+@@ -5710,8 +5846,6 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *ou
+ asection *s;
+ bfd_size_type dynsymcount;
+ unsigned long section_sym_count;
+- size_t bucketcount = 0;
+- size_t hash_entry_size;
+ unsigned int dtagcount;
+
+ dynobj = elf_hash_table (info)->dynobj;
+@@ -5762,23 +5896,215 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *ou
+ memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
+ }
+
++ elf_hash_table (info)->bucketcount = 0;
++
+ /* Compute the size of the hashing table. As a side effect this
+ computes the hash values for all the names we export. */
+- bucketcount = compute_bucket_count (info);
++ if (info->emit_hash)
++ {
++ unsigned long int *hashcodes;
++ unsigned long int *hashcodesp;
++ bfd_size_type amt;
++ unsigned long int nsyms;
++ size_t bucketcount;
++ size_t hash_entry_size;
++
++ /* Compute the hash values for all exported symbols. At the same
++ time store the values in an array so that we could use them for
++ optimizations. */
++ amt = dynsymcount * sizeof (unsigned long int);
++ hashcodes = bfd_malloc (amt);
++ if (hashcodes == NULL)
++ return FALSE;
++ hashcodesp = hashcodes;
+
+- s = bfd_get_section_by_name (dynobj, ".hash");
+- BFD_ASSERT (s != NULL);
+- hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
+- s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
+- s->contents = bfd_zalloc (output_bfd, s->size);
+- if (s->contents == NULL)
+- return FALSE;
++ /* Put all hash values in HASHCODES. */
++ elf_link_hash_traverse (elf_hash_table (info),
++ elf_collect_hash_codes, &hashcodesp);
+
+- bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
+- bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
+- s->contents + hash_entry_size);
++ nsyms = hashcodesp - hashcodes;
++ bucketcount
++ = compute_bucket_count (info, hashcodes, nsyms, 0);
++ free (hashcodes);
+
+- elf_hash_table (info)->bucketcount = bucketcount;
++ if (bucketcount == 0)
++ return FALSE;
++
++ elf_hash_table (info)->bucketcount = bucketcount;
++
++ s = bfd_get_section_by_name (dynobj, ".hash");
++ BFD_ASSERT (s != NULL);
++ hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
++ s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
++ s->contents = bfd_zalloc (output_bfd, s->size);
++ if (s->contents == NULL)
++ return FALSE;
++
++ bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list