]> git.pld-linux.org Git - packages/gdb.git/commitdiff
- support for .gnu.hash.
authorPaweł Sikora <pluto@pld-linux.org>
Mon, 9 Oct 2006 18:42:40 +0000 (18:42 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    gdb-gnu_hash.patch -> 1.1

gdb-gnu_hash.patch [new file with mode: 0644]

diff --git a/gdb-gnu_hash.patch b/gdb-gnu_hash.patch
new file mode 100644 (file)
index 0000000..d782118
--- /dev/null
@@ -0,0 +1,880 @@
+2006-07-10  Jakub Jelinek  <jakub@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);
++        bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
++                 s->contents + hash_entry_size);
++      }
++
++      if (info->emit_gnu_hash)
++      {
++        size_t i, cnt;
++        unsigned char *contents;
++        struct collect_gnu_hash_codes cinfo;
++        bfd_size_type amt;
++        size_t bucketcount;
++
++        memset (&cinfo, 0, sizeof (cinfo));
++
++        /* 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 * 2 * sizeof (unsigned long int);
++        cinfo.hashcodes = bfd_malloc (amt);
++        if (cinfo.hashcodes == NULL)
++          return FALSE;
++
++        cinfo.hashval = cinfo.hashcodes + dynsymcount;
++        cinfo.min_dynindx = -1;
++        cinfo.output_bfd = output_bfd;
++        cinfo.bed = bed;
++
++        /* Put all hash values in HASHCODES.  */
++        elf_link_hash_traverse (elf_hash_table (info),
++                                elf_collect_gnu_hash_codes, &cinfo);
++
++        bucketcount
++          = compute_bucket_count (info, cinfo.hashcodes, cinfo.nsyms, 1);
++
++        if (bucketcount == 0)
++          {
++            free (cinfo.hashcodes);
++            return FALSE;
++          }
++
++        s = bfd_get_section_by_name (dynobj, ".gnu.hash");
++        BFD_ASSERT (s != NULL);
++
++        if (cinfo.nsyms == 0)
++          {
++            /* Empty .gnu.hash section is special.  */
++            BFD_ASSERT (cinfo.min_dynindx == -1);
++            free (cinfo.hashcodes);
++            s->size = 5 * 4 + bed->s->arch_size / 8;
++            contents = bfd_zalloc (output_bfd, s->size);
++            if (contents == NULL)
++              return FALSE;
++            s->contents = contents;
++            /* 1 empty bucket.  */
++            bfd_put_32 (output_bfd, 1, contents);
++            /* SYMIDX above the special symbol 0.  */
++            bfd_put_32 (output_bfd, 1, contents + 4);
++            /* Just one word for bitmask.  */
++            bfd_put_32 (output_bfd, 1, contents + 8);
++            /* Only hash fn bloom filter.  */
++            bfd_put_32 (output_bfd, 0, contents + 12);
++            /* No hashes are valid - empty bitmask.  */
++            bfd_put (bed->s->arch_size, output_bfd, 0, contents + 16);
++            /* No hashes in the only bucket.  */
++            bfd_put_32 (output_bfd, 0,
++                        contents + 16 + bed->s->arch_size / 8);
++          }
++        else
++          {
++            BFD_ASSERT (cinfo.min_dynindx != -1);
++            unsigned long int maskwords, maskbitslog2;
++
++            maskbitslog2 = bfd_log2 (cinfo.nsyms) + 1;
++            if (maskbitslog2 < 3)
++              maskbitslog2 = 5;
++            else if ((1 << (maskbitslog2 - 2)) & cinfo.nsyms)
++              maskbitslog2 = maskbitslog2 + 3;
++            else
++              maskbitslog2 = maskbitslog2 + 2;
++            if (bed->s->arch_size == 64)
++              {
++                if (maskbitslog2 == 5)
++                  maskbitslog2 = 6;
++                cinfo.shift1 = 6;
++              }
++            else
++              cinfo.shift1 = 5;
++            cinfo.mask = (1 << cinfo.shift1) - 1;
++            cinfo.shift2 = maskbitslog2 + cinfo.shift1;
++            cinfo.maskbits = 1 << maskbitslog2;
++            maskwords = 1 << (maskbitslog2 - cinfo.shift1);
++            amt = bucketcount * sizeof (unsigned long int) * 2;
++            amt += maskwords * sizeof (bfd_vma);
++            cinfo.bitmask = bfd_malloc (amt);
++            if (cinfo.bitmask == NULL)
++              {
++                free (cinfo.hashcodes);
++                return FALSE;
++              }
++
++            cinfo.counts = (void *) (cinfo.bitmask + maskwords);
++            cinfo.indx = cinfo.counts + bucketcount;
++            cinfo.symindx = dynsymcount - cinfo.nsyms;
++            memset (cinfo.bitmask, 0, maskwords * sizeof (bfd_vma));
++
++            /* Determine how often each hash bucket is used.  */
++            memset (cinfo.counts, 0, bucketcount * sizeof (cinfo.counts[0]));
++            for (i = 0; i < cinfo.nsyms; ++i)
++              ++cinfo.counts[cinfo.hashcodes[i] % bucketcount];
++
++            for (i = 0, cnt = cinfo.symindx; i < bucketcount; ++i)
++              if (cinfo.counts[i] != 0)
++                {
++                  cinfo.indx[i] = cnt;
++                  cnt += cinfo.counts[i];
++                }
++            BFD_ASSERT (cnt == dynsymcount);
++            cinfo.bucketcount = bucketcount;
++            cinfo.local_indx = cinfo.min_dynindx;
++
++            s->size = (4 + bucketcount + cinfo.nsyms) * 4;
++            s->size += cinfo.maskbits / 8;
++            contents = bfd_zalloc (output_bfd, s->size);
++            if (contents == NULL)
++              {
++                free (cinfo.bitmask);
++                free (cinfo.hashcodes);
++                return FALSE;
++              }
++
++            s->contents = contents;
++            bfd_put_32 (output_bfd, bucketcount, contents);
++            bfd_put_32 (output_bfd, cinfo.symindx, contents + 4);
++            bfd_put_32 (output_bfd, maskwords, contents + 8);
++            bfd_put_32 (output_bfd, cinfo.shift2, contents + 12);
++            contents += 16 + cinfo.maskbits / 8;
++
++            for (i = 0; i < bucketcount; ++i)
++              {
++                if (cinfo.counts[i] == 0)
++                  bfd_put_32 (output_bfd, 0, contents);
++                else
++                  bfd_put_32 (output_bfd, cinfo.indx[i], contents);
++                contents += 4;
++              }
++
++            cinfo.contents = contents;
++
++            /* Renumber dynamic symbols, populate .gnu.hash section.  */
++            elf_link_hash_traverse (elf_hash_table (info),
++                                    elf_renumber_gnu_hash_syms, &cinfo);
++
++            contents = s->contents + 16;
++            for (i = 0; i < maskwords; ++i)
++              {
++                bfd_put (bed->s->arch_size, output_bfd, cinfo.bitmask[i],
++                         contents);
++                contents += bed->s->arch_size / 8;
++              }
++
++            free (cinfo.bitmask);
++            free (cinfo.hashcodes);
++          }
++      }
+       s = bfd_get_section_by_name (dynobj, ".dynstr");
+       BFD_ASSERT (s != NULL);
+@@ -6647,9 +6973,6 @@ elf_link_output_extsym (struct elf_link_
+     {
+       size_t bucketcount;
+       size_t bucket;
+-      size_t hash_entry_size;
+-      bfd_byte *bucketpos;
+-      bfd_vma chain;
+       bfd_byte *esym;
+       sym.st_name = h->dynstr_index;
+@@ -6663,15 +6986,23 @@ elf_link_output_extsym (struct elf_link_
+       bucketcount = elf_hash_table (finfo->info)->bucketcount;
+       bucket = h->u.elf_hash_value % bucketcount;
+-      hash_entry_size
+-      = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
+-      bucketpos = ((bfd_byte *) finfo->hash_sec->contents
+-                 + (bucket + 2) * hash_entry_size);
+-      chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos);
+-      bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos);
+-      bfd_put (8 * hash_entry_size, finfo->output_bfd, chain,
+-             ((bfd_byte *) finfo->hash_sec->contents
+-              + (bucketcount + 2 + h->dynindx) * hash_entry_size));
++
++      if (finfo->hash_sec != NULL)
++      {
++        size_t hash_entry_size;
++        bfd_byte *bucketpos;
++        bfd_vma chain;
++
++        hash_entry_size
++          = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
++        bucketpos = ((bfd_byte *) finfo->hash_sec->contents
++                     + (bucket + 2) * hash_entry_size);
++        chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos);
++        bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos);
++        bfd_put (8 * hash_entry_size, finfo->output_bfd, chain,
++                 ((bfd_byte *) finfo->hash_sec->contents
++                  + (bucketcount + 2 + h->dynindx) * hash_entry_size));
++      }
+       if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL)
+       {
+@@ -7845,7 +8176,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
+     {
+       finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
+       finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
+-      BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
++      BFD_ASSERT (finfo.dynsym_sec != NULL);
+       finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
+       /* Note that it is OK if symver_sec is NULL.  */
+     }
+@@ -8591,6 +8922,9 @@ bfd_elf_final_link (bfd *abfd, struct bf
+           case DT_HASH:
+             name = ".hash";
+             goto get_vma;
++          case DT_GNU_HASH:
++            name = ".gnu.hash";
++            goto get_vma;
+           case DT_STRTAB:
+             name = ".dynstr";
+             goto get_vma;
+Index: gdb-6.5/bfd/elfxx-target.h
+===================================================================
+--- gdb-6.5.orig/bfd/elfxx-target.h    2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/bfd/elfxx-target.h 2006-07-14 01:31:26.000000000 -0300
+@@ -553,6 +553,10 @@
+ #define elf_backend_merge_symbol NULL
+ #endif
++#ifndef elf_backend_hash_symbol
++#define elf_backend_hash_symbol _bfd_elf_hash_symbol
++#endif
++
+ extern const struct elf_size_info _bfd_elfNN_size_info;
+ #ifndef INCLUDED_TARGET_FILE
+@@ -630,6 +634,7 @@ static const struct elf_backend_data elf
+   elf_backend_common_section_index,
+   elf_backend_common_section,
+   elf_backend_merge_symbol,
++  elf_backend_hash_symbol,
+   elf_backend_link_order_error_handler,
+   elf_backend_relplt_name,
+   ELF_MACHINE_ALT1,
+Index: gdb-6.5/include/elf/common.h
+===================================================================
+--- gdb-6.5.orig/include/elf/common.h  2006-07-14 01:30:51.000000000 -0300
++++ gdb-6.5/include/elf/common.h       2006-07-14 01:31:26.000000000 -0300
+@@ -338,6 +338,7 @@
+ #define SHT_LOOS      0x60000000      /* First of OS specific semantics */
+ #define SHT_HIOS      0x6fffffff      /* Last of OS specific semantics */
++#define SHT_GNU_HASH  0x6ffffff6      /* GNU style symbol hash table */
+ #define SHT_GNU_LIBLIST       0x6ffffff7      /* List of prelink dependencies */
+ /* The next three section types are defined by Solaris, and are named
+@@ -577,6 +578,7 @@
+ #define DT_VALRNGHI   0x6ffffdff
+ #define DT_ADDRRNGLO  0x6ffffe00
++#define DT_GNU_HASH   0x6ffffef5
+ #define DT_TLSDESC_PLT        0x6ffffef6
+ #define DT_TLSDESC_GOT        0x6ffffef7
+ #define DT_GNU_CONFLICT       0x6ffffef8
+Index: gdb-6.5/include/bfdlink.h
+===================================================================
+--- gdb-6.5.orig/include/bfdlink.h     2006-04-06 15:52:45.000000000 -0300
++++ gdb-6.5/include/bfdlink.h  2006-07-14 01:31:26.000000000 -0300
+@@ -324,6 +324,12 @@ struct bfd_link_info
+   /* TRUE if unreferenced sections should be removed.  */
+   unsigned int gc_sections: 1;
++  /* TRUE if .hash section should be created.  */
++  unsigned int emit_hash: 1;
++
++  /* TRUE if .gnu.hash section should be created.  */
++  unsigned int emit_gnu_hash: 1;
++
+   /* What to do with unresolved symbols in an object file.
+      When producing executables the default is GENERATE_ERROR.
+      When producing shared libraries the default is IGNORE.  The
This page took 0.125203 seconds and 4 git commands to generate.