2006-12-31 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gdb / symtab.c
index dd5ce54b49040c26bfdf6105f457ba3ab364fcb6..62109358ffa376ee7b3824d7738a3d991a3355b4 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
 
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
    1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
@@ -18,8 +18,8 @@
 
    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.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -41,6 +41,7 @@
 #include "source.h"
 #include "filenames.h"         /* for FILENAME_CMP */
 #include "objc-lang.h"
+#include "ada-lang.h"
 
 #include "hashtab.h"
 
@@ -54,6 +55,8 @@
 #include "gdb_stat.h"
 #include <ctype.h>
 #include "cp-abi.h"
+#include "observer.h"
+#include "gdb_assert.h"
 
 /* Prototypes for local functions */
 
@@ -220,7 +223,7 @@ got_symtab:
     return (NULL);
 
   if (ps->readin)
-    error ("Internal: readin %s pst for `%s' found when no symtab found.",
+    error (_("Internal: readin %s pst for `%s' found when no symtab found."),
           ps->filename, name);
 
   s = PSYMTAB_TO_SYMTAB (ps);
@@ -272,8 +275,7 @@ lookup_partial_symtab (const char *name)
        this symtab and use its absolute path.  */
     if (full_path != NULL)
       {
-       if (pst->fullname == NULL)
-         source_full_path_of (pst->filename, &pst->fullname);
+       psymtab_to_fullname (pst);
        if (pst->fullname != NULL
            && FILENAME_CMP (full_path, pst->fullname) == 0)
          {
@@ -284,8 +286,7 @@ lookup_partial_symtab (const char *name)
     if (real_path != NULL)
       {
         char *rp = NULL;
-       if (pst->fullname == NULL)
-         source_full_path_of (pst->filename, &pst->fullname);
+       psymtab_to_fullname (pst);
         if (pst->fullname != NULL)
           {
             rp = gdb_realpath (pst->fullname);
@@ -636,17 +637,24 @@ symbol_init_demangled_name (struct general_symbol_info *gsymbol,
 char *
 symbol_natural_name (const struct general_symbol_info *gsymbol)
 {
-  if ((gsymbol->language == language_cplus
-       || gsymbol->language == language_java
-       || gsymbol->language == language_objc)
-      && (gsymbol->language_specific.cplus_specific.demangled_name != NULL))
+  switch (gsymbol->language) 
     {
-      return gsymbol->language_specific.cplus_specific.demangled_name;
-    }
-  else
-    {
-      return gsymbol->name;
+    case language_cplus:
+    case language_java:
+    case language_objc:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      break;
+    case language_ada:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      else
+       return ada_decode_symbol (gsymbol);
+      break;
+    default:
+      break;
     }
+  return gsymbol->name;
 }
 
 /* Return the demangled name for a symbol based on the language for
@@ -654,21 +662,37 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
 char *
 symbol_demangled_name (struct general_symbol_info *gsymbol)
 {
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_java
-      || gsymbol->language == language_objc)
-    return gsymbol->language_specific.cplus_specific.demangled_name;
-
-  else 
-    return NULL;
+  switch (gsymbol->language) 
+    {
+    case language_cplus:
+    case language_java:
+    case language_objc:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      break;
+    case language_ada:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      else
+       return ada_decode_symbol (gsymbol);
+      break;
+    default:
+      break;
+    }
+  return NULL;
 }
 
 /* Return the search name of a symbol---generally the demangled or
    linkage name of the symbol, depending on how it will be searched for.
    If there is no distinct demangled name, then returns the same value 
    (same pointer) as SYMBOL_LINKAGE_NAME. */
-char *symbol_search_name (const struct general_symbol_info *gsymbol) {
-  return symbol_natural_name (gsymbol);
+char *
+symbol_search_name (const struct general_symbol_info *gsymbol)
+{
+  if (gsymbol->language == language_ada)
+    return gsymbol->name;
+  else
+    return symbol_natural_name (gsymbol);
 }
 
 /* Initialize the structure fields to zero values.  */
@@ -683,6 +707,64 @@ init_sal (struct symtab_and_line *sal)
 }
 \f
 
+/* Return 1 if the two sections are the same, or if they could
+   plausibly be copies of each other, one in an original object
+   file and another in a separated debug file.  */
+
+int
+matching_bfd_sections (asection *first, asection *second)
+{
+  struct objfile *obj;
+
+  /* If they're the same section, then they match.  */
+  if (first == second)
+    return 1;
+
+  /* If either is NULL, give up.  */
+  if (first == NULL || second == NULL)
+    return 0;
+
+  /* This doesn't apply to absolute symbols.  */
+  if (first->owner == NULL || second->owner == NULL)
+    return 0;
+
+  /* If they're in the same object file, they must be different sections.  */
+  if (first->owner == second->owner)
+    return 0;
+
+  /* Check whether the two sections are potentially corresponding.  They must
+     have the same size, address, and name.  We can't compare section indexes,
+     which would be more reliable, because some sections may have been
+     stripped.  */
+  if (bfd_get_section_size (first) != bfd_get_section_size (second))
+    return 0;
+
+  if (bfd_get_section_vma (first->owner, first)
+      != bfd_get_section_vma (second->owner, second))
+    return 0;
+
+  if (bfd_get_section_name (first->owner, first) == NULL
+      || bfd_get_section_name (second->owner, second) == NULL
+      || strcmp (bfd_get_section_name (first->owner, first),
+                bfd_get_section_name (second->owner, second)) != 0)
+    return 0;
+
+  /* Otherwise check that they are in corresponding objfiles.  */
+
+  ALL_OBJFILES (obj)
+    if (obj->obfd == first->owner)
+      break;
+  gdb_assert (obj != NULL);
+
+  if (obj->separate_debug_objfile != NULL
+      && obj->separate_debug_objfile->obfd == second->owner)
+    return 1;
+  if (obj->separate_debug_objfile_backlink != NULL
+      && obj->separate_debug_objfile_backlink->obfd == second->owner)
+    return 1;
+
+  return 0;
+}
 
 /* Find which partial symtab contains PC and SECTION.  Return 0 if
    none.  We return the psymtab that contains a symbol whose address
@@ -822,7 +904,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
          if (section)          /* match on a specific section */
            {
              fixup_psymbol_section (p, psymtab->objfile);
-             if (SYMBOL_BFD_SECTION (p) != section)
+             if (!matching_bfd_sections (SYMBOL_BFD_SECTION (p), section))
                continue;
            }
          best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -846,7 +928,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
          if (section)          /* match on a specific section */
            {
              fixup_psymbol_section (p, psymtab->objfile);
-             if (SYMBOL_BFD_SECTION (p) != section)
+             if (!matching_bfd_sections (SYMBOL_BFD_SECTION (p), section))
                continue;
            }
          best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -1000,7 +1082,7 @@ lookup_symbol (const char *name, const struct block *block,
 
   modified_name = name;
 
-  /* If we are using C++ language, demangle the name before doing a lookup, so
+  /* If we are using C++ or Java, demangle the name before doing a lookup, so
      we can always binary search. */
   if (current_language->la_language == language_cplus)
     {
@@ -1012,6 +1094,17 @@ lookup_symbol (const char *name, const struct block *block,
          needtofreename = 1;
        }
     }
+  else if (current_language->la_language == language_java)
+    {
+      demangled_name = cplus_demangle (name, 
+                                      DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
+      if (demangled_name)
+       {
+         mangled_name = name;
+         modified_name = demangled_name;
+         needtofreename = 1;
+       }
+    }
 
   if (case_sensitivity == case_sensitive_off)
     {
@@ -1262,7 +1355,7 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name,
                                       STATIC_BLOCK : GLOBAL_BLOCK);
            sym = lookup_block_symbol (block, name, linkage_name, domain);
            if (!sym)
-             error ("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>).",
+             error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>)."),
                     block_index == GLOBAL_BLOCK ? "global" : "static",
                     name, ps->filename, name, name);
          }
@@ -1529,7 +1622,7 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
        {
          center = bottom + (top - bottom) / 2;
          if (!(center < top))
-           internal_error (__FILE__, __LINE__, "failed internal consistency check");
+           internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
          if (!do_linear_search
              && (SYMBOL_LANGUAGE (*center) == language_java))
            {
@@ -1545,7 +1638,7 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
            }
        }
       if (!(top == bottom))
-       internal_error (__FILE__, __LINE__, "failed internal consistency check");
+       internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
       while (top <= real_top
             && (linkage_name != NULL
@@ -1643,9 +1736,9 @@ basic_lookup_transparent_type (const char *name)
            block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
            sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
            if (!sym)
-             error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
+             error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
+(if a template, try specifying an instantiation: %s<type>)."),
                     name, ps->filename, name, name);
          }
        if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
@@ -1690,9 +1783,9 @@ basic_lookup_transparent_type (const char *name)
            block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
            sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
            if (!sym)
-             error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
+             error (_("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
+(if a template, try specifying an instantiation: %s<type>)."),
                     name, ps->filename, name, name);
          }
        if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
@@ -1868,7 +1961,7 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
            ALL_BLOCK_SYMBOLS (b, iter, sym)
              {
                fixup_symbol_section (sym, objfile);
-               if (section == SYMBOL_BFD_SECTION (sym))
+               if (matching_bfd_sections (SYMBOL_BFD_SECTION (sym), section))
                  break;
              }
            if (sym == NULL)
@@ -1890,8 +1983,8 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
        /* Might want to error() here (in case symtab is corrupt and
           will cause a core dump), but maybe we can successfully
           continue, so let's not.  */
-       warning ("\
-(Internal error: pc 0x%s in read in psymtab, but not in symtab.)\n",
+       warning (_("\
+(Internal error: pc 0x%s in read in psymtab, but not in symtab.)\n"),
                 paddr_nz (pc));
       s = PSYMTAB_TO_SYMTAB (ps);
     }
@@ -2129,23 +2222,11 @@ find_pc_sect_line (CORE_ADDR pc, struct bfd_section *section, int notcurrent)
 
   if (!best_symtab)
     {
-      if (!alt_symtab)
-       {                       /* If we didn't find any line # info, just
-                                  return zeros.  */
-         val.pc = pc;
-       }
-      else
-       {
-         val.symtab = alt_symtab;
-         val.line = alt->line - 1;
-
-         /* Don't return line 0, that means that we didn't find the line.  */
-         if (val.line == 0)
-           ++val.line;
-
-         val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
-         val.end = alt->pc;
-       }
+      /* If we didn't find any line number info, just return zeros.
+        We used to return alt->line - 1 here, but that could be
+        anywhere; if we don't have line number info for this PC,
+        don't make some up.  */
+      val.pc = pc;
     }
   else if (best->line == 0)
     {
@@ -2488,14 +2569,14 @@ operator_chars (char *p, char **end)
        else if (p[1] == '[')
          {
            if (p[2] == ']')
-             error ("mismatched quoting on brackets, try 'operator\\[\\]'");
+             error (_("mismatched quoting on brackets, try 'operator\\[\\]'"));
            else if (p[2] == '\\' && p[3] == ']')
              {
                *end = p + 4;   /* 'operator\[\]' */
                return p;
              }
            else
-             error ("nothing is allowed between '[' and ']'");
+             error (_("nothing is allowed between '[' and ']'"));
          }
        else 
          {
@@ -2551,21 +2632,21 @@ operator_chars (char *p, char **end)
        return p;
       case '(':
        if (p[1] != ')')
-         error ("`operator ()' must be specified without whitespace in `()'");
+         error (_("`operator ()' must be specified without whitespace in `()'"));
        *end = p + 2;
        return p;
       case '?':
        if (p[1] != ':')
-         error ("`operator ?:' must be specified without whitespace in `?:'");
+         error (_("`operator ?:' must be specified without whitespace in `?:'"));
        *end = p + 2;
        return p;
       case '[':
        if (p[1] != ']')
-         error ("`operator []' must be specified without whitespace in `[]'");
+         error (_("`operator []' must be specified without whitespace in `[]'"));
        *end = p + 2;
        return p;
       default:
-       error ("`operator %s' not supported", p);
+       error (_("`operator %s' not supported"), p);
        break;
       }
 
@@ -2663,7 +2744,7 @@ sources_info (char *ignore, int from_tty)
 
   if (!have_full_symbols () && !have_partial_symbols ())
     {
-      error ("No symbol table is loaded.  Use the \"file\" command.");
+      error (_("No symbol table is loaded.  Use the \"file\" command."));
     }
 
   printf_filtered ("Source files for which symbols have been read in:\n\n");
@@ -2835,7 +2916,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
   struct cleanup *old_chain = NULL;
 
   if (kind < VARIABLES_DOMAIN)
-    error ("must search on specific domain");
+    error (_("must search on specific domain"));
 
   ourtype = types[(int) (kind - VARIABLES_DOMAIN)];
   ourtype2 = types2[(int) (kind - VARIABLES_DOMAIN)];
@@ -2878,7 +2959,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
        }
 
       if (0 != (val = re_comp (regexp)))
-       error ("Invalid regexp (%s): %s", val, regexp);
+       error (_("Invalid regexp (%s): %s"), val, regexp);
     }
 
   /* Search through the partial symtabs *first* for all symbols
@@ -3996,6 +4077,11 @@ skip_prologue_using_sal (CORE_ADDR func_addr)
   prologue_sal = find_pc_line (start_pc, 0);
   if (prologue_sal.line != 0)
     {
+      /* If there is only one sal that covers the entire function,
+        then it is probably a single line function, like
+        "foo(){}". */
+      if (prologue_sal.end == end_pc)
+       return start_pc;
       while (prologue_sal.end < end_pc)
        {
          struct symtab_and_line sal;
@@ -4027,7 +4113,7 @@ decode_line_spec (char *string, int funfirstline)
   struct symtab_and_line cursal;
   
   if (string == 0)
-    error ("Empty line specification.");
+    error (_("Empty line specification."));
     
   /* We use whatever is set as the current source line. We do not try
      and get a default  or it will recursively call us! */  
@@ -4038,7 +4124,7 @@ decode_line_spec (char *string, int funfirstline)
                        (char ***) NULL, NULL);
 
   if (*string)
-    error ("Junk at end of line specification: %s", string);
+    error (_("Junk at end of line specification: %s"), string);
   return sals;
 }
 
@@ -4059,27 +4145,71 @@ set_main_name (const char *name)
     }
 }
 
+/* Deduce the name of the main procedure, and set NAME_OF_MAIN
+   accordingly.  */
+
+static void
+find_main_name (void)
+{
+  char *new_main_name;
+
+  /* Try to see if the main procedure is in Ada.  */
+  /* FIXME: brobecker/2005-03-07: Another way of doing this would
+     be to add a new method in the language vector, and call this
+     method for each language until one of them returns a non-empty
+     name.  This would allow us to remove this hard-coded call to
+     an Ada function.  It is not clear that this is a better approach
+     at this point, because all methods need to be written in a way
+     such that false positives never be returned. For instance, it is
+     important that a method does not return a wrong name for the main
+     procedure if the main procedure is actually written in a different
+     language.  It is easy to guaranty this with Ada, since we use a
+     special symbol generated only when the main in Ada to find the name
+     of the main procedure. It is difficult however to see how this can
+     be guarantied for languages such as C, for instance.  This suggests
+     that order of call for these methods becomes important, which means
+     a more complicated approach.  */
+  new_main_name = ada_main_name ();
+  if (new_main_name != NULL)
+    { 
+      set_main_name (new_main_name);
+      return;
+    }
+
+  /* The languages above didn't identify the name of the main procedure.
+     Fallback to "main".  */
+  set_main_name ("main");
+}
+
 char *
 main_name (void)
 {
-  if (name_of_main != NULL)
-    return name_of_main;
-  else
-    return "main";
+  if (name_of_main == NULL)
+    find_main_name ();
+
+  return name_of_main;
 }
 
+/* Handle ``executable_changed'' events for the symtab module.  */
+
+static void
+symtab_observer_executable_changed (void *unused)
+{
+  /* NAME_OF_MAIN may no longer be the same, so reset it for now.  */
+  set_main_name (NULL);
+}
 
 void
 _initialize_symtab (void)
 {
-  add_info ("variables", variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+  add_info ("variables", variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
   if (dbx_commands)
-    add_com ("whereis", class_info, variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+    add_com ("whereis", class_info, variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
 
   add_info ("functions", functions_info,
-           "All function names, or those matching REGEXP.");
+           _("All function names, or those matching REGEXP."));
 
   
   /* FIXME:  This command has at least the following problems:
@@ -4091,22 +4221,25 @@ _initialize_symtab (void)
      I also think "ptype" or "whatis" is more likely to be useful (but if
      there is much disagreement "info types" can be fixed).  */
   add_info ("types", types_info,
-           "All type names, or those matching REGEXP.");
+           _("All type names, or those matching REGEXP."));
 
   add_info ("sources", sources_info,
-           "Source files in the program.");
+           _("Source files in the program."));
 
   add_com ("rbreak", class_breakpoint, rbreak_command,
-          "Set a breakpoint for all functions matching REGEXP.");
+          _("Set a breakpoint for all functions matching REGEXP."));
 
   if (xdb_commands)
     {
-      add_com ("lf", class_info, sources_info, "Source files in the program");
-      add_com ("lg", class_info, variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+      add_com ("lf", class_info, sources_info,
+              _("Source files in the program"));
+      add_com ("lg", class_info, variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
     }
 
   /* Initialize the one built-in type that isn't language dependent... */
   builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0,
                                  "<unknown type>", (struct objfile *) NULL);
+
+  observer_attach_executable_changed (symtab_observer_executable_changed);
 }
This page took 0.031341 seconds and 4 git commands to generate.