diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 75ff450701..e3a5c5415e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2013-08-01 Doug Evans + * symtab.c (do_free_search_symbols_cleanup): Change arg to, + effectively, struct symbol_search **. + (make_cleanup_free_search_symbols): Change arg to struct + symbol_search **. All callers updated. + (compare_search_syms): Compare symtab file name and block as well. + (search_symbols_equal): New function. + (sort_search_symbols_remove_dups): Renamed from sort_search_symbols. + New args new_head, new_tail. Result is now void. Remove dups after + sorting the symbols. + (search_symbols): Sort all found symbols once, after all have been + found, and remove duplicates. Simplify cleanup tracking of result. + * symtab.h (make_cleanup_free_search_symbols): Update prototype. + Further workarounds for binutils/15021. * dwarf2read.c (recursively_compute_inclusions): Change type of result parameter to VEC (symtab_ptr) **. New parameter all_type_symtabs. diff --git a/gdb/symtab.c b/gdb/symtab.c index 00662eafeb..237b2582e9 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3307,64 +3307,102 @@ free_search_symbols (struct symbol_search *symbols) } static void -do_free_search_symbols_cleanup (void *symbols) +do_free_search_symbols_cleanup (void *symbolsp) { + struct symbol_search *symbols = *(struct symbol_search **) symbolsp; + free_search_symbols (symbols); } struct cleanup * -make_cleanup_free_search_symbols (struct symbol_search *symbols) +make_cleanup_free_search_symbols (struct symbol_search **symbolsp) { - return make_cleanup (do_free_search_symbols_cleanup, symbols); + return make_cleanup (do_free_search_symbols_cleanup, symbolsp); } -/* Helper function for sort_search_symbols and qsort. Can only +/* Helper function for sort_search_symbols_remove_dups and qsort. Can only sort symbols, not minimal symbols. */ static int compare_search_syms (const void *sa, const void *sb) { - struct symbol_search **sym_a = (struct symbol_search **) sa; - struct symbol_search **sym_b = (struct symbol_search **) sb; + struct symbol_search *sym_a = *(struct symbol_search **) sa; + struct symbol_search *sym_b = *(struct symbol_search **) sb; + int c; - return strcmp (SYMBOL_PRINT_NAME ((*sym_a)->symbol), - SYMBOL_PRINT_NAME ((*sym_b)->symbol)); + c = strcmp (sym_a->symtab->filename, sym_b->symtab->filename); + if (c != 0) + return c; + + if (sym_a->block != sym_b->block) + return sym_a->block - sym_b->block; + + return strcmp (SYMBOL_PRINT_NAME (sym_a->symbol), + SYMBOL_PRINT_NAME (sym_b->symbol)); } -/* Sort the ``nfound'' symbols in the list after prevtail. Leave - prevtail where it is, but update its next pointer to point to - the first of the sorted symbols. */ +/* Helper function for sort_search_symbols_remove_dups. + Return TRUE if symbols A, B are equal. */ -static struct symbol_search * -sort_search_symbols (struct symbol_search *prevtail, int nfound) +static int +search_symbols_equal (const struct symbol_search *a, + const struct symbol_search *b) +{ + return (strcmp (a->symtab->filename, b->symtab->filename) == 0 + && a->block == b->block + && strcmp (SYMBOL_PRINT_NAME (a->symbol), + SYMBOL_PRINT_NAME (b->symbol)) == 0); +} + +/* Sort the NFOUND symbols in list FOUND and remove duplicates. + The duplicates are freed, and the new list is returned in + *NEW_HEAD, *NEW_TAIL. */ + +static void +sort_search_symbols_remove_dups (struct symbol_search *found, int nfound, + struct symbol_search **new_head, + struct symbol_search **new_tail) { struct symbol_search **symbols, *symp, *old_next; - int i; + int i, j, nunique; + gdb_assert (found != NULL && nfound > 0); + + /* Build an array out of the list so we can easily sort them. */ symbols = (struct symbol_search **) xmalloc (sizeof (struct symbol_search *) * nfound); - symp = prevtail->next; + symp = found; for (i = 0; i < nfound; i++) { + gdb_assert (symp != NULL); + gdb_assert (symp->block >= 0 && symp->block <= 1); symbols[i] = symp; symp = symp->next; } - /* Generally NULL. */ - old_next = symp; + gdb_assert (symp == NULL); qsort (symbols, nfound, sizeof (struct symbol_search *), compare_search_syms); - symp = prevtail; - for (i = 0; i < nfound; i++) + /* Collapse out the dups. */ + for (i = 1, j = 1; i < nfound; ++i) { - symp->next = symbols[i]; - symp = symp->next; + if (! search_symbols_equal (symbols[j - 1], symbols[i])) + symbols[j++] = symbols[i]; + else + xfree (symbols[i]); } - symp->next = old_next; + nunique = j; + symbols[j - 1]->next = NULL; + /* Rebuild the linked list. */ + for (i = 0; i < nunique - 1; i++) + symbols[i]->next = symbols[i + 1]; + symbols[nunique - 1]->next = NULL; + + *new_head = symbols[0]; + *new_tail = symbols[nunique - 1]; xfree (symbols); - return symp; } /* An object of this type is passed as the user_data to the @@ -3412,8 +3450,9 @@ search_symbols_name_matches (const char *symname, void *user_data) free_search_symbols should be called when *MATCHES is no longer needed. - The results are sorted locally; each symtab's global and static blocks are - separately alphabetized. */ + Within each file the results are sorted locally; each symtab's global and + static blocks are separately alphabetized. + Duplicate entries are removed. */ void search_symbols (char *regexp, enum search_domain kind, @@ -3441,10 +3480,10 @@ search_symbols (char *regexp, enum search_domain kind, enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; enum minimal_symbol_type ourtype4; - struct symbol_search *sr; - struct symbol_search *psr; + struct symbol_search *found; struct symbol_search *tail; struct search_symbols_data datum; + int nfound; /* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current CLEANUP_CHAIN is freed only in the case of an error. */ @@ -3458,8 +3497,7 @@ search_symbols (char *regexp, enum search_domain kind, ourtype3 = types3[kind]; ourtype4 = types4[kind]; - sr = *matches = NULL; - tail = NULL; + *matches = NULL; datum.preg_p = 0; if (regexp != NULL) @@ -3531,8 +3569,6 @@ search_symbols (char *regexp, enum search_domain kind, &datum); } - retval_chain = make_cleanup (null_cleanup, NULL); - /* Here, we search through the minimal symbol tables for functions and variables that match, and force their symbols to be read. This is in particular necessary for demangled variable names, @@ -3581,14 +3617,16 @@ search_symbols (char *regexp, enum search_domain kind, } } + found = NULL; + tail = NULL; + nfound = 0; + retval_chain = make_cleanup_free_search_symbols (&found); + ALL_PRIMARY_SYMTABS (objfile, s) { bv = BLOCKVECTOR (s); for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++) { - struct symbol_search *prevtail = tail; - int nfound = 0; - b = BLOCKVECTOR_BLOCK (bv, i); ALL_BLOCK_SYMBOLS (b, iter, sym) { @@ -3623,7 +3661,7 @@ search_symbols (char *regexp, enum search_domain kind, && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))) { /* match */ - psr = (struct symbol_search *) + struct symbol_search *psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); psr->block = i; psr->symtab = real_symtab; @@ -3631,31 +3669,22 @@ search_symbols (char *regexp, enum search_domain kind, psr->msymbol = NULL; psr->next = NULL; if (tail == NULL) - sr = psr; + found = psr; else tail->next = psr; tail = psr; nfound ++; } } - if (nfound > 0) - { - if (prevtail == NULL) - { - struct symbol_search dummy; - - dummy.next = sr; - tail = sort_search_symbols (&dummy, nfound); - sr = dummy.next; - - make_cleanup_free_search_symbols (sr); - } - else - tail = sort_search_symbols (prevtail, nfound); - } } } + if (found != NULL) + { + sort_search_symbols_remove_dups (found, nfound, &found, &tail); + /* Note: nfound is no longer useful beyond this point. */ + } + /* If there are no eyes, avoid all contact. I mean, if there are no debug symbols, then print directly from the msymbol_vector. */ @@ -3687,7 +3716,7 @@ search_symbols (char *regexp, enum search_domain kind, == NULL) { /* match */ - psr = (struct symbol_search *) + struct symbol_search *psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); psr->block = i; psr->msymbol = msymbol; @@ -3695,10 +3724,7 @@ search_symbols (char *regexp, enum search_domain kind, psr->symbol = NULL; psr->next = NULL; if (tail == NULL) - { - sr = psr; - make_cleanup_free_search_symbols (sr); - } + found = psr; else tail->next = psr; tail = psr; @@ -3711,7 +3737,7 @@ search_symbols (char *regexp, enum search_domain kind, discard_cleanups (retval_chain); do_cleanups (old_chain); - *matches = sr; + *matches = found; } /* Helper function for symtab_symbol_info, this function uses @@ -3793,7 +3819,7 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty) /* Must make sure that if we're interrupted, symbols gets freed. */ search_symbols (regexp, kind, 0, (char **) NULL, &symbols); - old_chain = make_cleanup_free_search_symbols (symbols); + old_chain = make_cleanup_free_search_symbols (&symbols); if (regexp != NULL) printf_filtered (_("All %ss matching regular expression \"%s\":\n"), @@ -3895,7 +3921,7 @@ rbreak_command (char *regexp, int from_tty) } search_symbols (regexp, FUNCTIONS_DOMAIN, nfiles, files, &ss); - old_chain = make_cleanup_free_search_symbols (ss); + old_chain = make_cleanup_free_search_symbols (&ss); make_cleanup (free_current_contents, &string); start_rbreak_breakpoints (); diff --git a/gdb/symtab.h b/gdb/symtab.h index a95a9cfdb7..32897aabb7 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1292,7 +1292,7 @@ struct symbol_search /* Information describing what was found. - If symtab abd symbol are NOT NULL, then information was found + If symtab and symbol are NOT NULL, then information was found for this match. */ struct symtab *symtab; struct symbol *symbol; @@ -1309,7 +1309,7 @@ extern void search_symbols (char *, enum search_domain, int, char **, struct symbol_search **); extern void free_search_symbols (struct symbol_search *); extern struct cleanup *make_cleanup_free_search_symbols (struct symbol_search - *); + **); /* The name of the ``main'' function. FIXME: cagney/2001-03-20: Can't make main_name() const since some