OSDN Git Service

2009-12-16 Michael Snyder <msnyder@vmware.com>
[pf3gnuchains/pf3gnuchains3x.git] / gdb / minsyms.c
index b06c3f0..393a0ea 100644 (file)
@@ -1,14 +1,13 @@
 /* GDB routines for manipulating the minimal symbol tables.
-   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
    This file is part of GDB.
 
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +16,7 @@
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 /* This file contains support routines for creating, manipulating, and
@@ -50,6 +47,9 @@
 #include "demangle.h"
 #include "value.h"
 #include "cp-abi.h"
+#include "target.h"
+#include "cp-support.h"
+#include "language.h"
 
 /* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
    At the end, copy them all into one newly allocated location on an objfile's
@@ -128,13 +128,34 @@ add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
 {
   if (sym->demangled_hash_next == NULL)
     {
-      unsigned int hash = msymbol_hash_iw (SYMBOL_DEMANGLED_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE;
+      unsigned int hash
+       = msymbol_hash_iw (SYMBOL_SEARCH_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE;
       sym->demangled_hash_next = table[hash];
       table[hash] = sym;
     }
 }
 
 
+/* Return OBJFILE where minimal symbol SYM is defined.  */
+struct objfile *
+msymbol_objfile (struct minimal_symbol *sym)
+{
+  struct objfile *objf;
+  struct minimal_symbol *tsym;
+
+  unsigned int hash
+    = msymbol_hash (SYMBOL_LINKAGE_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE;
+
+  for (objf = object_files; objf; objf = objf->next)
+    for (tsym = objf->msymbol_hash[hash]; tsym; tsym = tsym->hash_next)
+      if (tsym == sym)
+       return objf;
+
+  /* We should always be able to find the objfile ...  */
+  internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+}
+
+
 /* Look through all the current minimal symbol tables and find the
    first minimal symbol that matches NAME.  If OBJF is non-NULL, limit
    the search to that objfile.  If SFILE is non-NULL, the only file-scope
@@ -145,7 +166,15 @@ add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
    Note:  One instance where there may be duplicate minimal symbols with
    the same name is when the symbol tables for a shared library and the
    symbol tables for an executable contain global symbols with the same
-   names (the dynamic linker deals with the duplication).  */
+   names (the dynamic linker deals with the duplication).
+
+   It's also possible to have minimal symbols with different mangled
+   names, but identical demangled names.  For example, the GNU C++ v3
+   ABI requires the generation of two (or perhaps three) copies of
+   constructor functions --- "in-charge", "not-in-charge", and
+   "allocate" copies; destructors may be duplicated as well.
+   Obviously, there must be distinct mangled names for each of these,
+   but the demangled names are all the same: S::S or S::~S.  */
 
 struct minimal_symbol *
 lookup_minimal_symbol (const char *name, const char *sfile,
@@ -160,20 +189,34 @@ lookup_minimal_symbol (const char *name, const char *sfile,
   unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
   unsigned int dem_hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
 
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+  int needtofreename = 0;
+  const char *modified_name;
+
   if (sfile != NULL)
     {
       char *p = strrchr (sfile, '/');
       if (p != NULL)
        sfile = p + 1;
     }
-#endif
+
+  /* For C++, canonicalize the input name. */
+  modified_name = name;
+  if (current_language->la_language == language_cplus)
+    {
+      char *cname = cp_canonicalize_string (name);
+      if (cname)
+       {
+         modified_name = cname;
+         needtofreename = 1;
+       }
+    }
 
   for (objfile = object_files;
        objfile != NULL && found_symbol == NULL;
        objfile = objfile->next)
     {
-      if (objf == NULL || objf == objfile)
+      if (objf == NULL || objf == objfile
+         || objf->separate_debug_objfile == objfile)
        {
          /* Do two passes: the first over the ordinary hash table,
             and the second over the demangled hash table.  */
@@ -189,33 +232,29 @@ lookup_minimal_symbol (const char *name, const char *sfile,
 
             while (msymbol != NULL && found_symbol == NULL)
                {
-                 /* FIXME: carlton/2003-02-27: This is an unholy
-                    mixture of linkage names and natural names.  If
-                    you want to test the linkage names with strcmp,
-                    do that.  If you want to test the natural names
-                    with strcmp_iw, use SYMBOL_MATCHES_NATURAL_NAME.  */
-                 if (strcmp (DEPRECATED_SYMBOL_NAME (msymbol), (name)) == 0
-                     || (SYMBOL_DEMANGLED_NAME (msymbol) != NULL
-                         && strcmp_iw (SYMBOL_DEMANGLED_NAME (msymbol),
-                                       (name)) == 0))
+                 int match;
+
+                 if (pass == 1)
+                   {
+                     match = strcmp (SYMBOL_LINKAGE_NAME (msymbol),
+                                     modified_name) == 0;
+                   }
+                 else
+                   {
+                     match = SYMBOL_MATCHES_SEARCH_NAME (msymbol,
+                                                         modified_name);
+                   }
+
+                 if (match)
                    {
                     switch (MSYMBOL_TYPE (msymbol))
                       {
                       case mst_file_text:
                       case mst_file_data:
                       case mst_file_bss:
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
                         if (sfile == NULL
                            || strcmp (msymbol->filename, sfile) == 0)
                           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;
-#endif
                         break;
 
                       case mst_solib_trampoline:
@@ -244,6 +283,10 @@ lookup_minimal_symbol (const char *name, const char *sfile,
            }
        }
     }
+
+  if (needtofreename)
+    xfree ((void *) modified_name);
+
   /* External symbols are best.  */
   if (found_symbol)
     return found_symbol;
@@ -280,7 +323,8 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
        objfile != NULL && found_symbol == NULL;
        objfile = objfile->next)
     {
-      if (objf == NULL || objf == objfile)
+      if (objf == NULL || objf == objfile
+         || objf->separate_debug_objfile == objfile)
        {
          for (msymbol = objfile->msymbol_hash[hash];
               msymbol != NULL && found_symbol == NULL;
@@ -315,6 +359,41 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
 }
 
 /* Look through all the current minimal symbol tables and find the
+   first minimal symbol that matches NAME and PC.  If OBJF is non-NULL,
+   limit the search to that objfile.  Returns a pointer to the minimal
+   symbol that matches, or NULL if no match is found.  */
+
+struct minimal_symbol *
+lookup_minimal_symbol_by_pc_name (CORE_ADDR pc, const char *name,
+                                 struct objfile *objf)
+{
+  struct objfile *objfile;
+  struct minimal_symbol *msymbol;
+
+  unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
+
+  for (objfile = object_files;
+       objfile != NULL;
+       objfile = objfile->next)
+    {
+      if (objf == NULL || objf == objfile
+         || objf->separate_debug_objfile == objfile)
+       {
+         for (msymbol = objfile->msymbol_hash[hash];
+              msymbol != NULL;
+              msymbol = msymbol->hash_next)
+           {
+             if (SYMBOL_VALUE_ADDRESS (msymbol) == pc
+                 && strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0)
+               return msymbol;
+           }
+       }
+    }
+
+  return NULL;
+}
+
+/* Look through all the current minimal symbol tables and find the
    first minimal symbol that matches NAME and is a solib trampoline.
    If OBJF is non-NULL, limit the search to that objfile.  Returns a
    pointer to the minimal symbol that matches, or NULL if no match is
@@ -336,7 +415,8 @@ lookup_minimal_symbol_solib_trampoline (const char *name,
        objfile != NULL && found_symbol == NULL;
        objfile = objfile->next)
     {
-      if (objf == NULL || objf == objfile)
+      if (objf == NULL || objf == objfile
+         || objf->separate_debug_objfile == objfile)
        {
          for (msymbol = objfile->msymbol_hash[hash];
               msymbol != NULL && found_symbol == NULL;
@@ -352,19 +432,25 @@ lookup_minimal_symbol_solib_trampoline (const char *name,
   return NULL;
 }
 
-
 /* Search through the minimal symbol table for each objfile and find
    the symbol whose address is the largest address that is still less
-   than or equal to PC, and matches SECTION (if non-NULL).  Returns a
-   pointer to the minimal symbol if such a symbol is found, or NULL if
-   PC is not in a suitable range.  Note that we need to look through
-   ALL the minimal symbol tables before deciding on the symbol that
-   comes closest to the specified PC.  This is because objfiles can
-   overlap, for example objfile A has .text at 0x100 and .data at
-   0x40000 and objfile B has .text at 0x234 and .data at 0x40048.  */
-
-struct minimal_symbol *
-lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, asection *section)
+   than or equal to PC, and matches SECTION (which is not NULL).
+   Returns a pointer to the minimal symbol if such a symbol is found,
+   or NULL if PC is not in a suitable range.
+   Note that we need to look through ALL the minimal symbol tables
+   before deciding on the symbol that comes closest to the specified PC.
+   This is because objfiles can overlap, for example objfile A has .text
+   at 0x100 and .data at 0x40000 and objfile B has .text at 0x234 and
+   .data at 0x40048.
+
+   If WANT_TRAMPOLINE is set, prefer mst_solib_trampoline symbols when
+   there are text and trampoline symbols at the same address.
+   Otherwise prefer mst_text symbols.  */
+
+static struct minimal_symbol *
+lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc,
+                                      struct obj_section *section,
+                                      int want_trampoline)
 {
   int lo;
   int hi;
@@ -372,29 +458,26 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, asection *section)
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
   struct minimal_symbol *best_symbol = NULL;
-  struct obj_section *pc_section;
-
-  /* PC has to be in a known section.  This ensures that anything
-     beyond the end of the last segment doesn't appear to be part of
-     the last function in the last segment.  */
-  pc_section = find_pc_section (pc);
-  if (pc_section == NULL)
-    return NULL;
-
-  /* NOTE: cagney/2004-01-27: Removed code (added 2003-07-19) that was
-     trying to force the PC into a valid section as returned by
-     find_pc_section.  It broke IRIX 6.5 mdebug which relies on this
-     code returning an absolute symbol - the problem was that
-     find_pc_section wasn't returning an absolute section and hence
-     the code below would skip over absolute symbols.  Since the
-     original problem was with finding a frame's function, and that
-     uses [indirectly] lookup_minimal_symbol_by_pc, the original
-     problem has been fixed by having that function use
-     find_pc_section.  */
-
-  for (objfile = object_files;
-       objfile != NULL;
-       objfile = objfile->next)
+  enum minimal_symbol_type want_type, other_type;
+
+  want_type = want_trampoline ? mst_solib_trampoline : mst_text;
+  other_type = want_trampoline ? mst_text : mst_solib_trampoline;
+
+  /* We can not require the symbol found to be in section, because
+     e.g. IRIX 6.5 mdebug relies on this code returning an absolute
+     symbol - but find_pc_section won't return an absolute section and
+     hence the code below would skip over absolute symbols.  We can
+     still take advantage of the call to find_pc_section, though - the
+     object file still must match.  In case we have separate debug
+     files, search both the file and its separate debug file.  There's
+     no telling which one will have the minimal symbols.  */
+
+  gdb_assert (section != NULL);
+  objfile = section->objfile;
+  if (objfile->separate_debug_objfile)
+    objfile = objfile->separate_debug_objfile;
+
+  for (; objfile != NULL; objfile = objfile->separate_debug_objfile_backlink)
     {
       /* If this objfile has a minimal symbol table, go search it using
          a binary search.  Note that a minimal symbol table always consists
@@ -404,6 +487,8 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, asection *section)
 
       if (objfile->minimal_symbol_count > 0)
        {
+         int best_zero_sized = -1;
+
           msymbol = objfile->msymbols;
          lo = 0;
          hi = objfile->minimal_symbol_count - 1;
@@ -453,34 +538,126 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, asection *section)
                         == SYMBOL_VALUE_ADDRESS (&msymbol[hi + 1])))
                hi++;
 
+             /* Skip various undesirable symbols.  */
+             while (hi >= 0)
+               {
+                 /* Skip any absolute symbols.  This is apparently
+                    what adb and dbx do, and is needed for the CM-5.
+                    There are two known possible problems: (1) on
+                    ELF, apparently end, edata, etc. are absolute.
+                    Not sure ignoring them here is a big deal, but if
+                    we want to use them, the fix would go in
+                    elfread.c.  (2) I think shared library entry
+                    points on the NeXT are absolute.  If we want
+                    special handling for this it probably should be
+                    triggered by a special mst_abs_or_lib or some
+                    such.  */
+
+                 if (MSYMBOL_TYPE (&msymbol[hi]) == mst_abs)
+                   {
+                     hi--;
+                     continue;
+                   }
+
+                 /* If SECTION was specified, skip any symbol from
+                    wrong section.  */
+                 if (section
+                     /* Some types of debug info, such as COFF,
+                        don't fill the bfd_section member, so don't
+                        throw away symbols on those platforms.  */
+                     && SYMBOL_OBJ_SECTION (&msymbol[hi]) != NULL
+                     && (!matching_obj_sections
+                         (SYMBOL_OBJ_SECTION (&msymbol[hi]), section)))
+                   {
+                     hi--;
+                     continue;
+                   }
+
+                 /* If we are looking for a trampoline and this is a
+                    text symbol, or the other way around, check the
+                    preceeding symbol too.  If they are otherwise
+                    identical prefer that one.  */
+                 if (hi > 0
+                     && MSYMBOL_TYPE (&msymbol[hi]) == other_type
+                     && MSYMBOL_TYPE (&msymbol[hi - 1]) == want_type
+                     && (MSYMBOL_SIZE (&msymbol[hi])
+                         == MSYMBOL_SIZE (&msymbol[hi - 1]))
+                     && (SYMBOL_VALUE_ADDRESS (&msymbol[hi])
+                         == SYMBOL_VALUE_ADDRESS (&msymbol[hi - 1]))
+                     && (SYMBOL_OBJ_SECTION (&msymbol[hi])
+                         == SYMBOL_OBJ_SECTION (&msymbol[hi - 1])))
+                   {
+                     hi--;
+                     continue;
+                   }
+
+                 /* If the minimal symbol has a zero size, save it
+                    but keep scanning backwards looking for one with
+                    a non-zero size.  A zero size may mean that the
+                    symbol isn't an object or function (e.g. a
+                    label), or it may just mean that the size was not
+                    specified.  */
+                 if (MSYMBOL_SIZE (&msymbol[hi]) == 0
+                     && best_zero_sized == -1)
+                   {
+                     best_zero_sized = hi;
+                     hi--;
+                     continue;
+                   }
+
+                 /* If we are past the end of the current symbol, try
+                    the previous symbol if it has a larger overlapping
+                    size.  This happens on i686-pc-linux-gnu with glibc;
+                    the nocancel variants of system calls are inside
+                    the cancellable variants, but both have sizes.  */
+                 if (hi > 0
+                     && MSYMBOL_SIZE (&msymbol[hi]) != 0
+                     && pc >= (SYMBOL_VALUE_ADDRESS (&msymbol[hi])
+                               + MSYMBOL_SIZE (&msymbol[hi]))
+                     && pc < (SYMBOL_VALUE_ADDRESS (&msymbol[hi - 1])
+                              + MSYMBOL_SIZE (&msymbol[hi - 1])))
+                   {
+                     hi--;
+                     continue;
+                   }
+
+                 /* Otherwise, this symbol must be as good as we're going
+                    to get.  */
+                 break;
+               }
+
+             /* If HI has a zero size, and best_zero_sized is set,
+                then we had two or more zero-sized symbols; prefer
+                the first one we found (which may have a higher
+                address).  Also, if we ran off the end, be sure
+                to back up.  */
+             if (best_zero_sized != -1
+                 && (hi < 0 || MSYMBOL_SIZE (&msymbol[hi]) == 0))
+               hi = best_zero_sized;
+
+             /* If the minimal symbol has a non-zero size, and this
+                PC appears to be outside the symbol's contents, then
+                refuse to use this symbol.  If we found a zero-sized
+                symbol with an address greater than this symbol's,
+                use that instead.  We assume that if symbols have
+                specified sizes, they do not overlap.  */
+
+             if (hi >= 0
+                 && MSYMBOL_SIZE (&msymbol[hi]) != 0
+                 && pc >= (SYMBOL_VALUE_ADDRESS (&msymbol[hi])
+                           + MSYMBOL_SIZE (&msymbol[hi])))
+               {
+                 if (best_zero_sized != -1)
+                   hi = best_zero_sized;
+                 else
+                   /* Go on to the next object file.  */
+                   continue;
+               }
+
              /* The minimal symbol indexed by hi now is the best one in this
                 objfile's minimal symbol table.  See if it is the best one
                 overall. */
 
-             /* Skip any absolute symbols.  This is apparently what adb
-                and dbx do, and is needed for the CM-5.  There are two
-                known possible problems: (1) on ELF, apparently end, edata,
-                etc. are absolute.  Not sure ignoring them here is a big
-                deal, but if we want to use them, the fix would go in
-                elfread.c.  (2) I think shared library entry points on the
-                NeXT are absolute.  If we want special handling for this
-                it probably should be triggered by a special
-                mst_abs_or_lib or some such.  */
-             while (hi >= 0
-                    && msymbol[hi].type == mst_abs)
-               --hi;
-
-             /* If "section" specified, skip any symbol from wrong section */
-             /* This is the new code that distinguishes it from the old function */
-             if (section)
-               while (hi >= 0
-                      /* Some types of debug info, such as COFF,
-                         don't fill the bfd_section member, so don't
-                         throw away symbols on those platforms.  */
-                      && SYMBOL_BFD_SECTION (&msymbol[hi]) != NULL
-                      && SYMBOL_BFD_SECTION (&msymbol[hi]) != section)
-                 --hi;
-
              if (hi >= 0
                  && ((best_symbol == NULL) ||
                      (SYMBOL_VALUE_ADDRESS (best_symbol) <
@@ -494,19 +671,28 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, asection *section)
   return (best_symbol);
 }
 
+struct minimal_symbol *
+lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, struct obj_section *section)
+{
+  if (section == NULL)
+    {
+      /* NOTE: cagney/2004-01-27: This was using find_pc_mapped_section to
+        force the section but that (well unless you're doing overlay
+        debugging) always returns NULL making the call somewhat useless.  */
+      section = find_pc_section (pc);
+      if (section == NULL)
+       return NULL;
+    }
+  return lookup_minimal_symbol_by_pc_section_1 (pc, section, 0);
+}
+
 /* Backward compatibility: search through the minimal symbol table 
    for a matching PC (no section given) */
 
 struct minimal_symbol *
 lookup_minimal_symbol_by_pc (CORE_ADDR pc)
 {
-  /* NOTE: cagney/2004-01-27: This was using find_pc_mapped_section to
-     force the section but that (well unless you're doing overlay
-     debugging) always returns NULL making the call somewhat useless.  */
-  struct obj_section *section = find_pc_section (pc);
-  if (section == NULL)
-    return NULL;
-  return lookup_minimal_symbol_by_pc_section (pc, section->the_bfd_section);
+  return lookup_minimal_symbol_by_pc_section (pc, NULL);
 }
 \f
 
@@ -564,19 +750,21 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
     }
 
   prim_record_minimal_symbol_and_info (name, address, ms_type,
-                                      NULL, section, NULL, objfile);
+                                      section, NULL, objfile);
 }
 
 /* Record a minimal symbol in the msym bunches.  Returns the symbol
    newly created.  */
 
 struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
-                                    enum minimal_symbol_type ms_type,
-                                    char *info, int section,
-                                    asection *bfd_section,
-                                    struct objfile *objfile)
+prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
+                                CORE_ADDR address,
+                                enum minimal_symbol_type ms_type,
+                                int section,
+                                asection *bfd_section,
+                                struct objfile *objfile)
 {
+  struct obj_section *obj_section;
   struct msym_bunch *new;
   struct minimal_symbol *msymbol;
 
@@ -593,14 +781,17 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   /* It's safe to strip the leading char here once, since the name
      is also stored stripped in the minimal symbol table. */
   if (name[0] == get_symbol_leading_char (objfile->obfd))
-    ++name;
+    {
+      ++name;
+      --name_len;
+    }
 
   if (ms_type == mst_file_text && strncmp (name, "__gnu_compiled", 14) == 0)
     return (NULL);
 
   if (msym_bunch_index == BUNCH_SIZE)
     {
-      new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch));
+      new = XCALLOC (1, struct msym_bunch);
       msym_bunch_index = 0;
       new->next = msym_bunch;
       msym_bunch = new;
@@ -608,15 +799,26 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   msymbol = &msym_bunch->contents[msym_bunch_index];
   SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
   SYMBOL_LANGUAGE (msymbol) = language_auto;
-  SYMBOL_SET_NAMES (msymbol, (char *)name, strlen (name), objfile);
+  SYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile);
 
   SYMBOL_VALUE_ADDRESS (msymbol) = address;
   SYMBOL_SECTION (msymbol) = section;
-  SYMBOL_BFD_SECTION (msymbol) = bfd_section;
+  SYMBOL_OBJ_SECTION (msymbol) = NULL;
+
+  /* Find obj_section corresponding to bfd_section.  */
+  if (bfd_section)
+    ALL_OBJFILE_OSECTIONS (objfile, obj_section)
+      {
+       if (obj_section->the_bfd_section == bfd_section)
+         {
+           SYMBOL_OBJ_SECTION (msymbol) = obj_section;
+           break;
+         }
+      }
 
   MSYMBOL_TYPE (msymbol) = ms_type;
-  /* FIXME:  This info, if it remains, needs its own field.  */
-  MSYMBOL_INFO (msymbol) = info;       /* FIXME! */
+  MSYMBOL_TARGET_FLAG_1 (msymbol) = 0;
+  MSYMBOL_TARGET_FLAG_2 (msymbol) = 0;
   MSYMBOL_SIZE (msymbol) = 0;
 
   /* The hash pointers must be cleared! If they're not,
@@ -630,6 +832,21 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   return msymbol;
 }
 
+/* Record a minimal symbol in the msym bunches.  Returns the symbol
+   newly created.  */
+
+struct minimal_symbol *
+prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
+                                    enum minimal_symbol_type ms_type,
+                                    int section,
+                                    asection *bfd_section,
+                                    struct objfile *objfile)
+{
+  return prim_record_minimal_symbol_full (name, strlen (name), 1,
+                                         address, ms_type, section,
+                                         bfd_section, objfile);
+}
+
 /* Compare two minimal symbols by address and return a signed result based
    on unsigned comparisons, so that we sort into unsigned numeric order.  
    Within groups with the same address, sort by name.  */
@@ -791,7 +1008,7 @@ build_minimal_symbol_hash_tables (struct objfile *objfile)
       add_minsym_to_hash_table (msym, objfile->msymbol_hash);
 
       msym->demangled_hash_next = 0;
-      if (SYMBOL_DEMANGLED_NAME (msym) != NULL)
+      if (SYMBOL_SEARCH_NAME (msym) != SYMBOL_LINKAGE_NAME (msym))
        add_minsym_to_demangled_hash_table (msym,
                                             objfile->msymbol_demangled_hash);
     }
@@ -888,7 +1105,8 @@ install_minimal_symbols (struct objfile *objfile)
 
       SYMBOL_LINKAGE_NAME (&msymbols[mcount]) = NULL;
       SYMBOL_VALUE_ADDRESS (&msymbols[mcount]) = 0;
-      MSYMBOL_INFO (&msymbols[mcount]) = NULL;
+      MSYMBOL_TARGET_FLAG_1 (&msymbols[mcount]) = 0;
+      MSYMBOL_TARGET_FLAG_2 (&msymbols[mcount]) = 0;
       MSYMBOL_SIZE (&msymbols[mcount]) = 0;
       MSYMBOL_TYPE (&msymbols[mcount]) = mst_unknown;
       SYMBOL_INIT_LANGUAGE_SPECIFIC (&msymbols[mcount], language_unknown);
@@ -947,7 +1165,12 @@ msymbols_sort (struct objfile *objfile)
 struct minimal_symbol *
 lookup_solib_trampoline_symbol_by_pc (CORE_ADDR pc)
 {
-  struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+  struct obj_section *section = find_pc_section (pc);
+  struct minimal_symbol *msymbol;
+
+  if (section == NULL)
+    return NULL;
+  msymbol = lookup_minimal_symbol_by_pc_section_1 (pc, section, 1);
 
   if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
     return msymbol;
@@ -965,7 +1188,7 @@ lookup_solib_trampoline_symbol_by_pc (CORE_ADDR pc)
    a duplicate function in case this matters someday.  */
 
 CORE_ADDR
-find_solib_trampoline_target (CORE_ADDR pc)
+find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc)
 {
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
@@ -979,6 +1202,22 @@ find_solib_trampoline_target (CORE_ADDR pc)
            && strcmp (SYMBOL_LINKAGE_NAME (msymbol),
                       SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
          return SYMBOL_VALUE_ADDRESS (msymbol);
+
+       /* Also handle minimal symbols pointing to function descriptors.  */
+       if (MSYMBOL_TYPE (msymbol) == mst_data
+           && strcmp (SYMBOL_LINKAGE_NAME (msymbol),
+                      SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
+         {
+           CORE_ADDR func;
+           func = gdbarch_convert_from_func_ptr_addr
+                   (get_objfile_arch (objfile),
+                    SYMBOL_VALUE_ADDRESS (msymbol),
+                    &current_target);
+
+           /* Ignore data symbols that are not function descriptors.  */
+           if (func != SYMBOL_VALUE_ADDRESS (msymbol))
+             return func;
+         }
       }
     }
   return 0;