From 9d199712301d957dab5e5b98f7e555ef774d49bf Mon Sep 17 00:00:00 2001 From: John Gilmore Date: Fri, 19 Apr 1991 01:09:45 +0000 Subject: * symfile.c (clear_symtab_users_once, cashier_psymtab, free_named_symtabs): Move these routines from symmisc.c. --- gdb/symfile.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) (limited to 'gdb/symfile.c') diff --git a/gdb/symfile.c b/gdb/symfile.c index d2f8255..9aa9ee1 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -47,6 +47,7 @@ extern char *getenv (); /* Functions this file defines */ static bfd *symfile_open(); static struct sym_fns *symfile_init(); +static void clear_symtab_users_once(); /* List of all available sym_fns. */ @@ -93,6 +94,14 @@ struct complaint complaint_root[1] = { {(char *)0, 0, complaint_root}, }; +/* Some actual complaints. */ + +struct complaint oldsyms_complaint = { + "Replacing old symbols for `%s'", 0, 0 }; + +struct complaint empty_symtab_complaint = { + "Empty symbol table found for `%s'", 0, 0 }; + /* In the following sort, we always make sure that register debug symbol declarations always come before regular @@ -723,6 +732,183 @@ clear_complaints () p->counter = 0; } +/* clear_symtab_users_once: + + This function is run after symbol reading, or from a cleanup. + If an old symbol table was obsoleted, the old symbol table + has been blown away, but the other GDB data structures that may + reference it have not yet been cleared or re-directed. (The old + symtab was zapped, and the cleanup queued, in free_named_symtab() + below.) + + This function can be queued N times as a cleanup, or called + directly; it will do all the work the first time, and then will be a + no-op until the next time it is queued. This works by bumping a + counter at queueing time. Much later when the cleanup is run, or at + the end of symbol processing (in case the cleanup is discarded), if + the queued count is greater than the "done-count", we do the work + and set the done-count to the queued count. If the queued count is + less than or equal to the done-count, we just ignore the call. This + is needed because reading a single .o file will often replace many + symtabs (one per .h file, for example), and we don't want to reset + the breakpoints N times in the user's face. + + The reason we both queue a cleanup, and call it directly after symbol + reading, is because the cleanup protects us in case of errors, but is + discarded if symbol reading is successful. */ + +static int clear_symtab_users_queued; +static int clear_symtab_users_done; + +static void +clear_symtab_users_once () +{ + /* Enforce once-per-`do_cleanups'-semantics */ + if (clear_symtab_users_queued <= clear_symtab_users_done) + return; + clear_symtab_users_done = clear_symtab_users_queued; + + printf ("Resetting debugger state after updating old symbol tables\n"); + + /* Someday, we should do better than this, by only blowing away + the things that really need to be blown. */ + clear_value_history (); + clear_displays (); + clear_internalvars (); + breakpoint_re_set (); + set_default_breakpoint (0, 0, 0, 0); + current_source_symtab = 0; +} + +/* Delete the specified psymtab, and any others that reference it. */ + +cashier_psymtab (pst) + struct partial_symtab *pst; +{ + struct partial_symtab *ps, *pprev; + int i; + + /* Find its previous psymtab in the chain */ + for (ps = partial_symtab_list; ps; ps = ps->next) { + if (ps == pst) + break; + pprev = ps; + } + + if (ps) { + /* Unhook it from the chain. */ + if (ps == partial_symtab_list) + partial_symtab_list = ps->next; + else + pprev->next = ps->next; + + /* FIXME, we can't conveniently deallocate the entries in the + partial_symbol lists (global_psymbols/static_psymbols) that + this psymtab points to. These just take up space until all + the psymtabs are reclaimed. Ditto the dependencies list and + filename, which are all in the psymbol_obstack. */ + + /* We need to cashier any psymtab that has this one as a dependency... */ +again: + for (ps = partial_symtab_list; ps; ps = ps->next) { + for (i = 0; i < ps->number_of_dependencies; i++) { + if (ps->dependencies[i] == pst) { + cashier_psymtab (ps); + goto again; /* Must restart, chain has been munged. */ + } + } + } + } +} + +/* If a symtab or psymtab for filename NAME is found, free it along + with any dependent breakpoints, displays, etc. + Used when loading new versions of object modules with the "add-file" + command. This is only called on the top-level symtab or psymtab's name; + it is not called for subsidiary files such as .h files. + + Return value is 1 if we blew away the environment, 0 if not. + + FIXME. I think this is not the best way to do this. We should + work on being gentler to the environment while still cleaning up + all stray pointers into the freed symtab. */ + +int +free_named_symtabs (name) + char *name; +{ + register struct symtab *s; + register struct symtab *prev; + register struct partial_symtab *ps; + register struct partial_symtab *pprev; + struct blockvector *bv; + int blewit = 0; + + /* Look for a psymtab with the specified name. */ + +again2: + for (ps = partial_symtab_list; ps; ps = ps->next) { + if (!strcmp (name, ps->filename)) { + cashier_psymtab (ps); /* Blow it away...and its little dog, too. */ + goto again2; /* Must restart, chain has been munged */ + } + } + + /* Look for a symtab with the specified name. */ + + for (s = symtab_list; s; s = s->next) + { + if (!strcmp (name, s->filename)) + break; + prev = s; + } + + if (s) + { + if (s == symtab_list) + symtab_list = s->next; + else + prev->next = s->next; + + /* For now, queue a delete for all breakpoints, displays, etc., whether + or not they depend on the symtab being freed. This should be + changed so that only those data structures affected are deleted. */ + + /* But don't delete anything if the symtab is empty. + This test is necessary due to a bug in "dbxread.c" that + causes empty symtabs to be created for N_SO symbols that + contain the pathname of the object file. (This problem + has been fixed in GDB 3.9x). */ + + bv = BLOCKLIST (s); + if (BLOCKLIST_NBLOCKS (bv) > 2 + || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) + || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))) + { + complain (&oldsyms_complaint, name); + + clear_symtab_users_queued++; + make_cleanup (clear_symtab_users_once, 0); + blewit = 1; + } else { + complain (&empty_symtab_complaint, name); + } + + free_symtab (s); + } + else + /* It is still possible that some breakpoints will be affected + even though no symtab was found, since the file might have + been compiled without debugging, and hence not be associated + with a symtab. In order to handle this correctly, we would need + to keep a list of text address ranges for undebuggable files. + For now, we do nothing, since this is a fairly obscure case. */ + ; + + /* FIXME, what about the misc function vector? */ + return blewit; +} + void _initialize_symfile () { -- cgit v1.1