2000-06-14 Jim Blandy <jimb@redhat.com>
[deliverable/binutils-gdb.git] / gdb / minsyms.c
index e878b916563ba9068a9fe382c85160a58acf1f8e..e6978e7909f9115a8efc9fcd8f2099033e4b42fa 100644 (file)
@@ -39,6 +39,7 @@
 
 
 #include "defs.h"
+#include <ctype.h>
 #include "gdb_string.h"
 #include "symtab.h"
 #include "bfd.h"
@@ -74,11 +75,69 @@ static int msym_count;
 
 /* Prototypes for local functions. */
 
-static int
-compare_minimal_symbols PARAMS ((const void *, const void *));
+static int compare_minimal_symbols (const void *, const void *);
 
 static int
-compact_minimal_symbols PARAMS ((struct minimal_symbol *, int));
+compact_minimal_symbols (struct minimal_symbol *, int, struct objfile *);
+
+static void add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
+                                               struct minimal_symbol **table);
+
+/* Compute a hash code based using the same criteria as `strcmp_iw'.  */
+
+unsigned int
+msymbol_hash_iw (const char *string)
+{
+  unsigned int hash = 0;
+  while (*string && *string != '(')
+    {
+      while (isspace (*string))
+       ++string;
+      if (*string && *string != '(')
+       hash = (31 * hash) + *string;
+      ++string;
+    }
+  return hash % MINIMAL_SYMBOL_HASH_SIZE;
+}
+
+/* Compute a hash code for a string.  */
+
+unsigned int
+msymbol_hash (const char *string)
+{
+  unsigned int hash = 0;
+  for (; *string; ++string)
+    hash = (31 * hash) + *string;
+  return hash % MINIMAL_SYMBOL_HASH_SIZE;
+}
+
+/* Add the minimal symbol SYM to an objfile's minsym hash table, TABLE.  */
+void
+add_minsym_to_hash_table (struct minimal_symbol *sym,
+                         struct minimal_symbol **table)
+{
+  if (sym->hash_next == NULL)
+    {
+      unsigned int hash = msymbol_hash (SYMBOL_NAME (sym));
+      sym->hash_next = table[hash];
+      table[hash] = sym;
+    }
+}
+
+/* Add the minimal symbol SYM to an objfile's minsym demangled hash table,
+   TABLE.  */
+static void
+add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
+                                  struct minimal_symbol **table)
+{
+  if (sym->demangled_hash_next == NULL)
+    {
+      unsigned int hash = msymbol_hash_iw (SYMBOL_DEMANGLED_NAME (sym));
+      sym->demangled_hash_next = table[hash];
+      table[hash] = sym;
+    }
+}
+
 
 /* Look through all the current minimal symbol tables and find the
    first minimal symbol that matches NAME.  If OBJF is non-NULL, limit
@@ -103,6 +162,9 @@ lookup_minimal_symbol (name, sfile, objf)
   struct minimal_symbol *found_file_symbol = NULL;
   struct minimal_symbol *trampoline_symbol = NULL;
 
+  unsigned int hash = msymbol_hash (name);
+  unsigned int dem_hash = msymbol_hash_iw (name);
+
 #ifdef SOFUN_ADDRESS_MAYBE_MISSING
   if (sfile != NULL)
     {
@@ -118,46 +180,62 @@ lookup_minimal_symbol (name, sfile, objf)
     {
       if (objf == NULL || objf == objfile)
        {
-         for (msymbol = objfile->msymbols;
-              msymbol != NULL && SYMBOL_NAME (msymbol) != NULL &&
-              found_symbol == NULL;
-              msymbol++)
+         /* Do two passes: the first over the ordinary hash table,
+            and the second over the demangled hash table.  */
+        int pass;
+
+        for (pass = 1; pass <= 2 && found_symbol == NULL; pass++)
            {
-             if (SYMBOL_MATCHES_NAME (msymbol, name))
+            /* Select hash list according to pass.  */
+            if (pass == 1)
+              msymbol = objfile->msymbol_hash[hash];
+            else
+              msymbol = objfile->msymbol_demangled_hash[dem_hash];
+
+            while (msymbol != NULL && found_symbol == NULL)
                {
-                 switch (MSYMBOL_TYPE (msymbol))
+                if (SYMBOL_MATCHES_NAME (msymbol, name))
                    {
-                   case mst_file_text:
-                   case mst_file_data:
-                   case mst_file_bss:
+                    switch (MSYMBOL_TYPE (msymbol))
+                      {
+                      case mst_file_text:
+                      case mst_file_data:
+                      case mst_file_bss:
 #ifdef SOFUN_ADDRESS_MAYBE_MISSING
-                     if (sfile == NULL || STREQ (msymbol->filename, sfile))
-                       found_file_symbol = msymbol;
+                        if (sfile == NULL || STREQ (msymbol->filename, sfile))
+                          found_file_symbol = msymbol;
 #else
-                     /* We have neither the ability nor the need to
-                        deal with the SFILE parameter.  If we find
-                        more than one symbol, just return the latest
-                        one (the user can't expect useful behavior in
-                        that case).  */
-                     found_file_symbol = msymbol;
+                        /* We have neither the ability nor the need to
+                           deal with the SFILE parameter.  If we find
+                           more than one symbol, just return the latest
+                           one (the user can't expect useful behavior in
+                           that case).  */
+                        found_file_symbol = msymbol;
 #endif
-                     break;
-
-                   case mst_solib_trampoline:
-
-                     /* If a trampoline symbol is found, we prefer to
-                        keep looking for the *real* symbol. If the
-                        actual symbol is not found, then we'll use the
-                        trampoline entry. */
-                     if (trampoline_symbol == NULL)
-                       trampoline_symbol = msymbol;
-                     break;
-
-                   case mst_unknown:
-                   default:
-                     found_symbol = msymbol;
-                     break;
+                        break;
+
+                      case mst_solib_trampoline:
+
+                        /* If a trampoline symbol is found, we prefer to
+                           keep looking for the *real* symbol. If the
+                           actual symbol is not found, then we'll use the
+                           trampoline entry. */
+                        if (trampoline_symbol == NULL)
+                          trampoline_symbol = msymbol;
+                        break;
+
+                      case mst_unknown:
+                      default:
+                        found_symbol = msymbol;
+                        break;
+                      }
                    }
+
+                /* Find the next symbol on the hash chain.  */
+                if (pass == 1)
+                  msymbol = msymbol->hash_next;
+                else
+                  msymbol = msymbol->demangled_hash_next;
                }
            }
        }
@@ -440,9 +518,9 @@ lookup_minimal_symbol_by_pc (pc)
 
 #ifdef SOFUN_ADDRESS_MAYBE_MISSING
 CORE_ADDR
-find_stab_function_addr (namestring, pst, objfile)
+find_stab_function_addr (namestring, filename, objfile)
      char *namestring;
-     struct partial_symtab *pst;
+     char *filename;
      struct objfile *objfile;
 {
   struct minimal_symbol *msym;
@@ -457,7 +535,7 @@ find_stab_function_addr (namestring, pst, objfile)
   strncpy (p, namestring, n);
   p[n] = 0;
 
-  msym = lookup_minimal_symbol (p, pst->filename, objfile);
+  msym = lookup_minimal_symbol (p, filename, objfile);
   if (msym == NULL)
     {
       /* Sun Fortran appends an underscore to the minimal symbol name,
@@ -465,8 +543,23 @@ find_stab_function_addr (namestring, pst, objfile)
          was not found.  */
       p[n] = '_';
       p[n + 1] = 0;
-      msym = lookup_minimal_symbol (p, pst->filename, objfile);
+      msym = lookup_minimal_symbol (p, filename, objfile);
+    }
+
+  if (msym == NULL && filename != NULL)
+    {
+      /* Try again without the filename. */
+      p[n] = 0;
+      msym = lookup_minimal_symbol (p, 0, objfile);
+    }
+  if (msym == NULL && filename != NULL)
+    {
+      /* And try again for Sun Fortran, but without the filename. */
+      p[n] = '_';
+      p[n + 1] = 0;
+      msym = lookup_minimal_symbol (p, 0, objfile);
     }
+
   return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym);
 }
 #endif /* SOFUN_ADDRESS_MAYBE_MISSING */
@@ -475,7 +568,7 @@ find_stab_function_addr (namestring, pst, objfile)
 /* Return leading symbol character for a BFD. If BFD is NULL,
    return the leading symbol character from the main objfile.  */
 
-static int get_symbol_leading_char PARAMS ((bfd *));
+static int get_symbol_leading_char (bfd *);
 
 static int
 get_symbol_leading_char (abfd)
@@ -514,15 +607,15 @@ prim_record_minimal_symbol (name, address, ms_type, objfile)
     case mst_text:
     case mst_file_text:
     case mst_solib_trampoline:
-      section = SECT_OFF_TEXT;
+      section = SECT_OFF_TEXT (objfile);
       break;
     case mst_data:
     case mst_file_data:
-      section = SECT_OFF_DATA;
+      section = SECT_OFF_DATA (objfile);
       break;
     case mst_bss:
     case mst_file_bss:
-      section = SECT_OFF_BSS;
+      section = SECT_OFF_BSS (objfile);
       break;
     default:
       section = -1;
@@ -588,6 +681,12 @@ prim_record_minimal_symbol_and_info (name, address, ms_type, info, section,
   MSYMBOL_TYPE (msymbol) = ms_type;
   /* FIXME:  This info, if it remains, needs its own field.  */
   MSYMBOL_INFO (msymbol) = info;       /* FIXME! */
+
+  /* The hash pointers must be cleared! If they're not,
+     add_minsym_to_hash_table will NOT add this msymbol to the hash table. */
+  msymbol->hash_next = NULL;
+  msymbol->demangled_hash_next = NULL;
+
   msym_bunch_index++;
   msym_count++;
   OBJSTAT (objfile, n_minsyms++);
@@ -642,10 +741,8 @@ compare_minimal_symbols (fn1p, fn2p)
    obstack and then simply blow the obstack away when we are done with
    it.  Is it worth the extra trouble though? */
 
-/* ARGSUSED */
-void
-discard_minimal_symbols (foo)
-     int foo;
+static void
+do_discard_minimal_symbols_cleanup (void *arg)
 {
   register struct msym_bunch *next;
 
@@ -657,6 +754,14 @@ discard_minimal_symbols (foo)
     }
 }
 
+struct cleanup *
+make_cleanup_discard_minimal_symbols (void)
+{
+  return make_cleanup (do_discard_minimal_symbols_cleanup, 0);
+}
+
+
+
 /* Compact duplicate entries out of a minimal symbol table by walking
    through the table and compacting out entries with duplicate addresses
    and matching names.  Return the number of entries remaining.
@@ -694,9 +799,10 @@ discard_minimal_symbols (foo)
    overwrite its type with the type from the one we are compacting out.  */
 
 static int
-compact_minimal_symbols (msymbol, mcount)
+compact_minimal_symbols (msymbol, mcount, objfile)
      struct minimal_symbol *msymbol;
      int mcount;
+     struct objfile *objfile;
 {
   struct minimal_symbol *copyfrom;
   struct minimal_symbol *copyto;
@@ -719,6 +825,8 @@ compact_minimal_symbols (msymbol, mcount)
          else
            {
              *copyto++ = *copyfrom++;
+
+             add_minsym_to_hash_table (copyto - 1, objfile->msymbol_hash);
            }
        }
       *copyto++ = *copyfrom++;
@@ -811,7 +919,7 @@ install_minimal_symbols (objfile)
       /* Compact out any duplicates, and free up whatever space we are
          no longer using.  */
 
-      mcount = compact_minimal_symbols (msymbols, mcount);
+      mcount = compact_minimal_symbols (msymbols, mcount, objfile);
 
       obstack_blank (&objfile->symbol_obstack,
               (mcount + 1 - alloc_count) * sizeof (struct minimal_symbol));
@@ -845,6 +953,9 @@ install_minimal_symbols (objfile)
       for (; mcount-- > 0; msymbols++)
        {
          SYMBOL_INIT_DEMANGLED_NAME (msymbols, &objfile->symbol_obstack);
+         if (SYMBOL_DEMANGLED_NAME (msymbols) != NULL)
+          add_minsym_to_demangled_hash_table (msymbols,
+                                              objfile->msymbol_demangled_hash);
        }
     }
 }
This page took 0.031649 seconds and 4 git commands to generate.