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; }