/* Symbol table lookup for the GNU debugger, GDB.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
- Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
This file is part of GDB.
s = lookup_symtab_1 (name);
if (s) return s;
+#if 0
+ /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab
+ "tree.c". */
+
/* If name not found as specified, see if adding ".c" helps. */
/* Why is this? Is it just a user convenience? (If so, it's pretty
questionable in the presence of C++, FORTRAN, etc.). It's not in
strcat (copy, ".c");
s = lookup_symtab_1 (copy);
if (s) return s;
+#endif /* 0 */
/* We didn't find anything; die. */
return 0;
char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
char *newname = type_name_no_tag (type);
+
+ /* Does the form of physname indicate that it is the full mangled name
+ of a constructor (not just the args)? */
+ int is_full_physname_constructor;
+
int is_constructor;
int is_destructor = DESTRUCTOR_PREFIX_P (physname);
/* Need a new type prefix. */
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));
- is_constructor = newname && STREQ(field_name, newname);
- if (!is_constructor)
- is_constructor = (physname[0]=='_' && physname[1]=='_' &&
- (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'));
- if (!is_constructor)
- is_constructor = (strncmp(physname, "__ct", 4) == 0);
+ is_full_physname_constructor =
+ ((physname[0]=='_' && physname[1]=='_' &&
+ (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'))
+ || (strncmp(physname, "__ct", 4) == 0));
+
+ is_constructor =
+ is_full_physname_constructor || (newname && STREQ(field_name, newname));
+
if (!is_destructor)
is_destructor = (strncmp(physname, "__dt", 4) == 0);
#ifndef GCC_MANGLE_BUG
- if (is_destructor)
+ if (is_destructor || is_full_physname_constructor)
{
mangled_name = (char*) xmalloc(strlen(physname)+1);
strcpy(mangled_name, physname);
best_pc = psymtab->textlow - 1;
+ /* Search the global symbols as well as the static symbols, so that
+ find_pc_partial_function doesn't use a minimal symbol and thus
+ cache a bad endaddr. */
+ for (p = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
+ (p - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+ < psymtab->n_global_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;
+ }
for (p = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
(p - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
< psymtab->n_static_syms);
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.) */
+/* This function has a bunch of loops in it and it would seem to be
+ attractive to put in some QUIT's (though I'm not really sure
+ whether it can run long enough to be really important). But there
+ are a few calls for which it would appear to be bad news to quit
+ out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and
+ nindy_frame_chain_valid in nindy-tdep.c. (Note that there is C++
+ code below which can error(), but that probably doesn't affect
+ these calls since they are looking for a known variable and thus
+ can probably assume it will never hit the C++ code). */
+
struct symbol *
lookup_symbol (name, block, namespace, is_a_field_of_this, symtab)
const char *name;
}
return (s);
}
+\f
+/* Find the closest symbol value (of any sort -- function or variable)
+ for a given address value. Slow but complete. */
+
+struct symbol *
+find_addr_symbol (addr, symtabp, symaddrp)
+ CORE_ADDR addr;
+ struct symtab **symtabp;
+ CORE_ADDR *symaddrp;
+{
+ struct symtab *symtab, *best_symtab;
+ struct objfile *objfile;
+ register int bot, top;
+ register struct symbol *sym;
+ register CORE_ADDR sym_addr;
+ struct block *block;
+ int blocknum;
+
+ /* Info on best symbol seen so far */
+
+ register CORE_ADDR best_sym_addr = 0;
+ struct symbol *best_sym = 0;
+
+ /* FIXME -- we should pull in all the psymtabs, too! */
+ ALL_SYMTABS (objfile, symtab)
+ {
+ /* Search the global and static blocks in this symtab for
+ the closest symbol-address to the desired address. */
+
+ for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++)
+ {
+ QUIT;
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum);
+ top = BLOCK_NSYMS (block);
+ for (bot = 0; bot < top; bot++)
+ {
+ sym = BLOCK_SYM (block, bot);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_STATIC:
+ case LOC_LABEL:
+ sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+ break;
+
+ case LOC_BLOCK:
+ sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ break;
+
+ default:
+ continue;
+ }
+
+ if (sym_addr <= addr)
+ if (sym_addr > best_sym_addr)
+ {
+ /* Quit if we found an exact match. */
+ best_sym = sym;
+ best_sym_addr = sym_addr;
+ best_symtab = symtab;
+ if (sym_addr == addr)
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ if (symtabp)
+ *symtabp = best_symtab;
+ if (symaddrp)
+ *symaddrp = best_sym_addr;
+ return best_sym;
+}
+
/* Find the source file and line number for a given PC value.
Return a structure containing a symtab pointer, a line number,
Returns 0 if could not find the specified line. */
int
-find_line_pc_range (symtab, thisline, startptr, endptr)
- struct symtab *symtab;
- int thisline;
+find_line_pc_range (sal, startptr, endptr)
+ struct symtab_and_line sal;
CORE_ADDR *startptr, *endptr;
{
- struct linetable *l;
- int ind;
- int exact_match; /* did we get an exact linenumber match */
+ CORE_ADDR startaddr;
+ struct symtab_and_line found_sal;
- if (symtab == 0)
+ startaddr = sal.pc;
+ if (startaddr == 0)
+ {
+ startaddr = find_line_pc (sal.symtab, sal.line);
+ }
+ if (startaddr == 0)
return 0;
- if (find_line_symtab (symtab, thisline, &l, &ind, &exact_match))
+ /* This whole function is based on address. For example, if line 10 has
+ two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then
+ "info line *0x123" should say the line goes from 0x100 to 0x200
+ and "info line *0x355" should say the line goes from 0x300 to 0x400.
+ This also insures that we never give a range like "starts at 0x134
+ and ends at 0x12c". */
+
+ found_sal = find_pc_line (startaddr, 0);
+ if (found_sal.line != sal.line)
{
- *startptr = l->item[ind].pc;
- /* If we have not seen an entry for the specified line,
- assume that means the specified line has zero bytes. */
- if (!exact_match || ind == l->nitems-1)
- *endptr = *startptr;
- else
- /* Perhaps the following entry is for the following line.
- It's worth a try. */
- if (ind+1 < l->nitems
- && l->item[ind+1].line == thisline + 1)
- *endptr = l->item[ind+1].pc;
- else
- *endptr = find_line_pc (symtab, thisline+1);
- return 1;
+ /* The specified line (sal) has zero bytes. */
+ *startptr = found_sal.pc;
+ *endptr = found_sal.pc;
}
-
- return 0;
+ else
+ {
+ *startptr = found_sal.pc;
+ *endptr = found_sal.end;
+ }
+ return 1;
}
/* Given a line table and a line number, return the index into the line
{
int field_counter;
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
+ char dem_opname[64];
+
+ if (strncmp(method_name, "__", 2)==0 ||
+ strncmp(method_name, "op", 2)==0 ||
+ strncmp(method_name, "type", 4)==0 )
+ {
+ if (cplus_demangle_opname(method_name, dem_opname, DMGL_ANSI))
+ method_name = dem_opname;
+ else if (cplus_demangle_opname(method_name, dem_opname, 0))
+ method_name = dem_opname;
+ }
if (STREQ (name, method_name))
/* Find all the fields with that name. */
for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
{
fputs_filtered("(Cannot find method ", gdb_stdout);
fprintf_symbol_filtered (gdb_stdout, phys_name,
- language_cplus, DMGL_PARAMS);
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
}
}
if no file is validly specified. Callers must check that.
Also, the line number returned may be invalid. */
+/* We allow single quotes in various places. This is a hideous
+ kludge, which exists because the completer can't yet deal with the
+ lack of single quotes. FIXME: write a linespec_completer which we
+ can use as appropriate instead of make_symbol_completion_list. */
+
struct symtabs_and_lines
decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
char **argptr;
struct symtab_and_line val;
#endif
register char *p, *p1;
- char *q, *q1;
+ char *q, *q1, *pp;
register struct symtab *s;
register struct symbol *sym;
char *copy;
struct symbol *sym_class;
int i1;
- int is_quoted;
+ int is_quoted, has_parens;
struct symbol **sym_arr;
struct type *t;
char *saved_arg = *argptr;
/* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
s = NULL;
- is_quoted = (strchr (gdb_completer_quote_characters, **argptr) != NULL);
+ is_quoted = (strchr(gdb_completer_quote_characters, **argptr) != NULL);
+ has_parens = (( pp = strchr(*argptr, '(')) != NULL &&
+ (pp = strchr(pp, ')')) != NULL);
for (p = *argptr; *p; p++)
{
+ if (p[0] == '<')
+ {
+ while(!++p && *p != '>');
+ if (!p)
+ {
+ /* FIXME: Why warning() and then return_to_top_level?
+ What's wrong with error()? */
+ warning("non-matching '<' and '>' in command");
+ return_to_top_level (RETURN_ERROR);
+ }
+ }
if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
break;
}
while (p[0] == ' ' || p[0] == '\t') p++;
- if ((p[0] == ':') && !is_quoted)
+ if ((p[0] == ':') && !has_parens)
{
/* C++ */
+ if (is_quoted) *argptr = *argptr+1;
if (p[1] ==':')
{
/* Extract the class name. */
|| TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
{
/* Arg token is not digits => try it as a function name
- Find the next token (everything up to end or next whitespace). */
- p = *argptr;
- while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
+ Find the next token(everything up to end or next blank). */
+ if (strchr(gdb_completer_quote_characters, **argptr) != NULL)
+ {
+ p = skip_quoted(*argptr);
+ *argptr = *argptr + 1;
+ }
+ else
+ {
+ p = *argptr;
+ while (*p && *p!=' ' && *p!='\t' && *p!=',' && *p!=':') p++;
+ }
+/*
q = operator_chars (*argptr, &q1);
-
if (q1 - q)
{
char *opname;
p = q1;
}
else
+*/
{
- copy = (char *) alloca (p - *argptr + 1 + (q1 - q));
+ copy = (char *) alloca (p - *argptr + 1 );
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
+ if (strchr(gdb_completer_quote_characters, copy[p-*argptr-1]) != NULL)
+ copy[p - *argptr -1] = '\0';
}
/* no line number may be specified */
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
/* Arg is the name of a function */
- pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
if (funfirstline)
- SKIP_PROLOGUE (pc);
+ {
+ pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (pc);
+ }
values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
values.sals[0] = find_pc_line (pc, 0);
/* Check whether arg is all digits (and sign) */
- p = *argptr;
- if (*p == '-' || *p == '+') p++;
- while (*p >= '0' && *p <= '9')
- p++;
+ q = *argptr;
+ if (*q == '-' || *q == '+') q++;
+ while (*q >= '0' && *q <= '9')
+ q++;
- if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+ if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
{
/* We found a token consisting of all digits -- at least one digit. */
enum sign {none, plus, minus} sign = none;
switch (sign)
{
case plus:
- if (p == *argptr)
+ if (q == *argptr)
val.line = 5;
if (s == 0)
val.line = default_line + val.line;
break;
case minus:
- if (p == *argptr)
+ if (q == *argptr)
val.line = 15;
if (s == 0)
val.line = default_line - val.line;
break; /* No need to adjust val.line. */
}
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
+ while (*q == ' ' || *q == '\t') q++;
+ *argptr = q;
if (s == 0)
s = default_symtab;
val.symtab = s;
/* Arg token is not digits => try it as a variable name
Find the next token (everything up to end or next whitespace). */
- p = skip_quoted (*argptr);
- if (is_quoted && p[-1] != '\'')
- error ("Unmatched single quote.");
+ if (is_quoted)
+ {
+ p = skip_quoted (*argptr);
+ if (p[-1] != '\'')
+ error ("Unmatched single quote.");
+ }
+ else if (has_parens)
+ {
+ p = pp+1;
+ }
+ else
+ {
+ p = skip_quoted(*argptr);
+ }
+
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
/* Arg is the name of a function */
- pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
if (funfirstline)
- SKIP_PROLOGUE (pc);
+ {
+ pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (pc);
+ }
val = find_pc_line (pc, 0);
#ifdef PROLOGUE_FIRSTLINE_OVERLAP
/* Convex: no need to suppress code on first line, if any */
{
val.symtab = 0;
val.line = 0;
- val.pc = SYMBOL_VALUE_ADDRESS (msymbol) + FUNCTION_START_OFFSET;
+ val.pc = SYMBOL_VALUE_ADDRESS (msymbol);
if (funfirstline)
- SKIP_PROLOGUE (val.pc);
+ {
+ val.pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (val.pc);
+ }
values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
values.sals[0] = val;
values.nelts = 1;
if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
{
/* Arg is the name of a function */
- pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i]))
- + FUNCTION_START_OFFSET;
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i]));
if (funfirstline)
- SKIP_PROLOGUE (pc);
+ {
+ pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (pc);
+ }
values.sals[i] = find_pc_line (pc, 0);
values.sals[i].pc = (values.sals[i].end && values.sals[i].pc != pc) ?
values.sals[i].end : pc;