[base] 2007-09-21 Jan Kratochvil * linespec.c (add_minsym_members): Support also the `$allocate' and `$delete' variants. 2007-10-05 Jan Kratochvil * 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. Index: gdb-6.5/gdb/linespec.c =================================================================== --- gdb-6.5.orig/gdb/linespec.c 2006-01-10 20:14:43.000000000 -0200 +++ gdb-6.5/gdb/linespec.c 2006-07-07 01:04:56.000000000 -0300 @@ -37,6 +37,7 @@ #include "objc-lang.h" #include "linespec.h" #include "exceptions.h" +#include "gdb_assert.h" /* We share this one with symtab.c, but it is not exported widely. */ @@ -75,7 +75,8 @@ static struct symtabs_and_lines find_met struct symbol *sym_class); static int collect_methods (char *copy, struct type *t, - struct symbol **sym_arr); + struct symbol **sym_arr, + struct minimal_symbol **msym_arr); static NORETURN void cplusplus_error (const char *name, const char *fmt, ...) @@ -83,10 +84,12 @@ static NORETURN void cplusplus_error (co 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 *, struct symbol **, + struct minimal_symbol **); static int add_matching_methods (int method_counter, struct type *t, - struct symbol **sym_arr); + struct symbol **sym_arr, + struct minimal_symbol **msym_arr); static int add_constructors (int method_counter, struct type *t, struct symbol **sym_arr); @@ -101,6 +104,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); @@ -191,12 +197,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, struct symbol **sym_arr) +find_methods (struct type *t, char *name, struct symbol **sym_arr, + struct minimal_symbol **msym_arr) { int i1 = 0; int ibase; @@ -239,7 +251,8 @@ 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, - 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] == '<')) @@ -261,21 +274,101 @@ 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, sym_arr + i1); + i1 += find_methods (TYPE_BASECLASS (t, ibase), name, 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, - struct symbol **sym_arr) + 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; @@ -299,6 +374,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. */ @@ -324,6 +409,9 @@ add_matching_methods (int method_counter } } + if (list) + xfree (list); + return i1; } @@ -603,6 +691,146 @@ decode_line_2 (struct symbol *sym_arr[], 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 = DEPRECATED_SYMBOL_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 = DEPRECATED_SYMBOL_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. */ @@ -1406,36 +1634,46 @@ find_method (int funfirstline, char ***c int i1; /* Counter for the symbol array. */ 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_arr); + i1 = collect_methods (copy, t, 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 @@ -1462,11 +1700,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_arr) + struct symbol **sym_arr, + struct minimal_symbol **msym_arr) { int i1 = 0; /* Counter for the symbol array. */ @@ -1488,7 +1727,7 @@ collect_methods (char *copy, struct type } } else - i1 = find_methods (t, copy, sym_arr); + i1 = find_methods (t, copy, sym_arr, msym_arr); return i1; } @@ -1976,12 +2021,13 @@ decode_dollar (char *copy, int funfirstl and do not issue an error message. */ static struct symtabs_and_lines -decode_variable (char *copy, int funfirstline, char ***canonical, - struct symtab *file_symtab, int *not_found_ptr) +decode_variable_1 (char *copy, int funfirstline, char ***canonical, + struct symtab *file_symtab) { struct symbol *sym; /* The symtab that SYM was found in. */ struct symtab *sym_symtab; + struct symtabs_and_lines retval; struct minimal_symbol *msymbol; @@ -2001,8 +2047,25 @@ decode_variable (char *copy, int funfirs msymbol = lookup_minimal_symbol (copy, NULL, NULL); if (msymbol != NULL) - return minsym_found (funfirstline, msymbol); + { + retval = minsym_found (funfirstline, msymbol); + + /* Create a `filename:linkage_symbol_name' reference. */ + if (file_symtab == 0) + build_canonical_line_spec (retval.sals, SYMBOL_LINKAGE_NAME (msymbol), + canonical); + + return retval; + } + retval.nelts = 0; + retval.sals = NULL; + return retval; +} + +static void +decode_variable_not_found (char *copy, int *not_found_ptr) +{ if (!have_full_symbols () && !have_partial_symbols () && !have_minimal_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); @@ -2010,6 +2064,132 @@ decode_variable (char *copy, int funfirs throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy); } +/* Wrapper of DECODE_VARIABLE_1 collecting the results for all the found + VARIANTS of the symbol COPY. */ + +static struct symtabs_and_lines +decode_variable (char *copy, int funfirstline, char ***canonical, + struct symtab *file_symtab, int *not_found_ptr) +{ + char *src; + char *src_point; + char *s, *point; + /* Keep "" last as the trimming part always matches it. */ + const char *variants[] = {"$base","$allocate","$delete",""}; + int i; + char *dst, *dst_point; + struct + { + struct symtabs_and_lines sals; + char **canonical; + } found[ARRAY_SIZE (variants)]; + struct symtabs_and_lines retval_sals; + char **retval_canonical = NULL; /* Shut up GCC. */ + int filled; + int canonicals = 0; /* Shut up GCC. */ + + src = copy; + src_point = strchr (src, '('); + if (src_point == NULL) + { + struct symtabs_and_lines sals; + + sals = decode_variable_1 (src, funfirstline, canonical, file_symtab); + if (sals.nelts > 0) + return sals; + decode_variable_not_found (copy, not_found_ptr); + /* NOTREACHED */ + } + + dst = xmalloc (strlen (src) + strlen ("$allocate") + 1); + dst_point = dst + (src_point - src); + + memcpy (dst, src, src_point - src); + + /* Trim out any variant markers there first. */ + for (i = 0; i < ARRAY_SIZE (variants); i++) + { + size_t len = strlen (variants[i]); + + if (dst_point - dst >= len + && memcmp (dst_point - len, variants[i], len) == 0) + { + dst_point -= len; + /* In fact it should not be needed here. */ + break; + } + } + + filled = 0; + /* And now try to append all of them. */ + for (i = 0; i < ARRAY_SIZE (variants); i++) + { + size_t len = strlen (variants[i]); + struct minimal_symbol *minsym2; + + memcpy (dst_point, variants[i], len); + strcpy (dst_point + len, src_point); + + found[i].canonical = NULL; + found[i].sals = decode_variable_1 (dst, funfirstline, + (canonical == NULL ? NULL + : &found[i].canonical), + file_symtab); + filled += found[i].sals.nelts; + } + xfree (dst); + if (filled == 0) + { + decode_variable_not_found (copy, not_found_ptr); + /* NOTREACHED */ + } + + retval_sals.nelts = filled; + retval_sals.sals = xmalloc (filled * sizeof *retval_sals.sals); + if (canonical != NULL) + { + retval_canonical = xmalloc (filled * sizeof *retval_canonical); + canonicals = 0; + } + filled = 0; + for (i = 0; i < ARRAY_SIZE (variants); i++) + { + memcpy (&retval_sals.sals[filled], found[i].sals.sals, + found[i].sals.nelts * sizeof *retval_sals.sals); + xfree (found[i].sals.sals); + if (canonical != NULL) + { + if (found[i].canonical == NULL) + memset (&retval_canonical[filled], 0, + found[i].sals.nelts * sizeof *retval_canonical); + else + { + int j; + + memcpy (&retval_canonical[filled], found[i].canonical, + found[i].sals.nelts * sizeof *retval_canonical); + for (j = 0; j < found[i].sals.nelts; j++) + if (found[i].canonical[j] != NULL) + canonicals++; + xfree (found[i].canonical); + } + } + filled += found[i].sals.nelts; + } + gdb_assert (filled == retval_sals.nelts); + + if (canonical != NULL) + { + if (canonicals != 0) + *canonical = retval_canonical; + else + { + *canonical = NULL; + xfree (retval_canonical); + } + } + return retval_sals; +} diff -u -rup gdb-6.6-orig/gdb/Makefile.in gdb-6.6/gdb/Makefile.in --- gdb-6.6-orig/gdb/Makefile.in 2007-10-05 15:22:37.000000000 +0200 +++ gdb-6.6/gdb/Makefile.in 2007-10-05 16:29:10.000000000 +0200 @@ -2266,7 +2266,7 @@ libunwind-frame.o: libunwind-frame.c $(d linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \ $(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \ $(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \ - $(objc_lang_h) $(linespec_h) $(exceptions_h) + $(objc_lang_h) $(linespec_h) $(exceptions_h) $(gdb_assert_h) linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \ $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \ $(linux_nat_h)