Add Xtensa port
[deliverable/binutils-gdb.git] / bfd / elf-strtab.c
index 44d6fc8b29b4cdc40644b673c16a7d5a30e5ef21..3bd5531a81d9bf4026b772a00694a14dc8def034 100644 (file)
@@ -1,28 +1,29 @@
 /* ELF strtab with GC and suffix merging support.
-   Copyright 2001 Free Software Foundation, Inc.
+   Copyright 2001, 2002 Free Software Foundation, Inc.
    Written by Jakub Jelinek <jakub@redhat.com>.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "hashtab.h"
+#include "libiberty.h"
 
 /* An entry in the strtab hash table.  */
 
@@ -37,6 +38,7 @@ struct elf_strtab_hash_entry
     bfd_size_type index;
     /* Entry this is a suffix of (if len is 0).  */
     struct elf_strtab_hash_entry *suffix;
+    struct elf_strtab_hash_entry *next;
   } u;
 };
 
@@ -59,7 +61,6 @@ static struct bfd_hash_entry *elf_strtab_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 static int cmplengthentry PARAMS ((const PTR, const PTR));
 static int last4_eq PARAMS ((const PTR, const PTR));
-static int last_eq PARAMS ((const PTR, const PTR));
 
 /* Routine to create an entry in a section merge hashtab.  */
 
@@ -147,7 +148,7 @@ bfd_size_type
 _bfd_elf_strtab_add (tab, str, copy)
      struct elf_strtab_hash *tab;
      const char *str;
-     boolean copy;
+     bfd_boolean copy;
 {
   register struct elf_strtab_hash_entry *entry;
 
@@ -158,7 +159,7 @@ _bfd_elf_strtab_add (tab, str, copy)
 
   BFD_ASSERT (tab->sec_size == 0);
   entry = (struct elf_strtab_hash_entry *)
-         bfd_hash_lookup (&tab->table, str, true, copy);
+         bfd_hash_lookup (&tab->table, str, TRUE, copy);
 
   if (entry == NULL)
     return (bfd_size_type) -1;
@@ -242,7 +243,7 @@ _bfd_elf_strtab_offset (tab, idx)
   return tab->array[idx]->u.index;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_strtab_emit (abfd, tab)
      register bfd *abfd;
      struct elf_strtab_hash *tab;
@@ -250,7 +251,7 @@ _bfd_elf_strtab_emit (abfd, tab)
   bfd_size_type off = 1, i;
 
   if (bfd_bwrite ("", 1, abfd) != 1)
-    return false;
+    return FALSE;
 
   for (i = 1; i < tab->size; ++i)
     {
@@ -264,13 +265,13 @@ _bfd_elf_strtab_emit (abfd, tab)
        continue;
 
       if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len)
-       return false;
+       return FALSE;
 
       off += len;
     }
 
   BFD_ASSERT (off == tab->sec_size);
-  return true;
+  return TRUE;
 }
 
 /* Compare two elf_strtab_hash_entry structures.  This is called via qsort.  */
@@ -313,33 +314,6 @@ last4_eq (a, b)
                 B->root.string, B->len - 5) == 0;
 }
 
-static int
-last_eq (a, b)
-     const PTR a;
-     const PTR b;
-{
-  struct elf_strtab_hash_entry * A = (struct elf_strtab_hash_entry *) a;
-  struct elf_strtab_hash_entry * B = (struct elf_strtab_hash_entry *) b;
-
-  if (B->len >= 5)
-    /* Longer strings are just pushed into the hash table,
-       they'll be used when looking up for very short strings.  */
-    return 0;
-
-  if (memcmp (A->root.string + A->len - 2, B->root.string + B->len - 2, 1)
-      != 0)
-    /* This was a hashtable collision.  */
-    return 0;
-
-  if (A->len <= B->len)
-    /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
-       not to be equal by the hash table.  */
-    return 0;
-
-  return memcmp (A->root.string + (A->len - B->len),
-                B->root.string, B->len - 2) == 0;
-}
-
 /* This function assigns final string table offsets for used strings,
    merging strings matching suffixes of longer strings if possible.  */
 
@@ -348,8 +322,9 @@ _bfd_elf_strtab_finalize (tab)
      struct elf_strtab_hash *tab;
 {
   struct elf_strtab_hash_entry **array, **a, **end, *e;
-  htab_t lasttab = NULL, last4tab = NULL;
+  htab_t last4tab = NULL;
   bfd_size_type size, amt;
+  struct elf_strtab_hash_entry *last[256], **last_ptr[256];
 
   /* GCC 2.91.66 (egcs-1.1.2) on i386 miscompiles this function when i is
      a 64-bit bfd_size_type: a 64-bit target or --enable-64-bit-bfd.
@@ -364,6 +339,9 @@ _bfd_elf_strtab_finalize (tab)
   if (array == NULL)
     goto alloc_failure;
 
+  memset (last, 0, sizeof (last));
+  for (i = 0; i < 256; ++i)
+    last_ptr[i] = &last[i];
   for (i = 1, a = array; i < tab->size; ++i)
     if (tab->array[i]->refcount)
       *a++ = tab->array[i];
@@ -374,9 +352,8 @@ _bfd_elf_strtab_finalize (tab)
 
   qsort (array, size, sizeof (struct elf_strtab_hash_entry *), cmplengthentry);
 
-  last4tab = htab_create (size * 4, NULL, last4_eq, NULL);
-  lasttab = htab_create (size * 4, NULL, last_eq, NULL);
-  if (lasttab == NULL || last4tab == NULL)
+  last4tab = htab_create_alloc (size * 4, NULL, last4_eq, NULL, calloc, free);
+  if (last4tab == NULL)
     goto alloc_failure;
 
   /* Now insert the strings into hash tables (strings with last 4 characters
@@ -416,27 +393,35 @@ _bfd_elf_strtab_finalize (tab)
          else
            *p = (PTR) e;
        }
-      c = (unsigned char) e->root.string[e->len - 1];
-      p = htab_find_slot_with_hash (lasttab, e, c, INSERT);
-      if (p == NULL)
-       goto alloc_failure;
-      if (*p)
+      else
        {
-         struct elf_strtab_hash_entry *ent;
+         struct elf_strtab_hash_entry *tem;
 
-         ent = (struct elf_strtab_hash_entry *) *p;
-         e->u.suffix = ent;
-         e->len = 0;
+         c = e->root.string[e->len - 2] & 0xff;
+
+         for (tem = last[c]; tem; tem = tem->u.next)
+           if (tem->len > e->len
+               && memcmp (tem->root.string + (tem->len - e->len),
+                          e->root.string, e->len - 1) == 0)
+             break;
+         if (tem)
+           {
+             e->u.suffix = tem;
+             e->len = 0;
+             continue;
+           }
        }
-      else
-       *p = (PTR) e;
+
+      c = e->root.string[e->len - 2] & 0xff;
+      /* Put longest strings first.  */
+      *last_ptr[c] = e;
+      last_ptr[c] = &e->u.next;
+      e->u.next = NULL;
     }
 
 alloc_failure:
   if (array)
     free (array);
-  if (lasttab)
-    htab_delete (lasttab);
   if (last4tab)
     htab_delete (last4tab);
 
This page took 0.027533 seconds and 4 git commands to generate.