/* 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
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
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,
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "symtab.h"
#include "objc-lang.h"
#include "linespec.h"
#include "exceptions.h"
+#include "language.h"
+#include "interps.h"
+#include "mi/mi-cmds.h"
+#include "target.h"
/* We share this one with symtab.c, but it is not exported widely. */
struct symbol *sym_class);
static int collect_methods (char *copy, struct type *t,
+ struct symbol *sym_class,
struct symbol **sym_arr);
static NORETURN void cplusplus_error (const char *name,
static int total_number_of_methods (struct type *type);
-static int find_methods (struct type *, char *, struct symbol **);
+static int find_methods (struct type *, char *,
+ enum language, struct symbol **);
static int add_matching_methods (int method_counter, struct type *t,
+ enum language language,
struct symbol **sym_arr);
static int add_constructors (int method_counter, struct type *t,
+ enum language language,
struct symbol **sym_arr);
static void build_canonical_line_spec (struct symtab_and_line *,
char ***canonical,
char *copy,
struct symbol *sym,
- struct symtab *file_symtab,
- struct symtab *sym_symtab);
+ struct symtab *file_symtab);
static struct
symtabs_and_lines minsym_found (int funfirstline,
Note that this function is g++ specific. */
static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
+find_methods (struct type *t, char *name, enum language language,
+ struct symbol **sym_arr)
{
int i1 = 0;
int ibase;
unless we figure out how to get the physname without the name of
the class, then the loop can't do any good. */
if (class_name
- && (lookup_symbol (class_name, (struct block *) NULL,
- STRUCT_DOMAIN, (int *) NULL,
- (struct symtab **) NULL)))
+ && (lookup_symbol_in_language (class_name, (struct block *) NULL,
+ STRUCT_DOMAIN, language, (int *) NULL)))
{
int method_counter;
int name_len = strlen (name);
if (strcmp_iw (name, method_name) == 0)
/* Find all the overloaded methods with that name. */
- i1 += add_matching_methods (method_counter, t,
+ i1 += add_matching_methods (method_counter, t, language,
sym_arr + i1);
else if (strncmp (class_name, name, name_len) == 0
&& (class_name[name_len] == '\0'
|| class_name[name_len] == '<'))
- i1 += add_constructors (method_counter, t,
+ i1 += add_constructors (method_counter, t, language,
sym_arr + i1);
}
}
if (i1 == 0)
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
+ i1 += find_methods (TYPE_BASECLASS (t, ibase), name,
+ language, sym_arr + i1);
return i1;
}
static int
add_matching_methods (int method_counter, struct type *t,
- struct symbol **sym_arr)
+ enum language language, struct symbol **sym_arr)
{
int field_counter;
int i1 = 0;
}
else
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-
+
/* Destructor is handled by caller, don't add it to
the list. */
if (is_destructor_name (phys_name) != 0)
continue;
- sym_arr[i1] = lookup_symbol (phys_name,
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
NULL, VAR_DOMAIN,
- (int *) NULL,
- (struct symtab **) NULL);
+ language,
+ (int *) NULL);
if (sym_arr[i1])
i1++;
else
static int
add_constructors (int method_counter, struct type *t,
- struct symbol **sym_arr)
+ enum language language, struct symbol **sym_arr)
{
int field_counter;
int i1 = 0;
{
struct fn_field *f;
char *phys_name;
-
+
f = TYPE_FN_FIELDLIST1 (t, method_counter);
/* GCC 3.x will never produce stabs stub methods, so
/* If this method is actually defined, include it in the
list. */
- sym_arr[i1] = lookup_symbol (phys_name,
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
NULL, VAR_DOMAIN,
- (int *) NULL,
- (struct symtab **) NULL);
+ language,
+ (int *) NULL);
if (sym_arr[i1])
i1++;
}
char *symname;
struct cleanup *old_chain;
char **canonical_arr = (char **) NULL;
+ const char *select_mode = multiple_symbols_select_mode ();
+ if (select_mode == multiple_symbols_cancel)
+ error (_("\
+canceled because the command is ambiguous\n\
+See set/show multiple-symbol."));
+
values.sals = (struct symtab_and_line *)
alloca (nelts * sizeof (struct symtab_and_line));
return_values.sals = (struct symtab_and_line *)
}
i = 0;
- printf_unfiltered (_("[0] cancel\n[1] all\n"));
while (i < nelts)
{
init_sal (&return_values.sals[i]); /* Initialize to zeroes. */
init_sal (&values.sals[i]);
if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- {
- values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
- if (values.sals[i].symtab)
- printf_unfiltered ("[%d] %s at %s:%d\n",
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].symtab->filename,
- values.sals[i].line);
- else
- printf_unfiltered (_("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n"),
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].line);
-
- }
- else
- printf_unfiltered (_("?HERE\n"));
+ values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
i++;
}
- prompt = getenv ("PS2");
- if (prompt == NULL)
+ /* If select_mode is "all", then do not print the multiple-choice
+ menu and act as if the user had chosen choice "1" (all). */
+ if (select_mode == multiple_symbols_all
+ || ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+ args = "1";
+ else
{
- prompt = "> ";
+ i = 0;
+ printf_unfiltered (_("[0] cancel\n[1] all\n"));
+ while (i < nelts)
+ {
+ if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+ {
+ if (values.sals[i].symtab)
+ printf_unfiltered ("[%d] %s at %s:%d\n",
+ (i + 2),
+ SYMBOL_PRINT_NAME (sym_arr[i]),
+ values.sals[i].symtab->filename,
+ values.sals[i].line);
+ else
+ printf_unfiltered (_("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n"),
+ (i + 2),
+ SYMBOL_PRINT_NAME (sym_arr[i]),
+ values.sals[i].line);
+
+ }
+ else
+ printf_unfiltered (_("?HERE\n"));
+ i++;
+ }
+
+ prompt = getenv ("PS2");
+ if (prompt == NULL)
+ {
+ prompt = "> ";
+ }
+ args = command_line_input (prompt, 0, "overload-choice");
}
- args = command_line_input (prompt, 0, "overload-choice");
if (args == 0 || *args == 0)
error_no_arg (_("one or more choice numbers"));
return decode_compound (argptr, funfirstline, canonical,
saved_arg, p);
- /* No, the first part is a filename; set s to be that file's
+ /* No, the first part is a filename; set file_symtab to be that file's
symtab. Also, move argptr past the filename. */
file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\000';
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+ sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
if (sym)
{
*argptr = (*p == '\'') ? p + 1 : p;
- return symbol_found (funfirstline, canonical, copy, sym,
- NULL, sym_symtab);
+ return symbol_found (funfirstline, canonical, copy, sym, NULL);
}
/* Otherwise fall out from here and go to file/line spec
processing, etc. */
}
#endif
- /* S is specified file's symtab, or 0 if no file specified.
+ /* file_symtab is specified file's symtab, or 0 if no file specified.
arg no longer contains the file name. */
/* Check whether arg is all digits (and sign). */
values.sals[0] = find_pc_line (pc, 0);
values.sals[0].pc = pc;
values.sals[0].section = find_pc_overlay (pc);
+ values.sals[0].explicit_pc = 1;
return values;
}
if (file_symtab != NULL)
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
else
- block = get_selected_block (0);
-
+ {
+ enum language save_language;
+
+ /* get_selected_block can change the current language when there is
+ no selected frame yet. */
+ save_language = current_language->la_language;
+ block = get_selected_block (0);
+ set_language (save_language);
+ }
+
copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2);
if (i1 > 0)
{
sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
- sym_arr[i1] = 0;
+ sym_arr[i1] = NULL;
copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
*argptr = copy;
else
{
/* The only match was a non-debuggable symbol. */
- values.sals[0].symtab = 0;
+ values.sals[0].symtab = NULL;
values.sals[0].line = 0;
values.sals[0].end = 0;
values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
char *saved_arg2 = *argptr;
char *temp_end;
struct symbol *sym;
- /* The symtab that SYM was found in. */
- struct symtab *sym_symtab;
char *copy;
struct symbol *sym_class;
struct symbol **sym_arr;
*argptr = (*p == '\'') ? p + 1 : p;
/* Look up entire name */
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+ sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
if (sym)
- return symbol_found (funfirstline, canonical, copy, sym,
- NULL, sym_symtab);
+ return symbol_found (funfirstline, canonical, copy, sym, NULL);
/* Couldn't find any interpretation as classes/namespaces, so give
up. The quotes are important if copy is empty. */
/* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA",
argptr->"inA::fun" */
- return lookup_symbol (copy, 0, STRUCT_DOMAIN, 0,
- (struct symtab **) NULL);
+ return lookup_symbol (copy, 0, STRUCT_DOMAIN, 0);
}
/* This finds the method COPY in the class whose type is T and whose
char *copy, struct type *t, struct symbol *sym_class)
{
struct symtabs_and_lines values;
- struct symbol *sym = 0;
+ struct symbol *sym = NULL;
int i1; /* Counter for the symbol array. */
struct symbol **sym_arr = alloca (total_number_of_methods (t)
* sizeof (struct symbol *));
/* Find all methods with a matching name, and put them in
sym_arr. */
- i1 = collect_methods (copy, t, sym_arr);
+ i1 = collect_methods (copy, t, sym_class, sym_arr);
if (i1 == 1)
{
static int
collect_methods (char *copy, struct type *t,
- struct symbol **sym_arr)
+ struct symbol *sym_class, struct symbol **sym_arr)
{
int i1 = 0; /* Counter for the symbol array. */
sym_arr[i1] =
lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
- NULL, VAR_DOMAIN, (int *) NULL,
- (struct symtab **) NULL);
+ NULL, VAR_DOMAIN, (int *) NULL);
if (sym_arr[i1])
i1++;
}
}
else
- i1 = find_methods (t, copy, sym_arr);
+ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
return i1;
}
sign = none;
/* We might need a canonical line spec if no file was specified. */
- int need_canonical = (file_symtab == 0) ? 1 : 0;
+ int need_canonical = (file_symtab == NULL) ? 1 : 0;
init_sal (&val);
values.nelts = 1;
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
+ values.sals[0].explicit_line = 1;
return values;
}
struct symtab_and_line val;
char *p;
struct symbol *sym;
- /* The symtab that SYM was found in. */
- struct symtab *sym_symtab;
struct minimal_symbol *msymbol;
p = (copy[1] == '$') ? copy + 2 : copy + 1;
convenience variable. */
/* Look up entire name as a symbol first. */
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
- file_symtab = (struct symtab *) 0;
+ sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+ file_symtab = (struct symtab *) NULL;
need_canonical = 1;
/* Symbol was found --> jump to normal symbol processing. */
if (sym)
- return symbol_found (funfirstline, canonical, copy, sym,
- NULL, sym_symtab);
+ return symbol_found (funfirstline, canonical, copy, sym, NULL);
/* If symbol was not found, look in minimal symbol tables. */
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
return minsym_found (funfirstline, msymbol);
/* Not a user variable or function -- must be convenience variable. */
- need_canonical = (file_symtab == 0) ? 1 : 0;
valx = value_of_internalvar (lookup_internalvar (copy + 1));
if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
error (_("Convenience variables used in line specs must have integer values."));
struct symtab *file_symtab, int *not_found_ptr)
{
struct symbol *sym;
- /* The symtab that SYM was found in. */
- struct symtab *sym_symtab;
struct minimal_symbol *msymbol;
? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
STATIC_BLOCK)
: get_selected_block (0)),
- VAR_DOMAIN, 0, &sym_symtab);
+ VAR_DOMAIN, 0);
if (sym != NULL)
- return symbol_found (funfirstline, canonical, copy, sym,
- file_symtab, sym_symtab);
+ return symbol_found (funfirstline, canonical, copy, sym, file_symtab);
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
static struct symtabs_and_lines
symbol_found (int funfirstline, char ***canonical, char *copy,
- struct symbol *sym, struct symtab *file_symtab,
- struct symtab *sym_symtab)
+ struct symbol *sym, struct symtab *file_symtab)
{
struct symtabs_and_lines values;
function. */
if (file_symtab == 0)
{
- struct blockvector *bv = BLOCKVECTOR (sym_symtab);
+ struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
build_canonical_line_spec (values.sals, copy, canonical);
xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
memset (&values.sals[0], 0, sizeof (values.sals[0]));
- values.sals[0].symtab = sym_symtab;
+ values.sals[0].symtab = SYMBOL_SYMTAB (sym);
values.sals[0].line = SYMBOL_LINE (sym);
return values;
}
static struct symtabs_and_lines
minsym_found (int funfirstline, struct minimal_symbol *msymbol)
{
+ struct objfile *objfile = msymbol_objfile (msymbol);
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct symtabs_and_lines values;
+ CORE_ADDR pc;
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
(struct bfd_section *) 0, 0);
values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
+
+ /* The minimal symbol might point to a function descriptor;
+ resolve it to the actual code address instead. */
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
+ values.sals[0].pc,
+ ¤t_target);
+ if (pc != values.sals[0].pc)
+ values.sals[0] = find_pc_sect_line (pc, NULL, 0);
+
if (funfirstline)
{
- values.sals[0].pc += DEPRECATED_FUNCTION_START_OFFSET;
- values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
+ struct symtab_and_line sal;
+
+ values.sals[0].pc = find_function_start_pc (gdbarch,
+ values.sals[0].pc,
+ values.sals[0].section);
+
+ sal = find_pc_sect_line (values.sals[0].pc, values.sals[0].section, 0);
+
+ /* Check if SKIP_PROLOGUE left us in mid-line, and the next
+ line is still part of the same function. If there is no
+ line information here, sal.pc will be the passed in PC. */
+ if (sal.pc != values.sals[0].pc
+ && (lookup_minimal_symbol_by_pc_section (values.sals[0].pc,
+ values.sals[0].section)
+ == lookup_minimal_symbol_by_pc_section (sal.end,
+ values.sals[0].section)))
+ /* Recalculate the line number (might not be N+1). */
+ values.sals[0] = find_pc_sect_line (sal.end, values.sals[0].section, 0);
}
+
values.nelts = 1;
return values;
}