464 lines
14 KiB
Diff
464 lines
14 KiB
Diff
[base]
|
||
|
||
2007-09-21 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
* linespec.c (add_minsym_members): Support also the `$allocate' and
|
||
`$delete' variants.
|
||
|
||
2007-10-05 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
* linespec.c (add_minsym_members): Support also the `$allocate' and
|
||
`$delete' variants.
|
||
(decode_variable): Renamed to ...
|
||
(decode_variable_1) ... here, its parameter NOT_FOUND_PTR and its
|
||
exception throwing was moved to ...
|
||
(decode_variable_not_found): ... a new function here.
|
||
(decode_variable): New function.
|
||
|
||
2007-10-31 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
Port to GDB-6.7.
|
||
|
||
[ Remove decode_variable* for GDB-6.8+ as no longer needed. ]
|
||
|
||
Index: gdb-6.8.50.20081128/gdb/linespec.c
|
||
===================================================================
|
||
--- gdb-6.8.50.20081128.orig/gdb/linespec.c 2008-09-05 13:37:17.000000000 +0200
|
||
+++ gdb-6.8.50.20081128/gdb/linespec.c 2008-12-04 01:43:36.000000000 +0100
|
||
@@ -39,6 +39,7 @@
|
||
#include "interps.h"
|
||
#include "mi/mi-cmds.h"
|
||
#include "target.h"
|
||
+#include "gdb_assert.h"
|
||
|
||
/* We share this one with symtab.c, but it is not exported widely. */
|
||
|
||
@@ -78,7 +79,8 @@ static struct symtabs_and_lines find_met
|
||
|
||
static int collect_methods (char *copy, struct type *t,
|
||
struct symbol *sym_class,
|
||
- struct symbol **sym_arr);
|
||
+ struct symbol **sym_arr,
|
||
+ struct minimal_symbol **msym_arr);
|
||
|
||
static NORETURN void cplusplus_error (const char *name,
|
||
const char *fmt, ...)
|
||
@@ -87,11 +89,13 @@ static NORETURN void cplusplus_error (co
|
||
static int total_number_of_methods (struct type *type);
|
||
|
||
static int find_methods (struct type *, char *,
|
||
- enum language, struct symbol **);
|
||
+ enum language, struct symbol **,
|
||
+ struct minimal_symbol **);
|
||
|
||
static int add_matching_methods (int method_counter, struct type *t,
|
||
enum language language,
|
||
- struct symbol **sym_arr);
|
||
+ struct symbol **sym_arr,
|
||
+ struct minimal_symbol **msym_arr);
|
||
|
||
static int add_constructors (int method_counter, struct type *t,
|
||
enum language language,
|
||
@@ -107,6 +111,9 @@ static int is_objc_method_format (const
|
||
static struct symtabs_and_lines decode_line_2 (struct symbol *[],
|
||
int, int, char ***);
|
||
|
||
+static struct symtabs_and_lines decode_line_3 (struct minimal_symbol *[],
|
||
+ int, int, char ***);
|
||
+
|
||
static struct symtab *symtab_from_filename (char **argptr,
|
||
char *p, int is_quote_enclosed,
|
||
int *not_found_ptr);
|
||
@@ -196,13 +203,18 @@ total_number_of_methods (struct type *ty
|
||
/* Recursive helper function for decode_line_1.
|
||
Look for methods named NAME in type T.
|
||
Return number of matches.
|
||
- Put matches in SYM_ARR, which should have been allocated with
|
||
+ Put symbol matches in SYM_ARR, which should have been allocated with
|
||
a size of total_number_of_methods (T) * sizeof (struct symbol *).
|
||
+ In a special case where we are looking for constructors, we may
|
||
+ have to return minimal symbols in the array: MSYM_ARR. This occurs
|
||
+ when the compiler does not generate mangled names for the constructor's
|
||
+ debug info because there are multiple versions of the constructor
|
||
+ (in-charge vs not-in-charge).
|
||
Note that this function is g++ specific. */
|
||
|
||
static int
|
||
find_methods (struct type *t, char *name, enum language language,
|
||
- struct symbol **sym_arr)
|
||
+ struct symbol **sym_arr, struct minimal_symbol **msym_arr)
|
||
{
|
||
int i1 = 0;
|
||
int ibase;
|
||
@@ -244,7 +256,7 @@ find_methods (struct type *t, char *name
|
||
if (strcmp_iw (name, method_name) == 0)
|
||
/* Find all the overloaded methods with that name. */
|
||
i1 += add_matching_methods (method_counter, t, language,
|
||
- sym_arr + i1);
|
||
+ sym_arr + i1, msym_arr);
|
||
else if (strncmp (class_name, name, name_len) == 0
|
||
&& (class_name[name_len] == '\0'
|
||
|| class_name[name_len] == '<'))
|
||
@@ -267,21 +279,100 @@ find_methods (struct type *t, char *name
|
||
if (i1 == 0)
|
||
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
|
||
i1 += find_methods (TYPE_BASECLASS (t, ibase), name,
|
||
- language, sym_arr + i1);
|
||
+ language, sym_arr + i1, msym_arr);
|
||
|
||
return i1;
|
||
}
|
||
|
||
+static int
|
||
+add_minsym_members (const char *class_name,
|
||
+ const char *member_name,
|
||
+ struct minimal_symbol **msym_arr)
|
||
+{
|
||
+ char *completion_name;
|
||
+ char **list;
|
||
+ int i;
|
||
+ int comp_len;
|
||
+ int counter = 0;
|
||
+
|
||
+ /* To find the member, we first cheat and use symbol completion.
|
||
+ This will give us a list of all the member names including
|
||
+ the function signature. */
|
||
+ completion_name = xmalloc (strlen (class_name) +
|
||
+ strlen (member_name) + 9);
|
||
+ completion_name[0] = '\'';
|
||
+ strcpy (completion_name+1, class_name);
|
||
+ /* FIXME: make this the language class separator. */
|
||
+ strcat (completion_name, "::");
|
||
+ strcat (completion_name, member_name);
|
||
+ strcat (completion_name, "(");
|
||
+ list = make_symbol_completion_list (completion_name,
|
||
+ completion_name+1);
|
||
+
|
||
+ /* Now that we have the list, we generate an array of their
|
||
+ corresponding minimal symbols. */
|
||
+ counter = 0;
|
||
+ while (list && list[counter] != NULL)
|
||
+ {
|
||
+ msym_arr[counter] = lookup_minimal_symbol (list[counter], NULL, NULL);
|
||
+ ++counter;
|
||
+ }
|
||
+
|
||
+ xfree (list);
|
||
+
|
||
+ /* In the case of constructors, there may be in-charge vs not-in-charge
|
||
+ constructors. Check for names with $base which indicates not-in-charge
|
||
+ constructors. */
|
||
+ comp_len = strlen (completion_name);
|
||
+ strcpy (completion_name + comp_len - 1, "$base(");
|
||
+ list = make_symbol_completion_list (completion_name,
|
||
+ completion_name+1);
|
||
+
|
||
+ /* Again we have a list. Add their minimal symbols to the array. */
|
||
+ i = 0;
|
||
+ while (list && list[i] != NULL)
|
||
+ {
|
||
+ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL);
|
||
+ ++counter;
|
||
+ }
|
||
+ xfree (list);
|
||
+
|
||
+ /* Target also the allocating/deleting variants. */
|
||
+ if (member_name[0] == '~')
|
||
+ strcpy (completion_name + comp_len - 1, "$delete(");
|
||
+ else
|
||
+ strcpy (completion_name + comp_len - 1, "$allocate(");
|
||
+ list = make_symbol_completion_list (completion_name,
|
||
+ completion_name+1);
|
||
+
|
||
+ /* Again we have a list. Add their minimal symbols to the array. */
|
||
+ i = 0;
|
||
+ while (list && list[i] != NULL)
|
||
+ {
|
||
+ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL);
|
||
+ ++counter;
|
||
+ }
|
||
+ xfree (list);
|
||
+
|
||
+ xfree (completion_name);
|
||
+
|
||
+ return counter;
|
||
+}
|
||
+
|
||
/* 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)
|
||
+ enum language language, struct symbol **sym_arr,
|
||
+ struct minimal_symbol **msym_arr)
|
||
{
|
||
int field_counter;
|
||
int i1 = 0;
|
||
+ int cons_index = 0;
|
||
+ char *class_name = type_name_no_tag (t);
|
||
+ char **list = NULL;
|
||
|
||
for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
|
||
field_counter >= 0;
|
||
@@ -306,6 +397,16 @@ add_matching_methods (int method_counter
|
||
else
|
||
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
|
||
|
||
+ /* Check for special case of looking for member that
|
||
+ doesn't have a mangled name provided. This will happen
|
||
+ when we have in-charge and not-in-charge constructors.
|
||
+ Since we don't have a mangled name to work with, if we
|
||
+ look for the symbol, we can only find the class itself.
|
||
+ We can find the information we need in the minimal symbol
|
||
+ table which has the full member name information we need. */
|
||
+ if (strlen (phys_name) <= strlen (class_name))
|
||
+ return add_minsym_members (class_name, phys_name, msym_arr);
|
||
+
|
||
/* Destructor is handled by caller, don't add it to
|
||
the list. */
|
||
if (is_destructor_name (phys_name) != 0)
|
||
@@ -330,6 +431,9 @@ add_matching_methods (int method_counter
|
||
}
|
||
}
|
||
|
||
+ if (list)
|
||
+ xfree (list);
|
||
+
|
||
return i1;
|
||
}
|
||
|
||
@@ -630,6 +734,146 @@ See set/show multiple-symbol."));
|
||
discard_cleanups (old_chain);
|
||
return return_values;
|
||
}
|
||
+
|
||
+/* Given a list of NELTS minimal symbols in MSYM_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
|
||
+ as canonical line specs there. */
|
||
+
|
||
+static struct symtabs_and_lines
|
||
+decode_line_3 (struct minimal_symbol *msym_arr[],
|
||
+ int nelts, int funfirstline,
|
||
+ char ***canonical)
|
||
+{
|
||
+ struct symtabs_and_lines values, return_values;
|
||
+ char *args, *arg1;
|
||
+ int i;
|
||
+ char *prompt;
|
||
+ char *symname;
|
||
+ struct cleanup *old_chain;
|
||
+ char **canonical_arr = (char **) NULL;
|
||
+
|
||
+ values.sals = (struct symtab_and_line *)
|
||
+ alloca (nelts * sizeof (struct symtab_and_line));
|
||
+ return_values.sals = (struct symtab_and_line *)
|
||
+ xmalloc (nelts * sizeof (struct symtab_and_line));
|
||
+ old_chain = make_cleanup (xfree, return_values.sals);
|
||
+
|
||
+ if (canonical)
|
||
+ {
|
||
+ canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
|
||
+ make_cleanup (xfree, canonical_arr);
|
||
+ memset (canonical_arr, 0, nelts * sizeof (char *));
|
||
+ *canonical = canonical_arr;
|
||
+ }
|
||
+
|
||
+ 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 (msym_arr[i])
|
||
+ {
|
||
+ struct symtabs_and_lines msal = minsym_found (funfirstline,
|
||
+ msym_arr[i]);
|
||
+ memcpy (&values.sals[i], &msal.sals[0],
|
||
+ sizeof (struct symtab_and_line));
|
||
+ if (values.sals[i].symtab)
|
||
+ printf_unfiltered ("[%d] %s at %s:%d\n",
|
||
+ (i + 2),
|
||
+ SYMBOL_PRINT_NAME (msym_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 (msym_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");
|
||
+
|
||
+ if (args == 0 || *args == 0)
|
||
+ error_no_arg ("one or more choice numbers");
|
||
+
|
||
+ i = 0;
|
||
+ while (*args)
|
||
+ {
|
||
+ int num;
|
||
+
|
||
+ arg1 = args;
|
||
+ while (*arg1 >= '0' && *arg1 <= '9')
|
||
+ arg1++;
|
||
+ if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
|
||
+ error ("Arguments must be choice numbers.");
|
||
+
|
||
+ num = atoi (args);
|
||
+
|
||
+ if (num == 0)
|
||
+ error ("canceled");
|
||
+ else if (num == 1)
|
||
+ {
|
||
+ if (canonical_arr)
|
||
+ {
|
||
+ for (i = 0; i < nelts; i++)
|
||
+ {
|
||
+ if (canonical_arr[i] == NULL)
|
||
+ {
|
||
+ symname = SYMBOL_LINKAGE_NAME (msym_arr[i]);
|
||
+ canonical_arr[i] = savestring (symname, strlen (symname));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ memcpy (return_values.sals, values.sals,
|
||
+ (nelts * sizeof (struct symtab_and_line)));
|
||
+ return_values.nelts = nelts;
|
||
+ discard_cleanups (old_chain);
|
||
+ return return_values;
|
||
+ }
|
||
+
|
||
+ if (num >= nelts + 2)
|
||
+ {
|
||
+ printf_unfiltered ("No choice number %d.\n", num);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ num -= 2;
|
||
+ if (values.sals[num].pc)
|
||
+ {
|
||
+ if (canonical_arr)
|
||
+ {
|
||
+ symname = SYMBOL_LINKAGE_NAME (msym_arr[num]);
|
||
+ make_cleanup (xfree, symname);
|
||
+ canonical_arr[i] = savestring (symname, strlen (symname));
|
||
+ }
|
||
+ return_values.sals[i++] = values.sals[num];
|
||
+ values.sals[num].pc = 0;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ printf_unfiltered ("duplicate request for %d ignored.\n", num);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ args = arg1;
|
||
+ while (*args == ' ' || *args == '\t')
|
||
+ args++;
|
||
+ }
|
||
+ return_values.nelts = i;
|
||
+ discard_cleanups (old_chain);
|
||
+ return return_values;
|
||
+}
|
||
|
||
/* The parser of linespec itself. */
|
||
|
||
@@ -1438,35 +1682,46 @@ find_method (int funfirstline, char ***c
|
||
struct symbol **sym_arr = alloca (total_number_of_methods (t)
|
||
* sizeof (struct symbol *));
|
||
|
||
+ struct minimal_symbol **msym_arr = alloca (total_number_of_methods (t)
|
||
+ * sizeof (struct minimal_symbol *));
|
||
+
|
||
+ msym_arr[0] = NULL;
|
||
+
|
||
/* Find all methods with a matching name, and put them in
|
||
sym_arr. */
|
||
|
||
- i1 = collect_methods (copy, t, sym_class, sym_arr);
|
||
+ i1 = collect_methods (copy, t, sym_class, sym_arr, msym_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);
|
||
- }
|
||
+ if (msym_arr[0] != NULL)
|
||
+ return minsym_found (funfirstline, msym_arr[0]);
|
||
else
|
||
{
|
||
- values.sals = NULL;
|
||
- values.nelts = 0;
|
||
+ 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;
|
||
}
|
||
- return values;
|
||
}
|
||
if (i1 > 0)
|
||
{
|
||
/* There is more than one field with that name
|
||
(overloaded). Ask the user which one to use. */
|
||
+ if (msym_arr[0] != NULL)
|
||
+ return decode_line_3 (msym_arr, i1, funfirstline, canonical);
|
||
return decode_line_2 (sym_arr, i1, funfirstline, canonical);
|
||
}
|
||
else
|
||
@@ -1493,11 +1748,12 @@ find_method (int funfirstline, char ***c
|
||
}
|
||
|
||
/* Find all methods named COPY in the class whose type is T, and put
|
||
- them in SYM_ARR. Return the number of methods found. */
|
||
+ them in SYM_ARR or MSYM_ARR. Return the number of methods found. */
|
||
|
||
static int
|
||
collect_methods (char *copy, struct type *t,
|
||
- struct symbol *sym_class, struct symbol **sym_arr)
|
||
+ struct symbol *sym_class, struct symbol **sym_arr,
|
||
+ struct minimal_symbol **msym_arr)
|
||
{
|
||
int i1 = 0; /* Counter for the symbol array. */
|
||
|
||
@@ -1518,7 +1774,7 @@ collect_methods (char *copy, struct type
|
||
}
|
||
}
|
||
else
|
||
- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
|
||
+ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr);
|
||
|
||
return i1;
|
||
}
|