📄 symtab.c
字号:
/* Symbol table lookup for the GNU debugger, GDB. Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "symtab.h"#include "gdbtypes.h"#include "gdbcore.h"#include "frame.h"#include "target.h"#include "value.h"#include "symfile.h"#include "objfiles.h"#include "gdbcmd.h"#include "call-cmds.h"#include "regex.h"#include "expression.h"#include "language.h"#include "demangle.h"#include <obstack.h>#include <assert.h>#include <sys/types.h>#include <fcntl.h>#include <string.h>#include <sys/stat.h>#include <ctype.h>/* Prototypes for local functions */static char *expensive_mangler PARAMS ((const char *));extern intfind_methods PARAMS ((struct type *, char *, char **, struct symbol **));static voidcompletion_list_add_symbol PARAMS ((char *, char *, int));static struct symtabs_and_linesdecode_line_2 PARAMS ((struct symbol *[], int, int));static voidrbreak_command PARAMS ((char *, int));static voidtypes_info PARAMS ((char *, int));static voidfunctions_info PARAMS ((char *, int));static voidvariables_info PARAMS ((char *, int));static voidsources_info PARAMS ((char *, int));static voidlist_symbols PARAMS ((char *, int, int));static voidoutput_source_filename PARAMS ((char *, int *));static char *operator_chars PARAMS ((char *, char **));static intfind_line_common PARAMS ((struct linetable *, int, int *));static struct partial_symbol *lookup_partial_symbol PARAMS ((struct partial_symtab *, const char *, int, enum namespace));static struct partial_symbol *lookup_demangled_partial_symbol PARAMS ((const struct partial_symtab *, const char *));static struct symbol *lookup_demangled_block_symbol PARAMS ((const struct block *, const char *));static struct symtab *lookup_symtab_1 PARAMS ((char *));/* *//* The single non-language-specific builtin type */struct type *builtin_type_error;/* Block in which the most recently searched-for symbol was found. Might be better to make this a parameter to lookup_symbol and value_of_this. */const struct block *block_found;char no_symtab_msg[] = "No symbol table is loaded. Use the \"file\" command.";/* While the C++ support is still in flux, issue a possibly helpful hint on using the new command completion feature on single quoted demangled C++ symbols. Remove when loose ends are cleaned up. FIXME -fnf */voidcplusplus_hint (name) char *name;{ printf ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name); printf ("(Note leading single quote.)\n");}/* Check for a symtab of a specific name; first in symtabs, then in psymtabs. *If* there is no '/' in the name, a match after a '/' in the symtab filename will also work. */static struct symtab *lookup_symtab_1 (name) char *name;{ register struct symtab *s; register struct partial_symtab *ps; register char *slash; register struct objfile *objfile; got_symtab: /* First, search for an exact match */ ALL_SYMTABS (objfile, s) if (strcmp (name, s->filename) == 0) return s; slash = strchr (name, '/'); /* Now, search for a matching tail (only if name doesn't have any dirs) */ if (!slash) ALL_SYMTABS (objfile, s) { char *p = s -> filename; char *tail = strrchr (p, '/'); if (tail) p = tail + 1; if (strcmp (p, name) == 0) return s; } /* Same search rules as above apply here, but now we look thru the psymtabs. */ ALL_PSYMTABS (objfile, ps) if (strcmp (name, ps -> filename) == 0) goto got_psymtab; if (!slash) ALL_PSYMTABS (objfile, ps) { char *p = ps -> filename; char *tail = strrchr (p, '/'); if (tail) p = tail + 1; if (strcmp (p, name) == 0) goto got_psymtab; } return (NULL); got_psymtab: if (ps -> readin) error ("Internal: readin %s pst for `%s' found when no symtab found.", ps -> filename, name); s = PSYMTAB_TO_SYMTAB (ps); if (s) return s; /* At this point, we have located the psymtab for this file, but the conversion to a symtab has failed. This usually happens when we are looking up an include file. In this case, PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has been created. So, we need to run through the symtabs again in order to find the file. XXX - This is a crock, and should be fixed inside of the the symbol parsing routines. */ goto got_symtab;}/* Lookup the symbol table of a source file named NAME. Try a couple of variations if the first lookup doesn't work. */struct symtab *lookup_symtab (name) char *name;{ register struct symtab *s; register char *copy; s = lookup_symtab_1 (name); if (s) return s; /* If name not found as specified, see if adding ".c" helps. */ copy = (char *) alloca (strlen (name) + 3); strcpy (copy, name); strcat (copy, ".c"); s = lookup_symtab_1 (copy); if (s) return s; /* We didn't find anything; die. */ return 0;}/* Lookup the partial symbol table of a source file named NAME. This only returns true on an exact match (ie. this semantics are different from lookup_symtab. */struct partial_symtab *lookup_partial_symtab (name)char *name;{ register struct partial_symtab *pst; register struct objfile *objfile; ALL_PSYMTABS (objfile, pst) { if (strcmp (name, pst -> filename) == 0) { return (pst); } } return (NULL);}/* Demangle a GDB method stub type. */char *gdb_mangle_name (type, i, j) struct type *type; int i, j;{ int mangled_name_len; char *mangled_name; struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); struct fn_field *method = &f[j]; char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); char *newname = type_name_no_tag (type); int is_constructor = strcmp(field_name, newname) == 0; int is_destructor = is_constructor && physname[0] == '_' && physname[1] == CPLUS_MARKER && physname[2] == '_'; /* Need a new type prefix. */ char *const_prefix = method->is_const ? "C" : ""; char *volatile_prefix = method->is_volatile ? "V" : ""; char buf[20];#ifndef GCC_MANGLE_BUG int len = strlen (newname); if (is_destructor) { mangled_name = (char*) xmalloc(strlen(physname)+1); strcpy(mangled_name, physname); return mangled_name; } sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len); mangled_name_len = ((is_constructor ? 0 : strlen (field_name)) + strlen (buf) + len + strlen (physname) + 1); /* Only needed for GNU-mangled names. ANSI-mangled names work with the normal mechanisms. */ if (OPNAME_PREFIX_P (field_name)) { char *opname = cplus_mangle_opname (field_name + 3, 0); if (opname == NULL) error ("No mangling for \"%s\"", field_name); mangled_name_len += strlen (opname); mangled_name = (char *)xmalloc (mangled_name_len); strncpy (mangled_name, field_name, 3); mangled_name[3] = '\0'; strcat (mangled_name, opname); } else { mangled_name = (char *)xmalloc (mangled_name_len); if (is_constructor) mangled_name[0] = '\0'; else strcpy (mangled_name, field_name); } strcat (mangled_name, buf); strcat (mangled_name, newname);#else char *opname; if (is_constructor) { buf[0] = '\0'; } else { sprintf (buf, "__%s%s", const_prefix, volatile_prefix); } mangled_name_len = ((is_constructor ? 0 : strlen (field_name)) + strlen (buf) + strlen (physname) + 1); /* Only needed for GNU-mangled names. ANSI-mangled names work with the normal mechanisms. */ if (OPNAME_PREFIX_P (field_name)) { opname = cplus_mangle_opname (field_name + 3, 0); if (opname == NULL) { error ("No mangling for \"%s\"", field_name); } mangled_name_len += strlen (opname); mangled_name = (char *) xmalloc (mangled_name_len); strncpy (mangled_name, field_name, 3); strcpy (mangled_name + 3, opname); } else { mangled_name = (char *) xmalloc (mangled_name_len); if (is_constructor) { mangled_name[0] = '\0'; } else { strcpy (mangled_name, field_name); } } strcat (mangled_name, buf);#endif strcat (mangled_name, physname); return (mangled_name);}/* Find which partial symtab on contains PC. Return 0 if none. */struct partial_symtab *find_pc_psymtab (pc) register CORE_ADDR pc;{ register struct partial_symtab *pst; register struct objfile *objfile; ALL_PSYMTABS (objfile, pst) { if (pc >= pst -> textlow && pc < pst -> texthigh) { return (pst); } } return (NULL);}/* Find which partial symbol within a psymtab contains PC. Return 0 if none. Check all psymtabs if PSYMTAB is 0. */struct partial_symbol *find_pc_psymbol (psymtab, pc) struct partial_symtab *psymtab; CORE_ADDR pc;{ struct partial_symbol *best, *p; CORE_ADDR best_pc; if (!psymtab) psymtab = find_pc_psymtab (pc); if (!psymtab) return 0; best_pc = psymtab->textlow - 1; for (p = psymtab->objfile->static_psymbols.list + psymtab->statics_offset; (p - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset) < psymtab->n_static_syms); p++) if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE && SYMBOL_CLASS (p) == LOC_BLOCK && pc >= SYMBOL_VALUE_ADDRESS (p) && SYMBOL_VALUE_ADDRESS (p) > best_pc) { best_pc = SYMBOL_VALUE_ADDRESS (p); best = p; } if (best_pc == psymtab->textlow - 1) return 0; return best;}/* Find the definition for a specified symbol name NAME in namespace NAMESPACE, visible from lexical block BLOCK. Returns the struct symbol pointer, or zero if no symbol is found. If SYMTAB is non-NULL, store the symbol table in which the symbol was found there, or NULL if not found. C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if NAME is a field of the current implied argument `this'. If so set *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. BLOCK_FOUND is set to the block in which NAME is found (in the case of a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */struct symbol *lookup_symbol (name, block, namespace, is_a_field_of_this, symtab) const char *name; register const struct block *block; const enum namespace namespace; int *is_a_field_of_this; struct symtab **symtab;{ register struct symbol *sym; register struct symtab *s; register struct partial_symtab *ps; struct blockvector *bv; register struct objfile *objfile; register struct block *b; register struct minimal_symbol *msymbol; char *temp; extern char *gdb_completer_word_break_characters; /* If NAME contains any characters from gdb_completer_word_break_characters then it is probably from a quoted name string. So check to see if it has a C++ mangled equivalent, and if so, use the mangled equivalent. */ if (strpbrk (name, gdb_completer_word_break_characters) != NULL) { if ((temp = expensive_mangler (name)) != NULL) { name = temp; } } /* Search specified block and its superiors. */ while (block != 0) { sym = lookup_block_symbol (block, name, namespace); if (sym) { block_found = block; if (symtab != NULL) { /* Search the list of symtabs for one which contains the address of the start of this block. */ ALL_SYMTABS (objfile, s) { bv = BLOCKVECTOR (s); b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); if (BLOCK_START (b) <= BLOCK_START (block) && BLOCK_END (b) > BLOCK_START (block)) goto found; }found: *symtab = s; } return (sym); } block = BLOCK_SUPERBLOCK (block); } /* But that doesn't do any demangling for the STATIC_BLOCK.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -