📄 symfile.c
字号:
systems have ill-constructed symbol files. */static unsigned stop_whining = 0;/* Should each complaint be self explanatory, or should we assume that a series of complaints is being produced? case 0: self explanatory message. case 1: First message of a series that must start off with explanation. case 2: Subsequent message, when user already knows we are reading symbols and we can just state our piece. */static int complaint_series = 0;/* Print a complaint about the input symbols, and link the complaint block into a chain for later handling. */voidcomplain (complaint, val) struct complaint *complaint; char *val;{ complaint->counter++; if (complaint->next == 0) { complaint->next = complaint_root->next; complaint_root->next = complaint; } if (complaint->counter > stop_whining) return; wrap_here (""); switch (complaint_series + (info_verbose << 1)) { /* Isolated messages, must be self-explanatory. */ case 0: puts_filtered ("During symbol reading, "); wrap_here(""); printf_filtered (complaint->message, val); puts_filtered (".\n"); break; /* First of a series, without `set verbose'. */ case 1: puts_filtered ("During symbol reading..."); printf_filtered (complaint->message, val); puts_filtered ("..."); wrap_here(""); complaint_series++; break; /* Subsequent messages of a series, or messages under `set verbose'. (We'll already have produced a "Reading in symbols for XXX..." message and will clean up at the end with a newline.) */ default: printf_filtered (complaint->message, val); puts_filtered ("..."); wrap_here(""); }}/* Clear out all complaint counters that have ever been incremented. If sym_reading is 1, be less verbose about successive complaints, since the messages are appearing all together during a command that reads symbols (rather than scattered around as psymtabs get fleshed out into symtabs at random times). If noisy is 1, we are in a noisy symbol reading command, and our caller will print enough context for the user to figure it out. */voidclear_complaints (sym_reading, noisy) int sym_reading; int noisy;{ struct complaint *p; for (p = complaint_root->next; p != complaint_root; p = p->next) p->counter = 0; if (!sym_reading && !noisy && complaint_series > 1) { /* Terminate previous series, since caller won't. */ puts_filtered ("\n"); } complaint_series = sym_reading? 1 + noisy: 0;}enum languagededuce_language_from_filename (filename) char *filename;{ char *c = strrchr (filename, '.'); if (!c) ; /* Get default. */ else if(!strcmp(c,".mod")) return language_m2; else if(!strcmp(c,".c")) return language_c; else if(!strcmp(c,".cc") || !strcmp(c,".C")) return language_cplus; return language_unknown; /* default */}/* allocate_symtab: Allocate and partly initialize a new symbol table. Return a pointer to it. error() if no space. Caller must set these fields: LINETABLE(symtab) symtab->blockvector symtab->dirname symtab->free_code symtab->free_ptr initialize any EXTRA_SYMTAB_INFO possibly free_named_symtabs (symtab->filename); */struct symtab *allocate_symtab (filename, objfile) char *filename; struct objfile *objfile;{ register struct symtab *symtab; symtab = (struct symtab *) obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symtab)); memset (symtab, 0, sizeof (*symtab)); symtab -> filename = obsavestring (filename, strlen (filename), &objfile -> symbol_obstack); symtab -> fullname = NULL; symtab -> language = deduce_language_from_filename (filename); /* Hook it to the objfile it comes from */ symtab -> objfile = objfile; symtab -> next = objfile -> symtabs; objfile -> symtabs = symtab;#ifdef INIT_EXTRA_SYMTAB_INFO INIT_EXTRA_SYMTAB_INFO (symtab);#endif return (symtab);}struct partial_symtab *allocate_psymtab (filename, objfile) char *filename; struct objfile *objfile;{ struct partial_symtab *psymtab; if (objfile -> free_psymtabs) { psymtab = objfile -> free_psymtabs; objfile -> free_psymtabs = psymtab -> next; } else psymtab = (struct partial_symtab *) obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct partial_symtab)); memset (psymtab, 0, sizeof (struct partial_symtab)); psymtab -> filename = obsavestring (filename, strlen (filename), &objfile -> psymbol_obstack); psymtab -> symtab = NULL; /* Hook it to the objfile it comes from */ psymtab -> objfile = objfile; psymtab -> next = objfile -> psymtabs; objfile -> psymtabs = psymtab; return (psymtab);}/* 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;voidclear_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. */static voidcashier_psymtab (pst) struct partial_symtab *pst;{ struct partial_symtab *ps, *pprev; int i; /* Find its previous psymtab in the chain */ for (ps = pst->objfile->psymtabs; ps; ps = ps->next) { if (ps == pst) break; pprev = ps; } if (ps) { /* Unhook it from the chain. */ if (ps == pst->objfile->psymtabs) pst->objfile->psymtabs = 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 = pst->objfile->psymtabs; 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. The return valu appears to never be used. 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. */intfree_named_symtabs (name) char *name;{#if 0 /* FIXME: With the new method of each objfile having it's own psymtab list, this function needs serious rethinking. In particular, why was it ever necessary to toss psymtabs with specific compilation unit filenames, as opposed to all psymtabs from a particular symbol file? -- fnf Well, the answer is that some systems permit reloading of particular compilation units. We want to blow away any old info about these compilation units, regardless of which objfiles they arrived in. --gnu. */ register struct symtab *s; register struct symtab *prev; register struct partial_symtab *ps; struct blockvector *bv; int blewit = 0; /* We only wack things if the symbol-reload switch is set. */ if (!symbol_reloading) return 0; /* Some symbol formats have trouble providing file names... */ if (name == 0 || *name == '\0') return 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 = BLOCKVECTOR (s); if (BLOCKVECTOR_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 minimal symbol table? */ return blewit;#else return (0);#endif}/* Allocate and partially fill a partial symtab. It will be completely filled at the end of the symbol list. SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR is the address relative to which its symbols are (incremental) or 0 (normal). */struct partial_symtab *start_psymtab_common (objfile, section_offsets, filename, textlow, global_syms, static_syms) struct objfile *objfile; struct section_offsets *section_offsets; char *filename; CORE_ADDR textlow; struct partial_symbol *global_syms; struct partial_symbol *static_syms;{ struct partial_symtab *psymtab; psymtab = allocate_psymtab (filename, objfile); psymtab -> section_offsets = section_offsets; psymtab -> textlow = textlow; psymtab -> texthigh = psymtab -> textlow; /* default */ psymtab -> globals_offset = global_syms - objfile -> global_psymbols.list; psymtab -> statics_offset = static_syms - objfile -> static_psymbols.list; return (psymtab);}/* Debugging versions of functions that are usually inline macros (see symfile.h). */#if 0 /* Don't quite work nowadays... *//* Add a symbol with a long value to a psymtab. Since one arg is a struct, we pass in a ptr and deref it (sigh). */voidadd_psymbol_to_list (name, namelength, namespace, class, list, val) char *name; int namelength; enum namespace namespace; enum address_class class; struct psymbol_allocation_list *list; long val;{ ADD_PSYMBOL_VT_TO_LIST (name, namelength, namespace, class, (*list), val, SYMBOL_VALUE);}/* Add a symbol with a CORE_ADDR value to a psymtab. */voidadd_psymbol_addr_to_list (name, namelength, namespace, class, list, val) char *name; int namelength; enum namespace namespace; enum address_class class; struct psymbol_allocation_list *list; CORE_ADDR val;{ ADD_PSYMBOL_VT_TO_LIST (name, namelength, namespace, class, (*list), val, SYMBOL_VALUE_ADDRESS);}#endif /* 0 */void_initialize_symfile (){ add_com ("symbol-file", class_files, symbol_file_command, "Load symbol table from executable file FILE.\n\The `file' command can also load symbol tables, as well as setting the file\n\to execute."); add_com ("add-symbol-file", class_files, add_symbol_file_command, "Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\The second argument provides the starting address of the file's text."); add_com ("load", class_files, load_command, "Dynamically load FILE into the running program, and record its symbols\n\for access from GDB."); add_show_from_set (add_set_cmd ("complaints", class_support, var_zinteger, (char *)&stop_whining, "Set max number of complaints about incorrect symbols.", &setlist), &showlist); add_show_from_set (add_set_cmd ("symbol-reloading", class_support, var_boolean, (char *)&symbol_reloading, "Set dynamic symbol table reloading multiple times in one run.", &setlist), &showlist);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -