X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Flinespec.c;h=80aa3e12c43fe1274e030a5679fcbde883990775;hb=86443c3e9445d0cce7138f913c8979972c1d7b9d;hp=9efe1355f25a47eb9b45ad39e4c09265b319026d;hpb=22abf04a5d5485d051adac9d2447ad2fcbfb2704;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 9efe1355f2..80aa3e12c4 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1,13 +1,14 @@
/* Parser for linespec for the GNU debugger, GDB.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+
+ 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 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,
@@ -16,9 +17,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 . */
#include "defs.h"
#include "symtab.h"
@@ -31,8 +30,16 @@
#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. */
@@ -49,32 +56,59 @@ static struct symtabs_and_lines decode_indirect (char **argptr);
static char *locate_first_half (char **argptr, int *is_quote_enclosed);
+static struct symtabs_and_lines decode_objc (char **argptr,
+ int funfirstline,
+ struct symtab *file_symtab,
+ char ***canonical,
+ char *saved_arg);
+
static struct symtabs_and_lines decode_compound (char **argptr,
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);
+static struct symtabs_and_lines find_method (int funfirstline,
+ char ***canonical,
+ char *saved_arg,
+ char *copy,
+ struct type *t,
+ struct symbol *sym_class,
+ int *not_found_ptr);
+
static NORETURN void cplusplus_error (const char *name,
const char *fmt, ...)
ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
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 *, char ***);
static char *find_toplevel_char (char *s, char c);
+static int is_objc_method_format (const char *s);
+
static struct symtabs_and_lines decode_line_2 (struct symbol *[],
int, int, char ***);
static struct symtab *symtab_from_filename (char **argptr,
- char *p, int is_quote_enclosed);
+ char *p, int is_quote_enclosed,
+ int *not_found_ptr);
static struct
symtabs_and_lines decode_all_digits (char **argptr,
@@ -93,15 +127,15 @@ static struct symtabs_and_lines decode_dollar (char *copy,
static struct symtabs_and_lines decode_variable (char *copy,
int funfirstline,
char ***canonical,
- struct symtab *file_symtab);
+ struct symtab *file_symtab,
+ int *not_found_ptr);
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 symtab *file_symtab);
static struct
symtabs_and_lines minsym_found (int funfirstline,
@@ -117,6 +151,7 @@ static NORETURN void
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);
@@ -133,7 +168,10 @@ cplusplus_error (const char *name, const char *fmt, ...)
("Hint: try '%s or '%s\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
@@ -166,7 +204,8 @@ total_number_of_methods (struct type *type)
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;
@@ -176,9 +215,8 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
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_NAMESPACE, (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);
@@ -193,7 +231,6 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
method_counter >= 0;
--method_counter)
{
- int field_counter;
char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
char dem_opname[64];
@@ -209,88 +246,13 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
if (strcmp_iw (name, method_name) == 0)
/* Find all the overloaded methods with that name. */
- for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- {
- char *tmp_name;
-
- tmp_name = gdb_mangle_name (t,
- method_counter,
- field_counter);
- phys_name = alloca (strlen (tmp_name) + 1);
- strcpy (phys_name, tmp_name);
- xfree (tmp_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 (phys_name,
- NULL, VAR_NAMESPACE,
- (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- else
- {
- /* This error message gets printed, but the method
- still seems to be found
- fputs_filtered("(Cannot find method ", gdb_stdout);
- fprintf_symbol_filtered (gdb_stdout, phys_name,
- language_cplus,
- DMGL_PARAMS | DMGL_ANSI);
- fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
- */
- }
- }
+ 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] == '<'))
- {
- /* For GCC 3.x and stabs, constructors and destructors
- have names like __base_ctor and __complete_dtor.
- Check the physname for now if we're looking for a
- constructor. */
- for (field_counter
- = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
- /* GCC 3.x will never produce stabs stub methods, so
- we don't need to handle this case. */
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- continue;
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
- if (! is_constructor_name (phys_name))
- continue;
-
- /* If this method is actually defined, include it in the
- list. */
- sym_arr[i1] = lookup_symbol (phys_name,
- NULL, VAR_NAMESPACE,
- (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- }
- }
+ i1 += add_constructors (method_counter, t, language,
+ sym_arr + i1);
}
}
@@ -307,7 +269,110 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
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;
+}
+
+/* Add the symbols associated to methods of the class whose type is T
+ and whose name matches the method indexed by METHOD_COUNTER in the
+ array SYM_ARR. Return the number of methods added. */
+
+static int
+add_matching_methods (int method_counter, struct type *t,
+ enum language language, struct symbol **sym_arr)
+{
+ int field_counter;
+ int i1 = 0;
+
+ for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+ field_counter >= 0;
+ --field_counter)
+ {
+ struct fn_field *f;
+ char *phys_name;
+
+ f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ {
+ char *tmp_name;
+
+ tmp_name = gdb_mangle_name (t,
+ method_counter,
+ field_counter);
+ phys_name = alloca (strlen (tmp_name) + 1);
+ strcpy (phys_name, tmp_name);
+ xfree (tmp_name);
+ }
+ else
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
+ NULL, VAR_DOMAIN,
+ language,
+ (int *) NULL);
+ if (sym_arr[i1])
+ i1++;
+ else
+ {
+ /* This error message gets printed, but the method
+ still seems to be found
+ fputs_filtered("(Cannot find method ", gdb_stdout);
+ fprintf_symbol_filtered (gdb_stdout, phys_name,
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
+ */
+ }
+ }
+
+ return i1;
+}
+
+/* Add the symbols associated to constructors of the class whose type
+ is CLASS_TYPE and which are indexed by by METHOD_COUNTER to the
+ array SYM_ARR. Return the number of methods added. */
+
+static int
+add_constructors (int method_counter, struct type *t,
+ enum language language, struct symbol **sym_arr)
+{
+ int field_counter;
+ int i1 = 0;
+
+ /* For GCC 3.x and stabs, constructors and destructors
+ have names like __base_ctor and __complete_dtor.
+ Check the physname for now if we're looking for a
+ constructor. */
+ for (field_counter
+ = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+ field_counter >= 0;
+ --field_counter)
+ {
+ struct fn_field *f;
+ char *phys_name;
+
+ f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+ /* GCC 3.x will never produce stabs stub methods, so
+ we don't need to handle this case. */
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ continue;
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ if (! is_constructor_name (phys_name))
+ continue;
+
+ /* If this method is actually defined, include it in the
+ list. */
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
+ NULL, VAR_DOMAIN,
+ language,
+ (int *) NULL);
+ if (sym_arr[i1])
+ i1++;
+ }
return i1;
}
@@ -388,6 +453,25 @@ find_toplevel_char (char *s, char c)
return 0;
}
+/* Determines if the gives string corresponds to an Objective-C method
+ representation, such as -[Foo bar:] or +[Foo bar]. Objective-C symbols
+ are allowed to have spaces and parentheses in them. */
+
+static int
+is_objc_method_format (const char *s)
+{
+ if (s == NULL || *s == '\0')
+ return 0;
+ /* Handle arguments with the format FILENAME:SYMBOL. */
+ if ((s[0] == ':') && (strchr ("+-", s[1]) != NULL)
+ && (s[2] == '[') && strchr(s, ']'))
+ return 1;
+ /* Handle arguments that are just SYMBOL. */
+ else if ((strchr ("+-", s[0]) != NULL) && (s[1] == '[') && strchr(s, ']'))
+ return 1;
+ return 0;
+}
+
/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
operate on (ask user if necessary).
If CANONICAL is non-NULL return a corresponding array of mangled names
@@ -404,7 +488,13 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
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 *)
@@ -420,34 +510,56 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
}
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);
- 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 ("?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");
+ error_no_arg (_("one or more choice numbers"));
i = 0;
while (*args)
@@ -458,12 +570,12 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
while (*arg1 >= '0' && *arg1 <= '9')
arg1++;
if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
- error ("Arguments must be choice numbers.");
+ error (_("Arguments must be choice numbers."));
num = atoi (args);
if (num == 0)
- error ("canceled");
+ error (_("canceled"));
else if (num == 1)
{
if (canonical_arr)
@@ -472,8 +584,8 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
{
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);
}
}
}
@@ -486,7 +598,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
if (num >= nelts + 2)
{
- printf_unfiltered ("No choice number %d.\n", num);
+ printf_unfiltered (_("No choice number %d.\n"), num);
}
else
{
@@ -495,16 +607,16 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
{
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;
}
else
{
- printf_unfiltered ("duplicate request for %d ignored.\n", num);
+ printf_unfiltered (_("duplicate request for %d ignored.\n"), num);
}
}
@@ -554,7 +666,12 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
Note that it is possible to return zero for the symtab
if no file is validly specified. Callers must check that.
- Also, the line number returned may be invalid. */
+ Also, the line number returned may be invalid.
+
+ If NOT_FOUND_PTR is not null, store a boolean true/false value at the location, based
+ on whether or not failure occurs due to an unknown function or file. In the case
+ where failure does occur due to an unknown function or file, do not issue an error
+ message. */
/* We allow single quotes in various places. This is a hideous
kludge, which exists because the completer can't yet deal with the
@@ -563,7 +680,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
- int default_line, char ***canonical)
+ int default_line, char ***canonical, int *not_found_ptr)
{
char *p;
char *q;
@@ -579,8 +696,12 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
int is_quoted;
/* Is part of *ARGPTR is enclosed in double quotes? */
int is_quote_enclosed;
+ int is_objc_method = 0;
char *saved_arg = *argptr;
+ if (not_found_ptr)
+ *not_found_ptr = 0;
+
/* Defaults have defaults. */
initialize_defaults (&default_symtab, &default_line);
@@ -600,10 +721,32 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
/* Check to see if it's a multipart linespec (with colons or
periods). */
- /* Locate the end of the first half of the linespec. */
+ /* 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
+ 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. */
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))
+ {
+ is_objc_method = 1;
+ paren_pointer = NULL; /* Just a category name. Ignore it. */
+ }
+
+ /* Check if the symbol could be an Objective-C selector. */
+
+ {
+ struct symtabs_and_lines values;
+ values = decode_objc (argptr, funfirstline, NULL,
+ canonical, saved_arg);
+ if (values.sals != NULL)
+ return values;
+ }
+
/* Does it look like there actually were two parts? */
if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
@@ -611,16 +754,22 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
if (is_quoted)
*argptr = *argptr + 1;
- /* Is it a C++ or Java compound data structure? */
-
+ /* Is it a C++ or Java compound data structure?
+ The check on p[1] == ':' is capturing the case of "::",
+ since p[0]==':' was checked above.
+ Note that the call to decode_compound does everything
+ for us, including the lookup on the symbol table, so we
+ can return now. */
+
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);
+ file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
+ not_found_ptr);
}
#if 0
/* No one really seems to know why this was added. It certainly
@@ -645,19 +794,18 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\000';
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 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). */
@@ -683,7 +831,12 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
{
p = skip_quoted (*argptr);
if (p[-1] != '\'')
- error ("Unmatched single quote.");
+ error (_("Unmatched single quote."));
+ }
+ else if (is_objc_method)
+ {
+ /* allow word separators in method names for Obj-C */
+ p = skip_quoted_chars (*argptr, NULL, "");
}
else if (paren_pointer != NULL)
{
@@ -694,6 +847,10 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
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';
@@ -720,7 +877,8 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
/* Look up that token as a variable.
If file specified, use that file's per-file block to start with. */
- return decode_variable (copy, funfirstline, canonical, file_symtab);
+ return decode_variable (copy, funfirstline, canonical,
+ file_symtab, not_found_ptr);
}
@@ -826,6 +984,7 @@ decode_indirect (char **argptr)
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;
}
@@ -835,7 +994,9 @@ decode_indirect (char **argptr)
/* Locate the first half of the linespec, ending in a colon, period,
or whitespace. (More or less.) Also, check to see if *ARGPTR is
enclosed in double quotes; if so, set is_quote_enclosed, advance
- ARGPTR past that and zero out the trailing double quote. */
+ ARGPTR past that and zero out the trailing double quote.
+ If ARGPTR is just a simple name like "main", p will point to ""
+ at the end. */
static char *
locate_first_half (char **argptr, int *is_quote_enclosed)
@@ -880,9 +1041,15 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
{
char *temp_end = find_template_name_end (p);
if (!temp_end)
- error ("malformed template specification in command");
+ error (_("malformed template specification in command"));
p = temp_end;
}
+ /* Check for a colon and a plus or minus and a [ (which
+ indicates an Objective-C method) */
+ if (is_objc_method_format (p))
+ {
+ break;
+ }
/* Check for the end of the first half of the linespec. End of
line, a tab, a double colon or the last single colon, or a
space. But if enclosed in double quotes we do not break on
@@ -926,217 +1093,305 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
+/* Here's where we recognise an Objective-C Selector. An Objective C
+ selector may be implemented by more than one class, therefore it
+ may represent more than one method/function. This gives us a
+ situation somewhat analogous to C++ overloading. If there's more
+ than one method that could represent the selector, then use some of
+ the existing C++ code to let the user choose one. */
+
+struct symtabs_and_lines
+decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
+ char ***canonical, char *saved_arg)
+{
+ struct symtabs_and_lines values;
+ struct symbol **sym_arr = NULL;
+ struct symbol *sym = NULL;
+ char *copy = NULL;
+ struct block *block = NULL;
+ unsigned i1 = 0;
+ unsigned i2 = 0;
+
+ values.sals = NULL;
+ values.nelts = 0;
+
+ if (file_symtab != NULL)
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
+ else
+ {
+ 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] = NULL;
+
+ copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
+ *argptr = copy;
+ }
+
+ /* i1 now represents the TOTAL number of matches found.
+ i2 represents how many HIGH-LEVEL (struct symbol) matches,
+ which will come first in the sym_arr array. Any low-level
+ (minimal_symbol) matches will follow those. */
+
+ if (i1 == 1)
+ {
+ if (i2 > 0)
+ {
+ /* Already a struct symbol. */
+ sym = sym_arr[0];
+ }
+ else
+ {
+ sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
+ if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]), SYMBOL_LINKAGE_NAME (sym)) != 0)
+ {
+ warning (_("debugging symbol \"%s\" does not match selector; ignoring"), SYMBOL_LINKAGE_NAME (sym));
+ sym = NULL;
+ }
+ }
+
+ values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* Canonicalize this, so it remains resolved for dylib loads. */
+ values.sals[0] = find_function_start_sal (sym, funfirstline);
+ build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical);
+ }
+ else
+ {
+ /* 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;
+ }
+
+ if (i1 > 1)
+ {
+ /* More than one match. The user must choose one or more. */
+ return decode_line_2 (sym_arr, i2, funfirstline, canonical);
+ }
+
+ return values;
+}
+
/* This handles C++ and Java compound data structures. P should point
- at the first component separator, i.e. double-colon or period. */
+ at the first component separator, i.e. double-colon or period. As
+ an example, on entrance to this function we could have ARGPTR
+ pointing to "AAA::inA::fun" and P pointing to "::inA::fun". */
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;
-#if 0
- char *q, *q1;
-#endif
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;
- int i1;
struct symbol **sym_arr;
struct type *t;
- /* First check for "global" namespace specification,
- of the form "::foo". If found, skip over the colons
- and jump to normal symbol processing. */
+ /* First check for "global" namespace specification, of the form
+ "::foo". If found, skip over the colons and jump to normal
+ symbol processing. I.e. the whole line specification starts with
+ "::" (note the condition that *argptr == p). */
if (p[0] == ':'
&& ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
saved_arg2 += 2;
- /* We have what looks like a class or namespace
- scope specification (A::B), possibly with many
- levels of namespaces or classes (A::B::C::D).
-
- Some versions of the HP ANSI C++ compiler (as also possibly
- other compilers) generate class/function/member names with
- embedded double-colons if they are inside namespaces. To
- handle this, we loop a few times, considering larger and
- larger prefixes of the string as though they were single
- symbols. So, if the initially supplied string is
- A::B::C::D::foo, we have to look up "A", then "A::B",
- then "A::B::C", then "A::B::C::D", and finally
- "A::B::C::D::foo" as single, monolithic symbols, because
- A, B, C or D may be namespaces.
-
- Note that namespaces can nest only inside other
- namespaces, and not inside classes. So we need only
- consider *prefixes* of the string; there is no need to look up
- "B::C" separately as a symbol in the previous example. */
+ /* Given our example "AAA::inA::fun", we have two cases to consider:
- p2 = p; /* Save for restart. */
- while (1)
- {
- sym_class = lookup_prefix_sym (argptr, p);
+ 1) AAA::inA is the name of a class. In that case, presumably it
+ has a method called "fun"; we then look up that method using
+ find_method.
- if (sym_class &&
- (t = check_typedef (SYMBOL_TYPE (sym_class)),
- (TYPE_CODE (t) == TYPE_CODE_STRUCT
- || TYPE_CODE (t) == TYPE_CODE_UNION)))
- {
- /* Arg token is not digits => try it as a function name.
- Find the next token (everything up to end or next
- blank). */
- if (**argptr
- && strchr (get_gdb_completer_quote_characters (),
- **argptr) != NULL)
- {
- p = skip_quoted (*argptr);
- *argptr = *argptr + 1;
- }
- else
- {
- p = *argptr;
- while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
- p++;
- }
-/*
- q = operator_chars (*argptr, &q1);
- if (q1 - q)
- {
- char *opname;
- char *tmp = alloca (q1 - q + 1);
- memcpy (tmp, q, q1 - q);
- tmp[q1 - q] = '\0';
- opname = cplus_mangle_opname (tmp, DMGL_ANSI);
- if (opname == NULL)
- {
- cplusplus_error (saved_arg, "no mangling for \"%s\"\n", tmp);
- }
- copy = (char*) alloca (3 + strlen(opname));
- sprintf (copy, "__%s", opname);
- p = q1;
- }
- else
- */
- {
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\0';
- if (p != *argptr
- && copy[p - *argptr - 1]
- && strchr (get_gdb_completer_quote_characters (),
- copy[p - *argptr - 1]) != NULL)
- copy[p - *argptr - 1] = '\0';
- }
+ 2) AAA::inA isn't the name of a class. In that case, either the
+ user made a typo or AAA::inA is the name of a namespace.
+ Either way, we just look up AAA::inA::fun with lookup_symbol.
- /* No line number may be specified. */
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ Thus, our first task is to find everything before the last set of
+ double-colons and figure out if it's the name of a class. So we
+ first loop through all of the double-colons. */
- sym = 0;
- i1 = 0; /* Counter for the symbol array. */
- sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
- * sizeof (struct symbol *));
+ p2 = p; /* Save for restart. */
- if (destructor_name_p (copy, t))
- {
- /* Destructors are a special case. */
- int m_index, f_index;
+ /* This is very messy. Following the example above we have now the
+ following pointers:
+ p -> "::inA::fun"
+ argptr -> "AAA::inA::fun
+ saved_arg -> "AAA::inA::fun
+ saved_arg2 -> "AAA::inA::fun
+ p2 -> "::inA::fun". */
- 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_NAMESPACE, (int *) NULL,
- (struct symtab **) NULL);
- if (sym_arr[i1])
- i1++;
- }
- }
- else
- i1 = find_methods (t, copy, sym_arr);
- if (i1 == 1)
- {
- /* There is exactly one field with that name. */
- sym = sym_arr[0];
-
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym,
- funfirstline);
- }
- else
- {
- values.nelts = 0;
- }
- return values;
- }
- if (i1 > 0)
- {
- /* There is more than one field with that name
- (overloaded). Ask the user which one to use. */
- return decode_line_2 (sym_arr, i1, funfirstline, canonical);
- }
- 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] == '~')
- 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);
- }
- }
+ /* In the loop below, with these strings, we'll make 2 passes, each
+ is marked in comments.*/
+ while (1)
+ {
/* Move pointer up to next possible class/namespace token. */
+
p = p2 + 1; /* Restart with old value +1. */
+
+ /* PASS1: at this point p2->"::inA::fun", so p->":inA::fun",
+ i.e. if there is a double-colon, p will now point to the
+ second colon. */
+ /* PASS2: p2->"::fun", p->":fun" */
+
/* 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);
if (!temp_end)
- error ("malformed template specification in command");
+ error (_("malformed template specification in command"));
p = temp_end;
}
+ /* Note that, since, at the start of this loop, p would be
+ pointing to the second colon in a double-colon, we only
+ satisfy the condition below if there is another
+ double-colon to the right (after). I.e. there is another
+ component that can be a class or a namespace. I.e, if at
+ the beginning of this loop (PASS1), we had
+ p->":inA::fun", we'll trigger this when p has been
+ advanced to point to "::fun". */
+ /* PASS2: we will not trigger this. */
else if ((p[0] == ':') && (p[1] == ':'))
break; /* Found double-colon. */
else
+ /* PASS2: We'll keep getting here, until p->"", at which point
+ we exit this loop. */
p++;
}
if (*p != ':')
- break; /* Out of the while (1). */
-
- p2 = p; /* Save restart for next time around. */
- *argptr = saved_arg2; /* Restore argptr. */
+ break; /* Out of the while (1). This would happen
+ for instance if we have looked up
+ unsuccessfully all the components of the
+ string, and p->""(PASS2) */
+
+ /* We get here if p points to ' ', '\t', '\'', "::" or ""(i.e
+ string ended). */
+ /* Save restart for next time around. */
+ p2 = p;
+ /* Restore argptr as it was on entry to this function. */
+ *argptr = saved_arg2;
+ /* PASS1: at this point p->"::fun" argptr->"AAA::inA::fun",
+ p2->"::fun". */
+
+ /* All ready for next pass through the loop. */
} /* while (1) */
- /* Last chance attempt -- check entire name as a symbol. Use "copy"
- in preparation for jumping out of this block, to be consistent
- with usage following the jump target. */
+
+ /* Start of lookup in the symbol tables. */
+
+ /* Lookup in the symbol table the substring between argptr and
+ p. Note, this call changes the value of argptr. */
+ /* Before the call, argptr->"AAA::inA::fun",
+ p->"", p2->"::fun". After the call: argptr->"fun", p, p2
+ unchanged. */
+ sym_class = lookup_prefix_sym (argptr, p2);
+
+ /* If sym_class has been found, and if "AAA::inA" is a class, then
+ we're in case 1 above. So we look up "fun" as a method of that
+ class. */
+ if (sym_class &&
+ (t = check_typedef (SYMBOL_TYPE (sym_class)),
+ (TYPE_CODE (t) == TYPE_CODE_STRUCT
+ || TYPE_CODE (t) == TYPE_CODE_UNION)))
+ {
+ /* Arg token is not digits => try it as a function name.
+ Find the next token (everything up to end or next
+ blank). */
+ if (**argptr
+ && strchr (get_gdb_completer_quote_characters (),
+ **argptr) != NULL)
+ {
+ p = skip_quoted (*argptr);
+ *argptr = *argptr + 1;
+ }
+ else
+ {
+ /* At this point argptr->"fun". */
+ p = *argptr;
+ 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
+ p. */
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\0';
+ if (p != *argptr
+ && copy[p - *argptr - 1]
+ && strchr (get_gdb_completer_quote_characters (),
+ copy[p - *argptr - 1]) != NULL)
+ copy[p - *argptr - 1] = '\0';
+
+ /* At this point copy->"fun", p->"" */
+
+ /* No line number may be specified. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ *argptr = p;
+ /* At this point arptr->"". */
+
+ /* Look for copy as a method of sym_class. */
+ /* At this point copy->"fun", sym_class is "AAA:inA",
+ saved_arg->"AAA::inA::fun". This concludes the scanning of
+ the string for possible components matches. If we find it
+ here, we return. If not, and we are at the and of the string,
+ we'll lookup the whole string in the symbol tables. */
+
+ return find_method (funfirstline, canonical, saved_arg,
+ copy, t, sym_class, not_found_ptr);
+
+ } /* End if symbol found */
+
+
+ /* We couldn't find a class, so we're in case 2 above. We check the
+ entire name as a symbol instead. */
+
copy = (char *) alloca (p - saved_arg2 + 1);
memcpy (copy, saved_arg2, p - saved_arg2);
/* Note: if is_quoted should be true, we snuff out quote here
@@ -1144,14 +1399,16 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
copy[p - saved_arg2] = '\000';
/* Set argptr to skip over the name. */
*argptr = (*p == '\'') ? p + 1 : p;
+
/* Look up entire name */
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 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);
@@ -1162,13 +1419,16 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
/* Return the symbol corresponding to the substring of *ARGPTR ending
at P, allowing whitespace. Also, advance *ARGPTR past the symbol
name in question, the compound object separator ("::" or "."), and
- whitespace. */
+ whitespace. Note that *ARGPTR is changed whether or not the
+ lookup_symbol call finds anything (i.e we return NULL). As an
+ example, say ARGPTR is "AAA::inA::fun" and P is "::inA::fun". */
static struct symbol *
lookup_prefix_sym (char **argptr, char *p)
{
char *p1;
char *copy;
+ struct symbol *sym;
/* Extract the class name. */
p1 = p;
@@ -1178,23 +1438,107 @@ lookup_prefix_sym (char **argptr, char *p)
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = 0;
- /* Discard the class name from the arg. */
+ /* Discard the class name from the argptr. */
p = p1 + (p1[0] == ':' ? 2 : 1);
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
- return lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
- (struct symtab **) NULL);
+ /* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA",
+ argptr->"inA::fun" */
+
+ 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
+ symbol is SYM_CLASS. */
+
+static struct symtabs_and_lines
+find_method (int funfirstline, char ***canonical, char *saved_arg,
+ char *copy, struct type *t, struct symbol *sym_class, int *not_found_ptr)
+{
+ struct symtabs_and_lines values;
+ 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 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
+
+ if (i1 == 1)
+ {
+ /* There is exactly one field with that name. */
+ sym = sym_arr[0];
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ values.sals[0] = find_function_start_sal (sym,
+ funfirstline);
+ }
+ else
+ {
+ values.sals = NULL;
+ values.nelts = 0;
+ }
+ return values;
+ }
+ if (i1 > 0)
+ {
+ /* There is more than one field with that name
+ (overloaded). Ask the user which one to use. */
+ return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+ }
+ else
+ {
+ 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), copy);
+ }
}
/* Return the symtab associated to the filename given by the substring
- of *ARGPTR ending at P, and advance ARGPTR past that filename. */
+ of *ARGPTR ending at P, and advance ARGPTR past that filename. If
+ NOT_FOUND_PTR is not null and the source file is not found, store
+ boolean true at the location pointed to and do not issue an
+ error message. */
static struct symtab *
-symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+symtab_from_filename (char **argptr, char *p, int is_quote_enclosed,
+ int *not_found_ptr)
{
char *p1;
char *copy;
@@ -1217,9 +1561,12 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
file_symtab = lookup_symtab (copy);
if (file_symtab == 0)
{
+ if (not_found_ptr)
+ *not_found_ptr = 1;
if (!have_full_symbols () && !have_partial_symbols ())
- error ("No symbol table is loaded. Use the \"file\" command.");
- error ("No source file named %s.", copy);
+ 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);
}
/* Discard the file name from the arg. */
@@ -1253,10 +1600,12 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
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);
+ 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
@@ -1308,6 +1657,7 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
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));
@@ -1315,6 +1665,7 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
values.nelts = 1;
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
+ values.sals[0].explicit_line = 1;
return values;
}
@@ -1326,15 +1677,13 @@ static struct symtabs_and_lines
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;
@@ -1343,10 +1692,12 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
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)
- error ("History values used in line specs must have integer values.");
+ 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
{
@@ -1354,13 +1705,12 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
convenience variable. */
/* Look up entire name as a symbol first. */
- sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 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);
@@ -1369,18 +1719,17 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
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.");
+ if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
+ error (_("Convenience variables used in line specs must have integer values."));
}
init_sal (&val);
/* 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;
@@ -1395,15 +1744,15 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
/* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL,
- look in that symtab's static variables first. */
+ look in that symtab's static variables first. If NOT_FOUND_PTR is not NULL and
+ the function cannot be found, store boolean true in the location pointed to
+ and do not issue an error message. */
static struct symtabs_and_lines
decode_variable (char *copy, int funfirstline, char ***canonical,
- struct symtab *file_symtab)
+ 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;
@@ -1412,22 +1761,25 @@ decode_variable (char *copy, int funfirstline, char ***canonical,
? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
STATIC_BLOCK)
: get_selected_block (0)),
- VAR_NAMESPACE, 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;
- error ("Function \"%s\" not defined.", copy);
+ 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);
}
@@ -1441,8 +1793,7 @@ decode_variable (char *copy, int funfirstline, char ***canonical,
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;
@@ -1462,9 +1813,9 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
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_NAMESPACE) != NULL)
+ if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
build_canonical_line_spec (values.sals, copy, canonical);
}
return values;
@@ -1472,7 +1823,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
else
{
if (funfirstline)
- error ("\"%s\" is not a function", copy);
+ error (_("\"%s\" is not a function"), copy);
else if (SYMBOL_LINE (sym) != 0)
{
/* We know its line number. */
@@ -1480,7 +1831,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
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;
}
@@ -1490,7 +1841,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
/* FIXME: Shouldn't we just set .line and .symtab to zero
and return? For example, "info line foo" could print
the address. */
- error ("Line number not known for symbol \"%s\"", copy);
+ error (_("Line number not known for symbol \"%s\""), copy);
}
}
@@ -1500,18 +1851,47 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
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 sec *) 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)
{
- values.sals[0].pc += 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;
}