* python/python.c (gdbpy_decode_line): Move cleanup creation out
[deliverable/binutils-gdb.git] / gdb / linespec.c
index cdfb59c00906ab2be2faa41c581573051532e3b4..1e9770ef7c8247ca4279c12346b8573484084f13 100644 (file)
@@ -1,8 +1,6 @@
 /* Parser for linespec for the GNU debugger, GDB.
 
-   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
-   2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -121,9 +119,6 @@ struct collect_info
 
   /* The result being accumulated.  */
   struct symtabs_and_lines result;
-
-  /* The current objfile; used only by the minimal symbol code.  */
-  struct objfile *objfile;
 };
 
 /* Prototypes for local functions.  */
@@ -326,34 +321,80 @@ cplusplus_error (const char *name, const char *fmt, ...)
   throw_error (NOT_FOUND_ERROR, "%s", message);
 }
 
+/* A callback function and the additional data to call it with.  */
+
+struct symbol_and_data_callback
+{
+  /* The callback to use.  */
+  symbol_found_callback_ftype *callback;
+
+  /* Data to be passed to the callback.  */
+  void *data;
+};
+
+/* A helper for iterate_over_all_matching_symtabs that is used to
+   restrict calls to another callback to symbols representing inline
+   symbols only.  */
+
+static int
+iterate_inline_only (struct symbol *sym, void *d)
+{
+  if (SYMBOL_INLINED (sym))
+    {
+      struct symbol_and_data_callback *cad = d;
+
+      return cad->callback (sym, cad->data);
+    }
+  return 1; /* Continue iterating.  */
+}
+
+/* Some data for the expand_symtabs_matching callback.  */
+
+struct symbol_matcher_data
+{
+  /* The lookup name against which symbol name should be compared.  */
+  const char *lookup_name;
+
+  /* The routine to be used for comparison.  */
+  symbol_name_cmp_ftype symbol_name_cmp;
+};
+
 /* A helper for iterate_over_all_matching_symtabs that is passed as a
    callback to the expand_symtabs_matching method.  */
 
 static int
-iterate_name_matcher (const struct language_defn *language,
-                     const char *name, void *d)
+iterate_name_matcher (const char *name, void *d)
 {
-  const char **dname = d;
+  const struct symbol_matcher_data *data = d;
 
-  if (language->la_symbol_name_compare (name, *dname) == 0)
-    return 1;
-  return 0;
+  if (data->symbol_name_cmp (name, data->lookup_name) == 0)
+    return 1; /* Expand this symbol's symbol table.  */
+  return 0; /* Skip this symbol.  */
 }
 
 /* A helper that walks over all matching symtabs in all objfiles and
    calls CALLBACK for each symbol matching NAME.  If SEARCH_PSPACE is
    not NULL, then the search is restricted to just that program
-   space.  */
+   space.  If INCLUDE_INLINE is nonzero then symbols representing
+   inlined instances of functions will be included in the result.  */
 
 static void
 iterate_over_all_matching_symtabs (const char *name,
                                   const domain_enum domain,
-                                  int (*callback) (struct symbol *, void *),
+                                  symbol_found_callback_ftype *callback,
                                   void *data,
-                                  struct program_space *search_pspace)
+                                  struct program_space *search_pspace,
+                                  int include_inline)
 {
   struct objfile *objfile;
   struct program_space *pspace;
+  struct symbol_matcher_data matcher_data;
+
+  matcher_data.lookup_name = name;
+  matcher_data.symbol_name_cmp =
+    current_language->la_get_symbol_name_cmp != NULL
+    ? current_language->la_get_symbol_name_cmp (name)
+    : strcmp_iw;
 
   ALL_PSPACES (pspace)
   {
@@ -372,7 +413,7 @@ iterate_over_all_matching_symtabs (const char *name,
        objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
                                                  iterate_name_matcher,
                                                  ALL_DOMAIN,
-                                                 &name);
+                                                 &matcher_data);
 
       ALL_OBJFILE_SYMTABS (objfile, symtab)
        {
@@ -382,6 +423,20 @@ iterate_over_all_matching_symtabs (const char *name,
 
              block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
              LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
+
+             if (include_inline)
+               {
+                 struct symbol_and_data_callback cad = { callback, data };
+                 int i;
+
+                 for (i = FIRST_LOCAL_BLOCK;
+                      i < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (symtab)); i++)
+                   {
+                     block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), i);
+                     LA_ITERATE_OVER_SYMBOLS (block, name, domain,
+                                              iterate_inline_only, &cad);
+                   }
+               }
            }
        }
     }
@@ -423,8 +478,7 @@ find_methods (struct type *t, const char *name,
 {
   int i1 = 0;
   int ibase;
-  char *class_name = type_name_no_tag (t);
-  char *canon;
+  const char *class_name = type_name_no_tag (t);
 
   /* Ignore this class if it doesn't have a name.  This is ugly, but
      unless we figure out how to get the physname without the name of
@@ -444,7 +498,7 @@ find_methods (struct type *t, const char *name,
           method_counter >= 0;
           --method_counter)
        {
-         char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
+         const char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
          char dem_opname[64];
 
          if (strncmp (method_name, "__", 2) == 0 ||
@@ -639,6 +693,11 @@ decode_line_2 (struct linespec_state *self,
       return;
     }
 
+  /* Sort the list of method names alphabetically.  */
+  qsort (VEC_address (const_char_ptr, item_names),
+        VEC_length (const_char_ptr, item_names),
+        sizeof (const_char_ptr), compare_strings);
+
   printf_unfiltered (_("[0] cancel\n[1] all\n"));
   for (i = 0; VEC_iterate (const_char_ptr, item_names, i, iter); ++i)
     printf_unfiltered ("[%d] %s\n", i + 2, iter);
@@ -892,39 +951,53 @@ decode_line_internal (struct linespec_state *self, char **argptr)
 
   /* Locate the end of the first half of the linespec.
      After the call, for instance, if the argptr string is "foo.c:123"
-     p will point at "123".  If there is only one part, like "foo", p
+     p will point at ":123".  If there is only one part, like "foo", p
      will point to "".  If this is a C++ name, like "A::B::foo", p will
      point to "::B::foo".  Argptr is not changed by this call.  */
 
   first_half = p = locate_first_half (argptr, &is_quote_enclosed);
 
   /* First things first: if ARGPTR starts with a filename, get its
-     symtab and strip the filename from ARGPTR.  */
-  TRY_CATCH (file_exception, RETURN_MASK_ERROR)
+     symtab and strip the filename from ARGPTR.
+     Avoid calling symtab_from_filename if we know can,
+     it can be expensive.  We know we can avoid the call if we see a
+     single word (e.g., "break NAME") or if we see a qualified C++
+     name ("break QUAL::NAME").  */
+
+  if (*p != '\0' && !(p[0] == ':' && p[1] == ':'))
     {
-      self->file_symtabs = symtabs_from_filename (argptr, p, is_quote_enclosed,
-                                                 &self->user_filename);
-    }
+      TRY_CATCH (file_exception, RETURN_MASK_ERROR)
+       {
+         self->file_symtabs = symtabs_from_filename (argptr, p,
+                                                     is_quote_enclosed,
+                                                     &self->user_filename);
+       }
+
+      if (file_exception.reason >= 0)
+       {
+         /* Check for single quotes on the non-filename part.  */
+         is_quoted = (**argptr
+                      && strchr (get_gdb_completer_quote_characters (),
+                                 **argptr) != NULL);
+         if (is_quoted)
+           end_quote = skip_quoted (*argptr);
+
+         /* Locate the next "half" of the linespec.  */
+         first_half = p = locate_first_half (argptr, &is_quote_enclosed);
+       }
 
-  if (VEC_empty (symtab_p, self->file_symtabs))
+      if (VEC_empty (symtab_p, self->file_symtabs))
+       {
+         /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB.  */
+         VEC_safe_push (symtab_p, self->file_symtabs, NULL);
+       }
+    }
+  else
     {
       /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB.  */
       VEC_safe_push (symtab_p, self->file_symtabs, NULL);
     }
 
-  if (file_exception.reason >= 0)
-    {
-      /* Check for single quotes on the non-filename part.  */
-      is_quoted = (**argptr
-                  && strchr (get_gdb_completer_quote_characters (),
-                             **argptr) != NULL);
-      if (is_quoted)
-       end_quote = skip_quoted (*argptr);
-
-      /* Locate the next "half" of the linespec.  */
-      first_half = p = locate_first_half (argptr, &is_quote_enclosed);
-    }
-
   /* Check if this is an Objective-C method (anything that starts with
      a '+' or '-' and a '[').  */
   if (is_objc_method_format (p))
@@ -956,33 +1029,44 @@ decode_line_internal (struct linespec_state *self, char **argptr)
        
       if (p[0] == '.' || p[1] == ':')
        {
-         struct symtabs_and_lines values;
-         volatile struct gdb_exception ex;
-         char *saved_argptr = *argptr;
+        /* We only perform this check for the languages where it might
+           make sense.  For instance, Ada does not use this type of
+           syntax, and trying to apply this logic on an Ada linespec
+           may trigger a spurious error (for instance, decode_compound
+           does not like expressions such as `ops."<"', which is a
+           valid function name in Ada).  */
+         if (current_language->la_language == language_c
+             || current_language->la_language == language_cplus
+             || current_language->la_language == language_java)
+           {
+             struct symtabs_and_lines values;
+             volatile struct gdb_exception ex;
+             char *saved_argptr = *argptr;
 
-         if (is_quote_enclosed)
-           ++saved_arg;
+             if (is_quote_enclosed)
+               ++saved_arg;
 
-         /* Initialize it just to avoid a GCC false warning.  */
-         memset (&values, 0, sizeof (values));
+             /* Initialize it just to avoid a GCC false warning.  */
+             memset (&values, 0, sizeof (values));
 
-         TRY_CATCH (ex, RETURN_MASK_ERROR)
-           {
-             values = decode_compound (self, argptr, saved_arg, p);
-           }
-         if ((is_quoted || is_squote_enclosed) && **argptr == '\'')
-           *argptr = *argptr + 1;
+             TRY_CATCH (ex, RETURN_MASK_ERROR)
+               {
+                 values = decode_compound (self, argptr, saved_arg, p);
+               }
+             if ((is_quoted || is_squote_enclosed) && **argptr == '\'')
+               *argptr = *argptr + 1;
 
-         if (ex.reason >= 0)
-           {
-             do_cleanups (cleanup);
-             return values;
-           }
+             if (ex.reason >= 0)
+               {
+                 do_cleanups (cleanup);
+                 return values;
+               }
 
-         if (ex.error != NOT_FOUND_ERROR)
-           throw_exception (ex);
+             if (ex.error != NOT_FOUND_ERROR)
+               throw_exception (ex);
 
-         *argptr = saved_argptr;
+             *argptr = saved_argptr;
+           }
        }
       else
        {
@@ -1334,6 +1418,24 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   char *p, *p1;
   int has_comma;
 
+  /* Check if the linespec starts with an Ada operator (such as "+",
+     or ">", for instance).  */
+  p = *argptr;
+  if (p[0] == '"'
+      && current_language->la_language == language_ada)
+    {
+      const struct ada_opname_map *op;
+
+      for (op = ada_opname_table; op->encoded != NULL; op++)
+        if (strncmp (op->decoded, p, strlen (op->decoded)) == 0)
+         break;
+      if (op->encoded != NULL)
+       {
+         *is_quote_enclosed = 0;
+         return p + strlen (op->decoded);
+       }
+    }
+
   /* Maybe we were called with a line range FILENAME:LINENUM,FILENAME:LINENUM
      and we must isolate the first half.  Outer layers will call again later
      for the second half.
@@ -1462,7 +1564,6 @@ decode_objc (struct linespec_state *self, char **argptr)
   info.state = self;
   info.result.sals = NULL;
   info.result.nelts = 0;
-  info.objfile = NULL;
 
   new_argptr = find_imps (*argptr, &symbol_names); 
   if (VEC_empty (const_char_ptr, symbol_names))
@@ -1756,14 +1857,14 @@ collect_one_symbol (struct symbol *sym, void *d)
   struct type *t;
 
   if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
-    return 1;
+    return 1; /* Continue iterating.  */
 
   t = SYMBOL_TYPE (sym);
   CHECK_TYPEDEF (t);
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION
       && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
-    return 1;
+    return 1; /* Continue iterating.  */
 
   slot = htab_find_slot (collector->unique_syms, sym, INSERT);
   if (!*slot)
@@ -1772,7 +1873,7 @@ collect_one_symbol (struct symbol *sym, void *d)
       VEC_safe_push (symbolp, collector->symbols, sym);
     }
 
-  return 1;
+  return 1; /* Continue iterating.  */
 }
 
 /* Return the symbol corresponding to the substring of *ARGPTR ending
@@ -1827,10 +1928,10 @@ lookup_prefix_sym (char **argptr, char *p, VEC (symtab_p) *file_symtabs,
        {
          iterate_over_all_matching_symtabs (copy, STRUCT_DOMAIN,
                                             collect_one_symbol, &collector,
-                                            NULL);
+                                            NULL, 0);
          iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
                                             collect_one_symbol, &collector,
-                                            NULL);
+                                            NULL, 0);
        }
       else
        {
@@ -1966,7 +2067,6 @@ find_method (struct linespec_state *self, char *saved_arg,
   info.state = self;
   info.result.sals = NULL;
   info.result.nelts = 0;
-  info.objfile = NULL;
 
   /* Iterate over all the types, looking for the names of existing
      methods matching COPY.  If we cannot find a direct method in a
@@ -2164,7 +2264,7 @@ collect_function_symbols (struct symbol *sym, void *arg)
   if (SYMBOL_CLASS (sym) == LOC_BLOCK)
     VEC_safe_push (symbolp, *syms, sym);
 
-  return 1;
+  return 1; /* Continue iterating.  */
 }
 
 /* Look up a function symbol in *ARGPTR.  If found, advance *ARGPTR
@@ -2194,7 +2294,8 @@ find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
     copy[p - *argptr] = 0;
 
   iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
-                                    collect_function_symbols, &result, NULL);
+                                    collect_function_symbols, &result, NULL,
+                                    0);
 
   if (VEC_empty (symbolp, result))
     VEC_free (symbolp, result);
@@ -2664,23 +2765,14 @@ collect_symbols (struct symbol *sym, void *data)
   struct collect_info *info = data;
   struct symtab_and_line sal;
 
-  if ((SYMBOL_CLASS (sym) == LOC_STATIC
-       && !info->state->funfirstline
-       && !maybe_add_address (info->state->addr_set,
-                             SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
-                             SYMBOL_VALUE_ADDRESS (sym)))
-      || (SYMBOL_CLASS (sym) == LOC_BLOCK
-         && !maybe_add_address (info->state->addr_set,
-                                SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
-                                BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))))
-    {
-      /* Nothing.  */
-    }
-  else if (symbol_to_sal (&sal, info->state->funfirstline, sym))
+  if (symbol_to_sal (&sal, info->state->funfirstline, sym)
+      && maybe_add_address (info->state->addr_set,
+                           SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
+                           sal.pc))
     add_sal_to_sals (info->state, &info->result, &sal,
                     SYMBOL_NATURAL_NAME (sym));
 
-  return 1;
+  return 1; /* Continue iterating.  */
 }
 
 /* We've found a minimal symbol MSYMBOL to associate with our
@@ -2708,33 +2800,111 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
   if (self->funfirstline)
     skip_prologue_sal (&sal);
 
-  add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol));
+  if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
+    add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol));
 }
 
-/* Callback for iterate_over_minimal_symbols that may add the symbol
-   to the result.  */
+/* A helper struct which just holds a minimal symbol and the object
+   file from which it came.  */
 
-static void
-check_minsym (struct minimal_symbol *minsym, void *d)
+typedef struct minsym_and_objfile
 {
-  struct collect_info *info = d;
+  struct minimal_symbol *minsym;
+  struct objfile *objfile;
+} minsym_and_objfile_d;
 
-  if (MSYMBOL_TYPE (minsym) == mst_unknown
-      || MSYMBOL_TYPE (minsym) == mst_slot_got_plt
-      || MSYMBOL_TYPE (minsym) == mst_solib_trampoline)
-    {
-      /* Reject some odd ones.  */
-    }
-  else if (info->state->funfirstline
-          && MSYMBOL_TYPE (minsym) != mst_text
-          && MSYMBOL_TYPE (minsym) != mst_text_gnu_ifunc
-          && MSYMBOL_TYPE (minsym) != mst_file_text)
+DEF_VEC_O (minsym_and_objfile_d);
+
+/* A helper struct to pass some data through
+   iterate_over_minimal_symbols.  */
+
+struct collect_minsyms
+{
+  /* The objfile we're examining.  */
+  struct objfile *objfile;
+
+  /* The funfirstline setting from the initial call.  */
+  int funfirstline;
+
+  /* The list_mode setting from the initial call.  */
+  int list_mode;
+
+  /* The resulting symbols.  */
+  VEC (minsym_and_objfile_d) *msyms;
+};
+
+/* A helper function to classify a minimal_symbol_type according to
+   priority.  */
+
+static int
+classify_mtype (enum minimal_symbol_type t)
+{
+  switch (t)
     {
-      /* When FUNFIRSTLINE, only allow text symbols.  */
+    case mst_file_text:
+    case mst_file_data:
+    case mst_file_bss:
+      /* Intermediate priority.  */
+      return 1;
+
+    case mst_solib_trampoline:
+      /* Lowest priority.  */
+      return 2;
+
+    default:
+      /* Highest priority.  */
+      return 0;
     }
-  else if (maybe_add_address (info->state->addr_set, info->objfile->pspace,
-                             SYMBOL_VALUE_ADDRESS (minsym)))
-    minsym_found (info->state, info->objfile, minsym, &info->result);
+}
+
+/* Callback for qsort that sorts symbols by priority.  */
+
+static int
+compare_msyms (const void *a, const void *b)
+{
+  const minsym_and_objfile_d *moa = a;
+  const minsym_and_objfile_d *mob = b;
+  enum minimal_symbol_type ta = MSYMBOL_TYPE (moa->minsym);
+  enum minimal_symbol_type tb = MSYMBOL_TYPE (mob->minsym);
+
+  return classify_mtype (ta) - classify_mtype (tb);
+}
+
+/* Callback for iterate_over_minimal_symbols that adds the symbol to
+   the result.  */
+
+static void
+add_minsym (struct minimal_symbol *minsym, void *d)
+{
+  struct collect_minsyms *info = d;
+  minsym_and_objfile_d mo;
+
+  /* Exclude data symbols when looking for breakpoint locations.   */
+  if (!info->list_mode)
+    switch (minsym->type)
+      {
+       case mst_slot_got_plt:
+       case mst_data:
+       case mst_bss:
+       case mst_abs:
+       case mst_file_data:
+       case mst_file_bss:
+         {
+           /* Make sure this minsym is not a function descriptor
+              before we decide to discard it.  */
+           struct gdbarch *gdbarch = info->objfile->gdbarch;
+           CORE_ADDR addr = gdbarch_convert_from_func_ptr_addr
+                              (gdbarch, SYMBOL_VALUE_ADDRESS (minsym),
+                               &current_target);
+
+           if (addr == SYMBOL_VALUE_ADDRESS (minsym))
+             return;
+         }
+      }
+
+  mo.minsym = minsym;
+  mo.objfile = info->objfile;
+  VEC_safe_push (minsym_and_objfile_d, info->msyms, &mo);
 }
 
 /* Search minimal symbols in all objfiles for NAME.  If SEARCH_PSPACE
@@ -2750,6 +2920,9 @@ search_minsyms_for_name (struct collect_info *info, const char *name,
 
   ALL_PSPACES (pspace)
   {
+    struct collect_minsyms local;
+    struct cleanup *cleanup;
+
     if (search_pspace != NULL && search_pspace != pspace)
       continue;
     if (pspace->executing_startup)
@@ -2757,11 +2930,49 @@ search_minsyms_for_name (struct collect_info *info, const char *name,
 
     set_current_program_space (pspace);
 
+    memset (&local, 0, sizeof (local));
+    local.funfirstline = info->state->funfirstline;
+    local.list_mode = info->state->list_mode;
+
+    cleanup = make_cleanup (VEC_cleanup (minsym_and_objfile_d),
+                           &local.msyms);
+
     ALL_OBJFILES (objfile)
     {
-      info->objfile = objfile;
-      iterate_over_minimal_symbols (objfile, name, check_minsym, info);
+      local.objfile = objfile;
+      iterate_over_minimal_symbols (objfile, name, add_minsym, &local);
     }
+
+    if (!VEC_empty (minsym_and_objfile_d, local.msyms))
+      {
+       int classification;
+       int ix;
+       minsym_and_objfile_d *item;
+
+       qsort (VEC_address (minsym_and_objfile_d, local.msyms),
+              VEC_length (minsym_and_objfile_d, local.msyms),
+              sizeof (minsym_and_objfile_d),
+              compare_msyms);
+
+       /* Now the minsyms are in classification order.  So, we walk
+          over them and process just the minsyms with the same
+          classification as the very first minsym in the list.  */
+       item = VEC_index (minsym_and_objfile_d, local.msyms, 0);
+       classification = classify_mtype (MSYMBOL_TYPE (item->minsym));
+
+       for (ix = 0;
+            VEC_iterate (minsym_and_objfile_d, local.msyms, ix, item);
+            ++ix)
+         {
+           if (classify_mtype (MSYMBOL_TYPE (item->minsym)) != classification)
+             break;
+
+           minsym_found (info->state, item->objfile, item->minsym,
+                         &info->result);
+         }
+      }
+
+    do_cleanups (cleanup);
   }
 }
 
@@ -2785,7 +2996,7 @@ add_matching_symbols_to_info (const char *name,
        {
          iterate_over_all_matching_symtabs (name, VAR_DOMAIN,
                                             collect_symbols, info,
-                                            pspace);
+                                            pspace, 1);
          search_minsyms_for_name (info, name, pspace);
        }
       else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
@@ -2815,7 +3026,6 @@ decode_variable (struct linespec_state *self, char *copy)
   info.state = self;
   info.result.sals = NULL;
   info.result.nelts = 0;
-  info.objfile = NULL;
 
   cleanup = demangle_for_lookup (copy, current_language->la_language,
                                 &lookup_name);
This page took 0.030958 seconds and 4 git commands to generate.