/* 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
- Free Software Foundation, Inc.
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
+ 2009, 2010 Free Software Foundation, Inc.
This file is part of GDB.
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
+#include "cp-support.h"
#include "parser-defs.h"
#include "block.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. */
int funfirstline,
char ***canonical,
char *saved_arg,
- char *p);
+ char *p,
+ int *not_found_ptr);
static struct symbol *lookup_prefix_sym (char **argptr, char *p);
char *saved_arg,
char *copy,
struct type *t,
- struct symbol *sym_class);
-
-static int collect_methods (char *copy, struct type *t,
- struct symbol *sym_class,
- struct symbol **sym_arr);
+ struct symbol *sym_class,
+ int *not_found_ptr);
static NORETURN void cplusplus_error (const char *name,
const char *fmt, ...)
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,
cplusplus_error (const char *name, const char *fmt, ...)
{
struct ui_file *tmp_stream;
+ char *message;
tmp_stream = mem_fileopen ();
make_cleanup_ui_file_delete (tmp_stream);
("Hint: try '%s<TAB> or '%s<ESC-?>\n"
"(Note leading single quote.)"),
name, name);
- error_stream (tmp_stream);
+
+ message = ui_file_xstrdup (tmp_stream, NULL);
+ make_cleanup (xfree, message);
+ throw_error (NOT_FOUND_ERROR, "%s", message);
}
/* Return the number of methods described for TYPE, including the
the class, then the loop can't do any good. */
if (class_name
&& (lookup_symbol_in_language (class_name, (struct block *) NULL,
- STRUCT_DOMAIN, language, (int *) NULL,
- (struct symtab **) NULL)))
+ STRUCT_DOMAIN, language, (int *) NULL)))
{
int method_counter;
int name_len = strlen (name);
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_in_language (phys_name,
NULL, VAR_DOMAIN,
language,
- (int *) NULL,
- (struct symtab **) NULL);
+ (int *) NULL);
if (sym_arr[i1])
i1++;
else
sym_arr[i1] = lookup_symbol_in_language (phys_name,
NULL, VAR_DOMAIN,
language,
- (int *) NULL,
- (struct symtab **) NULL);
+ (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"));
{
if (canonical_arr[i] == NULL)
{
- symname = DEPRECATED_SYMBOL_NAME (sym_arr[i]);
- canonical_arr[i] = savestring (symname, strlen (symname));
+ symname = SYMBOL_LINKAGE_NAME (sym_arr[i]);
+ canonical_arr[i] = xstrdup (symname);
}
}
}
{
if (canonical_arr)
{
- symname = DEPRECATED_SYMBOL_NAME (sym_arr[num]);
+ symname = SYMBOL_LINKAGE_NAME (sym_arr[num]);
make_cleanup (xfree, symname);
- canonical_arr[i] = savestring (symname, strlen (symname));
+ canonical_arr[i] = xstrdup (symname);
}
return_values.sals[i++] = values.sals[num];
values.sals[num].pc = 0;
if (p[0] == '.' || p[1] == ':')
return decode_compound (argptr, funfirstline, canonical,
- saved_arg, p);
+ saved_arg, p, not_found_ptr);
- /* 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). */
p = skip_quoted (*argptr);
}
+ /* Keep any template parameters */
+ if (*p == '<')
+ p = find_template_name_end (p);
+
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
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)
}
else
{
- /* The only match was a non-debuggable symbol. */
- 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]);
+ /* The only match was a non-debuggable symbol, which might point
+ to a function descriptor; resolve it to the actual code address
+ instead. */
+ struct minimal_symbol *msymbol = (struct minimal_symbol *)sym_arr[0];
+ struct objfile *objfile = msymbol_objfile (msymbol);
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
+ ¤t_target);
+
+ init_sal (&values.sals[0]);
+ values.sals[0].pc = pc;
}
return values;
}
static struct symtabs_and_lines
decode_compound (char **argptr, int funfirstline, char ***canonical,
- char *saved_arg, char *p)
+ char *saved_arg, char *p, int *not_found_ptr)
{
struct symtabs_and_lines values;
char *p2;
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;
/* Move pointer ahead to next double-colon. */
while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
{
+ if (current_language->la_language == language_cplus)
+ p += cp_validate_operator (p);
+
if (p[0] == '<')
{
temp_end = find_template_name_end (p);
while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
p++;
/* At this point p->"". String ended. */
+ /* Nope, C++ operators could have spaces in them
+ ("foo::operator <" or "foo::operator delete []").
+ I apologize, this is a bit hacky... */
+ if (current_language->la_language == language_cplus
+ && *p == ' ' && p - 8 - *argptr + 1 > 0)
+ {
+ /* The above loop has already swallowed "operator". */
+ p += cp_validate_operator (p - 8) - 8;
+ }
}
/* Allocate our own copy of the substring between argptr and
we'll lookup the whole string in the symbol tables. */
return find_method (funfirstline, canonical, saved_arg,
- copy, t, sym_class);
+ copy, t, sym_class, not_found_ptr);
} /* End if symbol found */
*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. */
+ if (not_found_ptr)
+ *not_found_ptr = 1;
cplusplus_error (saved_arg,
"Can't find member of namespace, class, struct, or union named \"%s\"\n",
copy);
{
char *p1;
char *copy;
+ struct symbol *sym;
/* Extract the class name. */
p1 = p;
/* 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);
+ sym = lookup_symbol (copy, 0, STRUCT_DOMAIN, 0);
+ if (sym == NULL)
+ {
+ /* Typedefs are in VAR_DOMAIN so the above symbol lookup will
+ fail when the user attempts to lookup a method of a class
+ via a typedef'd name (NOT via the class's name, which is already
+ handled in symbol_matches_domain). So try the lookup again
+ using VAR_DOMAIN (where typedefs live) and double-check that we
+ found a struct/class type. */
+ struct symbol *s = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+ if (s != NULL)
+ {
+ struct type *t = SYMBOL_TYPE (s);
+ CHECK_TYPEDEF (t);
+ if (TYPE_CODE (t) == TYPE_CODE_STRUCT)
+ return s;
+ }
+ }
+
+ return sym;
}
/* This finds the method COPY in the class whose type is T and whose
static struct symtabs_and_lines
find_method (int funfirstline, char ***canonical, char *saved_arg,
- char *copy, struct type *t, struct symbol *sym_class)
+ char *copy, struct type *t, struct symbol *sym_class, int *not_found_ptr)
{
struct symtabs_and_lines values;
struct symbol *sym = NULL;
/* Find all methods with a matching name, and put them in
sym_arr. */
- i1 = collect_methods (copy, t, sym_class, sym_arr);
+ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
if (i1 == 1)
{
}
else
{
- char *tmp;
-
- if (is_operator_name (copy))
- {
- tmp = (char *) alloca (strlen (copy + 3) + 9);
- strcpy (tmp, "operator ");
- strcat (tmp, copy + 3);
- }
- else
- tmp = copy;
- if (tmp[0] == '~')
+ if (not_found_ptr)
+ *not_found_ptr = 1;
+ if (copy[0] == '~')
cplusplus_error (saved_arg,
"the class `%s' does not have destructor defined\n",
SYMBOL_PRINT_NAME (sym_class));
else
cplusplus_error (saved_arg,
"the class %s does not have any method named %s\n",
- SYMBOL_PRINT_NAME (sym_class), tmp);
- }
-}
-
-/* Find all methods named COPY in the class whose type is T, and put
- them in SYM_ARR. Return the number of methods found. */
-
-static int
-collect_methods (char *copy, struct type *t,
- struct symbol *sym_class, struct symbol **sym_arr)
-{
- int i1 = 0; /* Counter for the symbol array. */
-
- if (destructor_name_p (copy, t))
- {
- /* Destructors are a special case. */
- int m_index, f_index;
-
- if (get_destructor_fn_field (t, &m_index, &f_index))
- {
- struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
-
- sym_arr[i1] =
- lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
- NULL, VAR_DOMAIN, (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- }
+ SYMBOL_PRINT_NAME (sym_class), copy);
}
- else
- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
-
- return i1;
}
\f
file_symtab = lookup_symtab (copy);
if (file_symtab == 0)
{
- if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
if (not_found_ptr)
*not_found_ptr = 1;
+ if (!have_full_symbols () && !have_partial_symbols ())
+ throw_error (NOT_FOUND_ERROR,
+ _("No symbol table is loaded. Use the \"file\" command."));
throw_error (NOT_FOUND_ERROR, _("No source file named %s."), copy);
}
init_sal (&val);
+ val.pspace = current_program_space;
+
/* This is where we need to make sure that we have good defaults.
We must guarantee that this section of code is never executed
when we are called with just a function name, since
if (val.symtab == 0)
val.symtab = file_symtab;
+ val.pspace = SYMTAB_PSPACE (val.symtab);
val.pc = 0;
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
char ***canonical, struct symtab *file_symtab)
{
- struct value *valx;
+ LONGEST valx;
int index = 0;
int need_canonical = 0;
struct symtabs_and_lines 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;
if (!*p) /* Reached end of token without hitting non-digit. */
{
/* We have a value history reference. */
+ struct value *val_history;
sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
- valx = access_value_history ((copy[1] == '$') ? -index : index);
- if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+ val_history = access_value_history ((copy[1] == '$') ? -index : index);
+ if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
error (_("History values used in line specs must have integer values."));
+ valx = value_as_long (val_history);
}
else
{
convenience variable. */
/* Look up entire name as a symbol first. */
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+ 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. */
- valx = value_of_internalvar (lookup_internalvar (copy + 1));
- if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+ if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
error (_("Convenience variables used in line specs must have integer values."));
}
/* Either history value or convenience value from above, in valx. */
val.symtab = file_symtab ? file_symtab : default_symtab;
- val.line = value_as_long (valx);
+ val.line = valx;
val.pc = 0;
+ val.pspace = current_program_space;
values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
values.sals[0] = val;
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);
if (msymbol != NULL)
return minsym_found (funfirstline, msymbol);
- if (!have_full_symbols () &&
- !have_partial_symbols () && !have_minimal_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
-
if (not_found_ptr)
*not_found_ptr = 1;
+
+ if (!have_full_symbols ()
+ && !have_partial_symbols ()
+ && !have_minimal_symbols ())
+ throw_error (NOT_FOUND_ERROR,
+ _("No symbol table is loaded. Use the \"file\" command."));
throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
}
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);
+ (struct obj_section *) 0, 0);
+ values.sals[0].section = SYMBOL_OBJ_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)
{
struct symtab_and_line sal;
- values.sals[0].pc
- += gdbarch_deprecated_function_start_offset (current_gdbarch);
- values.sals[0].pc = gdbarch_skip_prologue
- (current_gdbarch, values.sals[0].pc);
+ 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);