/* Symbol table lookup for the GNU debugger, GDB.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+ Foundation, Inc.
This file is part of GDB.
const char *, int,
namespace_enum);
-static struct symbol *lookup_symbol_aux (const char *name, const
- struct block *block, const
- namespace_enum namespace, int
- *is_a_field_of_this, struct
- symtab **symtab);
+static struct symbol *lookup_symbol_aux (const char *name,
+ const char *mangled_name,
+ const struct block *block,
+ const namespace_enum namespace,
+ int *is_a_field_of_this,
+ struct symtab **symtab);
static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr);
register struct symtab *s;
register struct partial_symtab *ps;
register struct objfile *objfile;
+ char *real_path = NULL;
+ char *full_path = NULL;
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
got_symtab:
/* First, search for an exact match */
ALL_SYMTABS (objfile, s)
+ {
if (FILENAME_CMP (name, s->filename) == 0)
- return s;
+ {
+ return s;
+ }
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+
+ if (full_path != NULL)
+ {
+ const char *fp = symtab_to_filename (s);
+ if (FILENAME_CMP (full_path, fp) == 0)
+ {
+ return s;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ char *rp = gdb_realpath (symtab_to_filename (s));
+ make_cleanup (xfree, rp);
+ if (FILENAME_CMP (real_path, rp) == 0)
+ {
+ return s;
+ }
+ }
+ }
/* Now, search for a matching tail (only if name doesn't have any dirs) */
{
register struct partial_symtab *pst;
register struct objfile *objfile;
+ char *full_path = NULL;
+ char *real_path = NULL;
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
ALL_PSYMTABS (objfile, pst)
{
{
return (pst);
}
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+ if (full_path != NULL)
+ {
+ if (pst->fullname == NULL)
+ source_full_path_of (pst->filename, &pst->fullname);
+ if (pst->fullname != NULL
+ && FILENAME_CMP (full_path, pst->fullname) == 0)
+ {
+ return pst;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ char *rp = NULL;
+ if (pst->fullname == NULL)
+ source_full_path_of (pst->filename, &pst->fullname);
+ if (pst->fullname != NULL)
+ {
+ rp = gdb_realpath (pst->fullname);
+ make_cleanup (xfree, rp);
+ }
+ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+ {
+ return pst;
+ }
+ }
}
/* Now, search for a matching tail (only if name doesn't have any dirs) */
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));
- if (is_operator_name (field_name))
+ /* Nothing to do if physname already contains a fully mangled v3 abi name
+ or an operator name. */
+ if ((physname[0] == '_' && physname[1] == 'Z')
+ || is_operator_name (field_name))
return xstrdup (physname);
is_full_physname_constructor = is_constructor_name (physname);
strcat (mangled_name, physname);
return (mangled_name);
}
+
+\f
+/* Initialize a symbol's mangled name. */
+
+/* Try to initialize the demangled name for a symbol, based on the
+ language of that symbol. If the language is set to language_auto,
+ it will attempt to find any demangling algorithm that works and
+ then set the language appropriately. If no demangling of any kind
+ is found, the language is set back to language_unknown, so we can
+ avoid doing this work again the next time we encounter the symbol.
+ Any required space to store the name is obtained from the specified
+ obstack. */
+
+void
+symbol_init_demangled_name (struct general_symbol_info *gsymbol,
+ struct obstack *obstack)
+{
+ char *mangled = gsymbol->name;
+ char *demangled = NULL;
+
+ if (gsymbol->language == language_unknown)
+ gsymbol->language = language_auto;
+ if (gsymbol->language == language_cplus
+ || gsymbol->language == language_auto)
+ {
+ demangled =
+ cplus_demangle (gsymbol->name, DMGL_PARAMS | DMGL_ANSI);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_cplus;
+ gsymbol->language_specific.cplus_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), obstack);
+ xfree (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+ }
+ }
+ if (gsymbol->language == language_java)
+ {
+ demangled =
+ cplus_demangle (gsymbol->name,
+ DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_java;
+ gsymbol->language_specific.cplus_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), obstack);
+ xfree (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+ }
+ }
+ if (demangled == NULL
+ && (gsymbol->language == language_chill
+ || gsymbol->language == language_auto))
+ {
+ demangled =
+ chill_demangle (gsymbol->name);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_chill;
+ gsymbol->language_specific.chill_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), obstack);
+ xfree (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.chill_specific.demangled_name = NULL;
+ }
+ }
+}
+
+
\f
{
register struct partial_symtab *pst;
register struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+
+ /* If we know that this is not a text address, return failure. This is
+ necessary because we loop based on texthigh and textlow, which do
+ not include the data ranges. */
+ msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ if (msymbol
+ && (msymbol->type == mst_data
+ || msymbol->type == mst_bss
+ || msymbol->type == mst_abs
+ || msymbol->type == mst_file_data
+ || msymbol->type == mst_file_bss))
+ return NULL;
ALL_PSYMTABS (objfile, pst)
{
if (pc >= pst->textlow && pc < pst->texthigh)
{
- struct minimal_symbol *msymbol;
struct partial_symtab *tpst;
/* An objfile that has its functions reordered might have
section == 0) /* can't validate section this way */
return (pst);
- msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
if (msymbol == NULL)
return (pst);
{
char *modified_name = NULL;
char *modified_name2 = NULL;
+ const char *mangled_name = NULL;
int needtofreename = 0;
struct symbol *returnval;
modified_name2 = cplus_demangle (modified_name, DMGL_ANSI | DMGL_PARAMS);
if (modified_name2)
{
+ mangled_name = name;
modified_name = modified_name2;
needtofreename = 1;
}
}
- returnval = lookup_symbol_aux (modified_name, block, namespace,
- is_a_field_of_this, symtab);
+ returnval = lookup_symbol_aux (modified_name, mangled_name, block,
+ namespace, is_a_field_of_this, symtab);
if (needtofreename)
xfree (modified_name2);
}
static struct symbol *
-lookup_symbol_aux (const char *name, const struct block *block,
- const namespace_enum namespace, int *is_a_field_of_this,
- struct symtab **symtab)
+lookup_symbol_aux (const char *name, const char *mangled_name,
+ const struct block *block, const namespace_enum namespace,
+ int *is_a_field_of_this, struct symtab **symtab)
{
register struct symbol *sym;
register struct symtab *s = NULL;
while (block != 0)
{
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
if (BLOCK_START (b) <= BLOCK_START (block)
&& BLOCK_END (b) > BLOCK_START (block))
{
- sym = lookup_block_symbol (b, name, VAR_NAMESPACE);
+ sym = lookup_block_symbol (b, name, mangled_name, VAR_NAMESPACE);
if (sym)
{
block_found = b;
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ mangled_name, namespace);
/* We kept static functions in minimal symbol table as well as
in static scope. We want to find them in the symbol table. */
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ mangled_name, namespace);
}
/* sym == 0 if symbol was found in the minimal symbol table
{
/* This is a mangled variable, look it up by its
mangled name. */
- return lookup_symbol_aux (SYMBOL_NAME (msymbol), block,
+ return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, block,
namespace, is_a_field_of_this, symtab);
}
/* There are no debug symbols for this file, or we are looking
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, namespace);
+ sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ mangled_name, namespace);
/* We kept static functions in minimal symbol table as well as
in static scope. We want to find them in the symbol table. */
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
- namespace);
+ mangled_name, namespace);
}
/* If we found one, return it */
if (sym)
&& MSYMBOL_TYPE (msymbol) != mst_file_text
&& !STREQ (name, SYMBOL_NAME (msymbol)))
{
- return lookup_symbol_aux (SYMBOL_NAME (msymbol), block,
- namespace, is_a_field_of_this, symtab);
+ return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name,
+ block, namespace, is_a_field_of_this,
+ symtab);
}
}
}
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
/* This shouldn't be necessary, but as a last resort
* the psymtab gets it wrong in some cases.
*/
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
binary search terminates, we drop through and do a straight linear
search on the symbols. Each symbol which is marked as being a C++
symbol (language_cplus set) has both the encoded and non-encoded names
- tested for a match. */
+ tested for a match.
+
+ If MANGLED_NAME is non-NULL, verify that any symbol we find has this
+ particular mangled name.
+*/
struct symbol *
lookup_block_symbol (register const struct block *block, const char *name,
+ const char *mangled_name,
const namespace_enum namespace)
{
register int bot, top, inc;
return the first one; I believe it is now impossible for us
to encounter two symbols with the same name and namespace
here, because blocks containing argument symbols are no
- longer sorted. */
+ longer sorted. The exception is for C++, where multiple functions
+ (cloned constructors / destructors, in particular) can have
+ the same demangled name. So if we have a particular
+ mangled name to match, try to do so. */
top = BLOCK_NSYMS (block);
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
- if (SYMBOL_NAMESPACE (sym) == namespace &&
- SYMBOL_MATCHES_NAME (sym, name))
+ if (SYMBOL_NAMESPACE (sym) == namespace
+ && (mangled_name
+ ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
+ : SYMBOL_MATCHES_NAME (sym, name)))
{
return sym;
}
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
- if (SYMBOL_NAMESPACE (sym) == namespace &&
- SYMBOL_MATCHES_NAME (sym, name))
+ if (SYMBOL_NAMESPACE (sym) == namespace
+ && (mangled_name
+ ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
+ : SYMBOL_MATCHES_NAME (sym, name)))
{
/* If SYM has aliases, then use any alias that is active
at the current PC. If no alias is active at the current
register struct partial_symtab *ps;
register struct objfile *objfile;
CORE_ADDR distance = 0;
+ struct minimal_symbol *msymbol;
+
+ /* If we know that this is not a text address, return failure. This is
+ necessary because we loop based on the block's high and low code
+ addresses, which do not include the data ranges, and because
+ we call find_pc_sect_psymtab which has a similar restriction based
+ on the partial_symtab's texthigh and textlow. */
+ msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ if (msymbol
+ && (msymbol->type == mst_data
+ || msymbol->type == mst_bss
+ || msymbol->type == mst_abs
+ || msymbol->type == mst_file_data
+ || msymbol->type == mst_file_bss))
+ return NULL;
/* Search all symtabs for the one whose file contains our address, and which
is the smallest of all the ones containing the address. This is designed
INIT_SAL (&val); /* initialize to zeroes */
+ /* It's tempting to assume that, if we can't find debugging info for
+ any function enclosing PC, that we shouldn't search for line
+ number info, either. However, GAS can emit line number info for
+ assembly files --- very helpful when debugging hand-written
+ assembly code. In such a case, we'd have no debug info for the
+ function, but we would have line info. */
+
if (notcurrent)
pc -= 1;
val.end = alt->pc;
}
}
+ else if (best->line == 0)
+ {
+ /* If our best fit is in a range of PC's for which no line
+ number info is available (line number is zero) then we didn't
+ find any valid line information. */
+ val.pc = pc;
+ }
else
{
val.symtab = best_symtab;
return make_cleanup (do_free_search_symbols_cleanup, symbols);
}
+/* Helper function for sort_search_symbols 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;
+
+ return strcmp (SYMBOL_SOURCE_NAME ((*sym_a)->symbol),
+ SYMBOL_SOURCE_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. */
+static struct symbol_search *
+sort_search_symbols (struct symbol_search *prevtail, int nfound)
+{
+ struct symbol_search **symbols, *symp, *old_next;
+ int i;
+
+ symbols = (struct symbol_search **) xmalloc (sizeof (struct symbol_search *)
+ * nfound);
+ symp = prevtail->next;
+ for (i = 0; i < nfound; i++)
+ {
+ symbols[i] = symp;
+ symp = symp->next;
+ }
+ /* Generally NULL. */
+ old_next = symp;
+
+ qsort (symbols, nfound, sizeof (struct symbol_search *),
+ compare_search_syms);
+
+ symp = prevtail;
+ for (i = 0; i < nfound; i++)
+ {
+ symp->next = symbols[i];
+ symp = symp->next;
+ }
+ symp->next = old_next;
+
+ xfree (symbols);
+ return symp;
+}
/* Search the symbol table for matches to the regular expression REGEXP,
returning the results in *MATCHES.
and constants (enums)
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.
*/
void
search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
/* If wrong number of spaces, fix it. */
if (fix >= 0)
{
- char *tmp = (char *) alloca (strlen (regexp) + fix);
+ char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1);
sprintf (tmp, "operator%.*s%s", fix, " ", opname);
regexp = tmp;
}
if (bv != prev_bv)
for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
{
+ struct symbol_search *prevtail = tail;
+ int nfound = 0;
b = BLOCKVECTOR_BLOCK (bv, i);
- /* Skip the sort if this block is always sorted. */
- if (!BLOCK_SHOULD_SORT (b))
- sort_block_syms (b);
for (j = 0; j < BLOCK_NSYMS (b); j++)
{
QUIT;
psr->msymbol = NULL;
psr->next = NULL;
if (tail == NULL)
- {
- sr = psr;
- old_chain = make_cleanup_free_search_symbols (sr);
- }
+ sr = 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;
+
+ old_chain = make_cleanup_free_search_symbols (sr);
}
+ else
+ tail = sort_search_symbols (prevtail, nfound);
}
}
prev_bv = bv;
char *tmp;
if (TARGET_ADDR_BIT <= 32)
- tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
- & (CORE_ADDR) 0xffffffff,
- "08l");
+ tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
+ & (CORE_ADDR) 0xffffffff,
+ "08l");
else
- tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
- "016l");
+ tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
+ "016l");
printf_filtered ("%s %s\n",
tmp, SYMBOL_SOURCE_NAME (msymbol));
}
#endif /* 0 */
/* Breakpoint all functions matching regular expression. */
-#ifdef UI_OUT
+
void
rbreak_command_wrapper (char *regexp, int from_tty)
{
rbreak_command (regexp, from_tty);
}
-#endif
+
static void
rbreak_command (char *regexp, int from_tty)
{
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
- for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
- for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{