#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 "gdb_regex.h"
#include "expression.h"
#include "language.h"
#include "demangle.h"
#include "inferior.h"
#include "linespec.h"
#include "filenames.h"
#include "obstack.h"
#include <sys/types.h>
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
#include "cp-abi.h"
extern int metrowerks_stepping;
extern int metrowerks_step_func_start;
extern int metrowerks_step_func_end;
int metrowerks_ignore_breakpoint_errors_flag = 0;
int allow_objc_selectors_flag = 1;
extern char *find_template_name_end (char *);
static void completion_list_add_name (char *, char *, int, char *, char *);
static void rbreak_command (char *, int);
static void types_info (char *, int);
static void functions_info (char *, int);
static void variables_info (char *, int);
static void sources_info (char *, int);
static void output_source_filename (char *, int *);
static int find_line_common (struct linetable *, int, int *);
char *operator_chars (char *p, char **end);
static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
const char *, int,
namespace_enum);
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);
int hp_som_som_object_present = 0;
static void fixup_section (struct general_symbol_info *, struct objfile *);
static int file_matches (char *, char **, int);
static void print_symbol_info (namespace_enum,
struct symtab *, struct symbol *, int, char *);
static void print_msymbol_info (struct minimal_symbol *);
static void symtab_symbol_info (char *, namespace_enum, int);
static void overload_list_add_symbol (struct symbol *sym, char *oload_name);
void _initialize_symtab (void);
struct type *builtin_type_error;
const struct block *block_found;
static void
cplusplus_hint (char *name)
{
while (*name == '\'')
name++;
printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
printf_filtered ("(Note leading single quote.)\n");
}
struct symtab *
lookup_symtab (const char *name)
{
register struct symtab *s;
register struct partial_symtab *ps;
register struct objfile *objfile;
char *real_path = NULL;
char *full_path = NULL;
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:
ALL_SYMTABS (objfile, s)
{
if (FILENAME_CMP (name, s->filename) == 0)
{
return s;
}
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;
}
}
}
if (lbasename (name) == name)
ALL_SYMTABS (objfile, s)
{
if (FILENAME_CMP (lbasename (s->filename), name) == 0)
return s;
}
ps = lookup_partial_symtab (name);
if (!ps)
return (NULL);
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;
goto got_symtab;
}
struct partial_symtab *
lookup_partial_symtab (const char *name)
{
register struct partial_symtab *pst;
register struct objfile *objfile;
char *full_path = NULL;
char *real_path = NULL;
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)
{
if (FILENAME_CMP (name, pst->filename) == 0)
{
return (pst);
}
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;
}
}
}
if (lbasename (name) == name)
ALL_PSYMTABS (objfile, pst)
{
if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
return (pst);
}
return (NULL);
}
char *
gdb_mangle_name (struct type *type, int method_id, int signature_id)
{
int mangled_name_len;
char *mangled_name;
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id);
struct fn_field *method = &f[signature_id];
char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
char *newname = type_name_no_tag (type);
int is_full_physname_constructor;
int is_constructor;
int is_destructor = is_destructor_name (physname);
char *const_prefix = method->is_const ? "C" : "";
char *volatile_prefix = method->is_volatile ? "V" : "";
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));
if ((physname[0] == '_' && physname[1] == 'Z')
|| is_operator_name (field_name))
return xstrdup (physname);
is_full_physname_constructor = is_constructor_name (physname);
is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));
if (!is_destructor)
is_destructor = (strncmp (physname, "__dt", 4) == 0);
if (is_destructor || is_full_physname_constructor)
{
mangled_name = (char *) xmalloc (strlen (physname) + 1);
strcpy (mangled_name, physname);
return mangled_name;
}
if (len == 0)
{
sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
}
else if (physname[0] == 't' || physname[0] == 'Q')
{
sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
newname = NULL;
len = 0;
}
else
{
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);
#if 0
if (OPNAME_PREFIX_P (field_name))
{
const 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
#endif
{
mangled_name = (char *) xmalloc (mangled_name_len);
if (is_constructor)
mangled_name[0] = '\0';
else
strcpy (mangled_name, field_name);
}
strcat (mangled_name, buf);
if (newname != NULL)
strcat (mangled_name, newname);
strcat (mangled_name, physname);
return (mangled_name);
}
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;
}
}
if (demangled == NULL &&
(gsymbol->language == language_objc ||
gsymbol->language == language_objcplus ||
gsymbol->language == language_auto))
{
demangled =
objc_demangle (gsymbol->name);
if (demangled != NULL)
{
gsymbol->language = language_objc;
if (gsymbol->language == language_auto)
gsymbol->language_specific.objc_specific.demangled_name =
obsavestring (demangled, strlen (demangled), (obstack));
xfree (demangled);
}
else
{
gsymbol->language_specific.objc_specific.demangled_name = NULL;
}
}
if (demangled &&
gsymbol->language != language_objc &&
gsymbol->language != language_objcplus &&
(demangled = gsymbol->name) &&
demangled[0] == '_' &&
(demangled[1] == 'i' || demangled[1] == 'c') &&
demangled[2] == '_')
{
demangled =
objc_demangle (gsymbol->name);
if (demangled != NULL)
{
gsymbol->language = language_objc;
gsymbol->language_specific.objc_specific.demangled_name =
obsavestring (demangled, strlen (demangled), (obstack));
xfree (demangled);
}
}
if (gsymbol->language == language_auto)
{
gsymbol->language = language_unknown;
}
}
struct partial_symtab *
find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
{
register struct partial_symtab *pst;
register struct objfile *objfile;
struct minimal_symbol *msymbol;
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 partial_symtab *tpst;
if (!(objfile->flags & OBJF_REORDERED) &&
section == 0)
return (pst);
if (msymbol == NULL)
return (pst);
for (tpst = pst; tpst != NULL; tpst = tpst->next)
{
if (pc >= tpst->textlow && pc < tpst->texthigh)
{
struct partial_symbol *p;
p = find_pc_sect_psymbol (tpst, pc, section);
if (p != NULL
&& SYMBOL_VALUE_ADDRESS (p)
== SYMBOL_VALUE_ADDRESS (msymbol))
return (tpst);
}
}
return (pst);
}
}
return (NULL);
}
struct partial_symtab *
find_pc_psymtab (CORE_ADDR pc)
{
return find_pc_sect_psymtab (pc, find_pc_mapped_section (pc));
}
struct partial_symbol *
find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
asection *section)
{
struct partial_symbol *best = NULL, *p, **pp;
CORE_ADDR best_pc;
if (!psymtab)
psymtab = find_pc_sect_psymtab (pc, section);
if (!psymtab)
return 0;
best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
for (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
(pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
< psymtab->n_global_syms);
pp++)
{
p = *pp;
if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
&& SYMBOL_CLASS (p) == LOC_BLOCK
&& pc >= SYMBOL_VALUE_ADDRESS (p)
&& (SYMBOL_VALUE_ADDRESS (p) > best_pc
|| (psymtab->textlow == 0
&& best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
{
if (section)
{
fixup_psymbol_section (p, psymtab->objfile);
if (SYMBOL_BFD_SECTION (p) != section)
continue;
}
best_pc = SYMBOL_VALUE_ADDRESS (p);
best = p;
}
}
for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
(pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
< psymtab->n_static_syms);
pp++)
{
p = *pp;
if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
&& SYMBOL_CLASS (p) == LOC_BLOCK
&& pc >= SYMBOL_VALUE_ADDRESS (p)
&& (SYMBOL_VALUE_ADDRESS (p) > best_pc
|| (psymtab->textlow == 0
&& best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
{
if (section)
{
fixup_psymbol_section (p, psymtab->objfile);
if (SYMBOL_BFD_SECTION (p) != section)
continue;
}
best_pc = SYMBOL_VALUE_ADDRESS (p);
best = p;
}
}
return best;
}
struct partial_symbol *
find_pc_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc)
{
return find_pc_sect_psymbol (psymtab, pc, find_pc_mapped_section (pc));
}
static void
fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile)
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (ginfo->name, NULL, objfile);
if (msym)
{
ginfo->bfd_section = SYMBOL_BFD_SECTION (msym);
ginfo->section = SYMBOL_SECTION (msym);
}
}
struct symbol *
fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
{
if (!sym)
return NULL;
if (SYMBOL_BFD_SECTION (sym))
return sym;
fixup_section (&sym->ginfo, objfile);
return sym;
}
struct partial_symbol *
fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
{
if (!psym)
return NULL;
if (SYMBOL_BFD_SECTION (psym))
return psym;
fixup_section (&psym->ginfo, objfile);
return psym;
}
struct symbol *
lookup_symbol (const char *name, const struct block *block,
const namespace_enum namespace, int *is_a_field_of_this,
struct symtab **symtab)
{
char *modified_name = NULL;
char *modified_name2 = NULL;
const char *mangled_name = NULL;
int needtofreename = 0;
struct symbol *returnval;
if (case_sensitivity == case_sensitive_off)
{
char *copy;
int len, i;
len = strlen (name);
copy = (char *) alloca (len + 1);
for (i= 0; i < len; i++)
copy[i] = tolower (name[i]);
copy[len] = 0;
modified_name = copy;
}
else
modified_name = (char *) name;
if (current_language->la_language == language_cplus)
{
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, mangled_name, block,
namespace, is_a_field_of_this, symtab);
if (needtofreename)
xfree (modified_name2);
return returnval;
}
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)
{
register struct symbol *sym;
register struct symtab *s = NULL;
register struct partial_symtab *ps;
register struct blockvector *bv;
register struct objfile *objfile = NULL;
register struct block *b;
register struct minimal_symbol *msymbol;
while (block != 0)
{
sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
if (symtab != NULL)
{
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 fixup_symbol_section (sym, objfile);
}
block = BLOCK_SUPERBLOCK (block);
}
if (namespace == VAR_NAMESPACE && block != NULL)
{
struct block *b;
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
if (BLOCK_START (b) <= BLOCK_START (block)
&& BLOCK_END (b) > BLOCK_START (block))
{
sym = lookup_block_symbol (b, name, mangled_name, VAR_NAMESPACE);
if (sym)
{
block_found = b;
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
}
}
if (is_a_field_of_this)
{
struct value *v = value_of_this (0);
*is_a_field_of_this = 0;
if (v && check_field (v, name))
{
*is_a_field_of_this = 1;
if (symtab != NULL)
*symtab = NULL;
return NULL;
}
}
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
#ifndef HPUXHPPA
if (namespace == VAR_NAMESPACE)
{
msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol != NULL)
{
if ((MSYMBOL_TYPE (msymbol) == mst_text)
|| (MSYMBOL_TYPE (msymbol) == mst_file_text))
{
s = find_pc_sect_symtab (SYMBOL_VALUE_ADDRESS (msymbol),
SYMBOL_BFD_SECTION (msymbol));
if (s != NULL)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
mangled_name, namespace);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
mangled_name, namespace);
}
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
else if (!STREQ (name, SYMBOL_NAME (msymbol)))
{
return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, block,
namespace, is_a_field_of_this, symtab);
}
}
}
#endif
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
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\
(if a template, try specifying an instantiation: %s<type>).",
name, ps->filename, name, name);
}
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (sym)
{
block_found = block;
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, mangled_name, namespace);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
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\
(if a template, try specifying an instantiation: %s<type>).",
name, ps->filename, name, name);
}
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
#ifdef HPUXHPPA
if (namespace == VAR_NAMESPACE)
{
msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol != NULL)
{
s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
if (s != NULL)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
mangled_name, namespace);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
mangled_name, namespace);
}
if (sym)
{
if (symtab != NULL)
*symtab = s;
return sym;
}
}
else if (MSYMBOL_TYPE (msymbol) != mst_text
&& MSYMBOL_TYPE (msymbol) != mst_file_text
&& !STREQ (name, SYMBOL_NAME (msymbol)))
{
return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name,
block, namespace, is_a_field_of_this,
symtab);
}
}
}
#endif
if (symtab != NULL)
*symtab = NULL;
return 0;
}
static struct partial_symbol *
lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
namespace_enum namespace)
{
struct partial_symbol *temp;
struct partial_symbol **start, **psym;
struct partial_symbol **top, **bottom, **center;
int length = (global ? pst->n_global_syms : pst->n_static_syms);
int do_linear_search = 1;
if (length == 0)
{
return (NULL);
}
start = (global ?
pst->objfile->global_psymbols.list + pst->globals_offset :
pst->objfile->static_psymbols.list + pst->statics_offset);
if (global)
{
do_linear_search = 0;
bottom = start;
top = start + length - 1;
while (top > bottom)
{
center = bottom + (top - bottom) / 2;
if (!(center < top))
internal_error (__FILE__, __LINE__, "failed internal consistency check");
if (!do_linear_search
&& (SYMBOL_LANGUAGE (*center) == language_java))
{
do_linear_search = 1;
}
if (strcmp (SYMBOL_SOURCE_NAME (*center), name) >= 0)
{
top = center;
}
else
{
bottom = center + 1;
}
}
if (!(top == bottom))
internal_error (__FILE__, __LINE__, "failed internal consistency check");
while ((top < (start + length)) && (SYMBOL_MATCHES_NAME (*top, name)))
{
if (SYMBOL_NAMESPACE (*top) == namespace)
{
return (*top);
}
top++;
}
}
if (do_linear_search)
{
for (psym = start; psym < start + length; psym++)
{
if (namespace == SYMBOL_NAMESPACE (*psym))
{
if (SYMBOL_MATCHES_NAME (*psym, name))
{
return (*psym);
}
}
}
}
return (NULL);
}
struct type *
lookup_transparent_type (const char *name)
{
register struct symbol *sym;
register struct symtab *s = NULL;
register struct partial_symtab *ps;
struct blockvector *bv;
register struct objfile *objfile;
register struct block *block;
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_NAMESPACE))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
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\
(if a template, try specifying an instantiation: %s<type>).",
name, ps->filename, name, name);
}
if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
return SYMBOL_TYPE (sym);
}
}
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
{
return SYMBOL_TYPE (sym);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_NAMESPACE))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
if (!sym)
{
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
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\
(if a template, try specifying an instantiation: %s<type>).",
name, ps->filename, name, name);
}
if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
return SYMBOL_TYPE (sym);
}
}
return (struct type *) 0;
}
struct partial_symtab *
find_main_psymtab (void)
{
register struct partial_symtab *pst;
register struct objfile *objfile;
ALL_PSYMTABS (objfile, pst)
{
if (lookup_partial_symbol (pst, main_name (), 1, VAR_NAMESPACE))
{
return (pst);
}
}
return (NULL);
}
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;
register struct symbol *sym;
register struct symbol *sym_found = NULL;
register int do_linear_search = 1;
if (BLOCK_SHOULD_SORT (block))
{
do_linear_search = 0;
top = BLOCK_NSYMS (block);
bot = 0;
while (1)
{
inc = (top - bot + 1);
if (inc < 4)
{
break;
}
inc = (inc >> 1) + bot;
sym = BLOCK_SYM (block, inc);
if (!do_linear_search && (SYMBOL_LANGUAGE (sym) == language_java))
{
do_linear_search = 1;
}
if (SYMBOL_SOURCE_NAME (sym)[0] < name[0])
{
bot = inc;
}
else if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
{
top = inc;
}
else if (strcmp (SYMBOL_SOURCE_NAME (sym), name) < 0)
{
bot = inc;
}
else
{
top = inc;
}
}
top = BLOCK_NSYMS (block);
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
if (SYMBOL_NAMESPACE (sym) == namespace
&& (mangled_name
? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
: SYMBOL_MATCHES_NAME (sym, name)))
{
return sym;
}
if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
{
break;
}
bot++;
}
}
if (do_linear_search)
{
top = BLOCK_NSYMS (block);
bot = 0;
while (bot < top)
{
sym = BLOCK_SYM (block, bot);
if (SYMBOL_NAMESPACE (sym) == namespace
&& (mangled_name
? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
: SYMBOL_MATCHES_NAME (sym, name)))
{
if (SYMBOL_ALIASES (sym))
sym = find_active_alias (sym, read_pc ());
sym_found = sym;
if (SYMBOL_CLASS (sym) != LOC_ARG &&
SYMBOL_CLASS (sym) != LOC_LOCAL_ARG &&
SYMBOL_CLASS (sym) != LOC_REF_ARG &&
SYMBOL_CLASS (sym) != LOC_REGPARM &&
SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR &&
SYMBOL_CLASS (sym) != LOC_BASEREG_ARG)
{
break;
}
}
bot++;
}
}
return (sym_found);
}
static struct symbol *
find_active_alias (struct symbol *sym, CORE_ADDR addr)
{
struct range_list *r;
struct alias_list *aliases;
aliases = SYMBOL_ALIASES (sym);
while (aliases)
{
if (!SYMBOL_RANGES (aliases->sym))
return aliases->sym;
for (r = SYMBOL_RANGES (aliases->sym); r; r = r->next)
{
if (r->start <= addr && r->end > addr)
return aliases->sym;
}
aliases = aliases->next;
}
return sym;
}
struct symbol *
block_function (struct block *bl)
{
while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
bl = BLOCK_SUPERBLOCK (bl);
return BLOCK_FUNCTION (bl);
}
struct symtab *
find_pc_sect_symtab (CORE_ADDR pc, asection *section)
{
register struct block *b;
struct blockvector *bv;
register struct symtab *s = NULL;
register struct symtab *best_s = NULL;
register struct partial_symtab *ps;
register struct objfile *objfile;
CORE_ADDR distance = 0;
struct minimal_symbol *msymbol;
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_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
if (BLOCK_START (b) <= pc
&& BLOCK_END (b) > pc
&& (distance == 0
|| BLOCK_END (b) - BLOCK_START (b) < distance))
{
if ((objfile->flags & OBJF_REORDERED) && objfile->psymtabs)
{
ps = find_pc_sect_psymtab (pc, section);
if (ps)
return PSYMTAB_TO_SYMTAB (ps);
}
if (section != 0)
{
int i;
for (i = 0; i < b->nsyms; i++)
{
fixup_symbol_section (b->sym[i], objfile);
if (section == SYMBOL_BFD_SECTION (b->sym[i]))
break;
}
if (i >= b->nsyms)
continue;
}
distance = BLOCK_END (b) - BLOCK_START (b);
best_s = s;
}
}
if (best_s != NULL)
return (best_s);
s = NULL;
ps = find_pc_sect_psymtab (pc, section);
if (ps)
{
if (ps->readin)
warning ("\
(Internal error: pc 0x%s in read in psymtab, but not in symtab.)\n",
paddr_nz (pc));
s = PSYMTAB_TO_SYMTAB (ps);
}
return (s);
}
struct symtab *
find_pc_symtab (CORE_ADDR pc)
{
return find_pc_sect_symtab (pc, find_pc_mapped_section (pc));
}
#if 0
struct symbol *
find_addr_symbol (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;
register CORE_ADDR best_sym_addr = 0;
struct symbol *best_sym = 0;
ALL_SYMTABS (objfile, symtab)
{
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_INDIRECT:
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)
{
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;
}
#endif
struct symtab_and_line
find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
{
struct symtab *s;
register struct linetable *l;
register int len;
register int i;
register struct linetable_entry *item;
struct symtab_and_line val;
struct blockvector *bv;
struct minimal_symbol *msymbol;
struct minimal_symbol *mfunsym;
struct linetable_entry *best = NULL;
CORE_ADDR best_end = 0;
struct symtab *best_symtab = 0;
struct linetable_entry *alt = NULL;
struct symtab *alt_symtab = 0;
struct linetable_entry *prev;
INIT_SAL (&val);
if (notcurrent)
pc -= 1;
msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol != NULL)
if (MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
{
mfunsym = lookup_minimal_symbol_text (SYMBOL_NAME (msymbol), NULL, NULL);
if (mfunsym == NULL)
;
else if (SYMBOL_VALUE (mfunsym) == SYMBOL_VALUE (msymbol))
;
else
return find_pc_line (SYMBOL_VALUE (mfunsym), 0);
}
s = find_pc_sect_symtab (pc, section);
if (!s)
{
if (notcurrent)
pc++;
val.pc = pc;
convert_sal (&val);
return val;
}
bv = BLOCKVECTOR (s);
for (; s && BLOCKVECTOR (s) == bv; s = s->next)
{
l = LINETABLE (s);
if (!l)
continue;
len = l->nitems;
if (len <= 0)
{
continue;
}
prev = NULL;
item = l->item;
if (item->pc > pc && (!alt || item->pc < alt->pc))
{
alt = item;
alt_symtab = s;
}
for (i = 0; i < len; i++, item++)
{
if (item->pc > pc)
break;
prev = item;
}
if (prev && (!best || prev->pc > best->pc))
{
best = prev;
best_symtab = s;
if (best_end <= best->pc)
best_end = 0;
}
if (best && i < len && item->pc > best->pc
&& (best_end == 0 || best_end > item->pc))
best_end = item->pc;
}
if (!best_symtab)
{
if (!alt_symtab)
{
val.pc = pc;
}
else
{
val.symtab = alt_symtab;
val.line = alt->line - 1;
if (val.line == 0)
++val.line;
val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
val.end = alt->pc;
}
}
else if (best->line == 0)
{
val.pc = pc;
}
else
{
val.symtab = best_symtab;
val.line = best->line;
val.pc = best->pc;
if (best_end && (!alt || best_end < alt->pc))
val.end = best_end;
else if (alt)
val.end = alt->pc;
else
val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
}
val.section = section;
convert_sal (&val);
return val;
}
struct symtab_and_line
find_pc_line (CORE_ADDR pc, int notcurrent)
{
asection *section;
section = find_pc_overlay (pc);
if (pc_in_unmapped_range (pc, section))
pc = overlay_mapped_address (pc, section);
return find_pc_sect_line (pc, section, notcurrent);
}
struct symtab *
find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
{
int exact;
int best_index;
struct linetable *best_linetable;
struct symtab *best_symtab;
best_linetable = LINETABLE (symtab);
best_symtab = symtab;
best_index = find_line_common (best_linetable, line, &exact);
if (best_index < 0 || !exact)
{
int best;
struct objfile *objfile;
struct symtab *s;
if (best_index >= 0)
best = best_linetable->item[best_index].line;
else
best = 0;
ALL_SYMTABS (objfile, s)
{
struct linetable *l;
int ind;
if (!STREQ (symtab->filename, s->filename))
continue;
l = LINETABLE (s);
ind = find_line_common (l, line, &exact);
if (ind >= 0)
{
if (exact)
{
best_index = ind;
best_linetable = l;
best_symtab = s;
goto done;
}
if (best == 0 || l->item[ind].line < best)
{
best = l->item[ind].line;
best_index = ind;
best_linetable = l;
best_symtab = s;
}
}
}
}
done:
if (best_index < 0)
return NULL;
if (index)
*index = best_index;
if (exact_match)
*exact_match = exact;
return best_symtab;
}
static int
find_line_pc_helper (struct symtab *symtab, int line, CORE_ADDR *pc)
{
struct linetable *l;
int ind;
*pc = 0;
if (symtab == 0)
return 0;
symtab = find_line_symtab (symtab, line, &ind, NULL);
if (symtab != NULL)
{
l = LINETABLE (symtab);
*pc = l->item[ind].pc;
return 1;
}
else
return 0;
}
int
find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
{
CORE_ADDR end;
struct symtab_and_line sal;
sal.symtab = symtab;
sal.line = line;
sal.pc = *pc;
return find_line_pc_range (sal, pc, &end);
}
int
find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr,
CORE_ADDR *endptr)
{
CORE_ADDR startaddr;
struct symtab_and_line found_sal;
int line;
startaddr = sal.pc;
if (sal.symtab->line_charpos == 0)
{
int fd;
fd = open_source_file (sal.symtab);
if (fd >= 0)
{
find_source_lines (sal.symtab, fd);
close (fd);
}
}
if (!sal.symtab->linetable)
return 0;
else if (sal.symtab->linetable->lines_are_chars)
line = sal.symtab->line_charpos[sal.line - 1];
else
line = sal.line;
if (startaddr == 0 && !find_line_pc_helper (sal.symtab, line, &startaddr))
return 0;
found_sal = find_pc_sect_line (startaddr, sal.section, 0);
if (found_sal.line != sal.line)
{
*startptr = found_sal.pc;
*endptr = found_sal.pc;
}
else
{
*startptr = found_sal.pc;
*endptr = found_sal.end;
}
return 1;
}
static int
find_line_common (register struct linetable *l, register int lineno,
int *exact_match)
{
register int i;
register int len;
int best_index = -1;
int best = 0;
if (lineno <= 0)
return -1;
if (l == 0)
return -1;
len = l->nitems;
for (i = 0; i < len; i++)
{
register struct linetable_entry *item = &(l->item[i]);
if (item->line == lineno)
{
*exact_match = 1;
return i;
}
if (item->line > lineno && (best == 0 || item->line < best))
{
best = item->line;
best_index = i;
}
}
*exact_match = 0;
return best_index;
}
int
find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr)
{
struct symtab_and_line sal;
sal = find_pc_line (pc, 0);
*startptr = sal.pc;
*endptr = sal.end;
return sal.symtab != 0;
}
struct symtab_and_line
find_function_start_sal (struct symbol *sym, int funfirstline)
{
CORE_ADDR pc;
struct symtab_and_line sal;
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
fixup_symbol_section (sym, NULL);
if (funfirstline)
{
asection *section = SYMBOL_BFD_SECTION (sym);
if (section_is_overlay (section) &&
!section_is_mapped (section))
pc = overlay_unmapped_address (pc, section);
pc += FUNCTION_START_OFFSET;
pc = SKIP_PROLOGUE (pc);
pc = overlay_mapped_address (pc, section);
}
sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
#ifdef PROLOGUE_FIRSTLINE_OVERLAP
sal.pc = pc;
#else
if (sal.pc != pc
&& BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end
&& sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
{
pc = sal.end;
sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
}
sal.pc = pc;
#endif
return sal;
}
char *
operator_chars (char *p, char **end)
{
*end = "";
if (strncmp (p, "operator", 8))
return *end;
p += 8;
if (isalpha (*p) || *p == '_' || *p == '$' || *p == '\0')
return *end;
while (*p == ' ' || *p == '\t')
p++;
if (isalpha (*p) || *p == '_' || *p == '$')
{
register char *q = p + 1;
while (isalnum (*q) || *q == '_' || *q == '$')
q++;
*end = q;
return p;
}
while (*p)
switch (*p)
{
case '\\':
if (p[1] == '*')
{
if (p[2] == '=')
*end = p + 3;
else
*end = p + 2;
return p;
}
else if (p[1] == '[')
{
if (p[2] == ']')
error ("mismatched quoting on brackets, try 'operator\\[\\]'");
else if (p[2] == '\\' && p[3] == ']')
{
*end = p + 4;
return p;
}
else
error ("nothing is allowed between '[' and ']'");
}
else
{
p++;
continue;
}
break;
case '!':
case '=':
case '*':
case '/':
case '%':
case '^':
if (p[1] == '=')
*end = p + 2;
else
*end = p + 1;
return p;
case '<':
case '>':
case '+':
case '-':
case '&':
case '|':
if (p[0] == '-' && p[1] == '>')
{
if (p[2] == '*')
{
*end = p + 3;
return p;
}
else if (p[2] == '\\')
{
*end = p + 4;
return p;
}
else
{
*end = p + 2;
return p;
}
}
if (p[1] == '=' || p[1] == p[0])
*end = p + 2;
else
*end = p + 1;
return p;
case '~':
case ',':
*end = p + 1;
return p;
case '(':
if (p[1] != ')')
error ("`operator ()' must be specified without whitespace in `()'");
*end = p + 2;
return p;
case '?':
if (p[1] != ':')
error ("`operator ?:' must be specified without whitespace in `?:'");
*end = p + 2;
return p;
case '[':
if (p[1] != ']')
error ("`operator []' must be specified without whitespace in `[]'");
*end = p + 2;
return p;
default:
error ("`operator %s' not supported", p);
break;
}
*end = "";
return *end;
}
static int
filename_seen (const char *file, int add, int *first)
{
static const char **tab = NULL;
static int tab_alloc_size = (256 - 24) / sizeof (char *);
static int tab_cur_size;
const char **p;
if (*first)
{
if (tab == NULL)
tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
tab_cur_size = 0;
}
for (p = tab; p < tab + tab_cur_size; p++)
if (strcmp (*p, file) == 0)
return 1;
if (add)
{
if (tab_cur_size == tab_alloc_size)
{
tab_alloc_size *= 2;
tab = (const char **) xrealloc ((char *) tab,
tab_alloc_size * sizeof (*tab));
}
tab[tab_cur_size++] = file;
}
return 0;
}
static void
output_source_filename (char *name, int *first)
{
if (filename_seen (name, 1, first))
{
return;
}
if (*first)
{
*first = 0;
}
else
{
printf_filtered (", ");
}
wrap_here ("");
fputs_filtered (name, gdb_stdout);
}
static void
sources_info (char *ignore, int from_tty)
{
register struct symtab *s;
register struct partial_symtab *ps;
register struct objfile *objfile;
int first;
if (!have_full_symbols () && !have_partial_symbols ())
{
error ("No symbol table is loaded. Use the \"file\" command.");
}
printf_filtered ("Source files for which symbols have been read in:\n\n");
first = 1;
ALL_SYMTABS (objfile, s)
{
output_source_filename (s->filename, &first);
}
printf_filtered ("\n\n");
printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
first = 1;
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin)
{
output_source_filename (ps->filename, &first);
}
}
printf_filtered ("\n");
}
static int
file_matches (char *file, char *files[], int nfiles)
{
int i;
if (file != NULL && nfiles != 0)
{
for (i = 0; i < nfiles; i++)
{
if (strcmp (files[i], lbasename (file)) == 0)
return 1;
}
}
else if (nfiles == 0)
return 1;
return 0;
}
void
free_search_symbols (struct symbol_search *symbols)
{
struct symbol_search *p;
struct symbol_search *next;
for (p = symbols; p != NULL; p = next)
{
next = p->next;
xfree (p);
}
}
static void
do_free_search_symbols_cleanup (void *symbols)
{
free_search_symbols (symbols);
}
struct cleanup *
make_cleanup_free_search_symbols (struct symbol_search *symbols)
{
return make_cleanup (do_free_search_symbols_cleanup, 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));
}
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;
}
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;
}
void
search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
struct symbol_search **matches)
{
register struct symtab *s;
register struct partial_symtab *ps;
register struct blockvector *bv;
struct blockvector *prev_bv = 0;
register struct block *b;
register int i = 0;
register int j;
register struct symbol *sym;
struct partial_symbol **psym;
struct objfile *objfile;
struct minimal_symbol *msymbol;
char *val;
int found_misc = 0;
static enum minimal_symbol_type types[]
=
{mst_data, mst_text, mst_abs, mst_unknown};
static enum minimal_symbol_type types2[]
=
{mst_bss, mst_file_text, mst_abs, mst_unknown};
static enum minimal_symbol_type types3[]
=
{mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
static enum minimal_symbol_type types4[]
=
{mst_file_bss, mst_text, mst_abs, mst_unknown};
enum minimal_symbol_type ourtype;
enum minimal_symbol_type ourtype2;
enum minimal_symbol_type ourtype3;
enum minimal_symbol_type ourtype4;
struct symbol_search *sr;
struct symbol_search *psr;
struct symbol_search *tail;
struct cleanup *old_chain = NULL;
if (kind < VARIABLES_NAMESPACE)
error ("must search on specific namespace");
ourtype = types[(int) (kind - VARIABLES_NAMESPACE)];
ourtype2 = types2[(int) (kind - VARIABLES_NAMESPACE)];
ourtype3 = types3[(int) (kind - VARIABLES_NAMESPACE)];
ourtype4 = types4[(int) (kind - VARIABLES_NAMESPACE)];
sr = *matches = NULL;
tail = NULL;
if (regexp != NULL)
{
char *opend;
char *opname = operator_chars (regexp, &opend);
if (*opname)
{
int fix = -1;
if (isalpha (*opname) || *opname == '_' || *opname == '$')
{
if (opname[-1] != ' ' || opname[-2] == ' ')
fix = 1;
}
else
{
if (opname[-1] == ' ')
fix = 0;
}
if (fix >= 0)
{
char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1);
sprintf (tmp, "operator%.*s%s", fix, " ", opname);
regexp = tmp;
}
}
if (0 != (val = re_comp (regexp)))
error ("Invalid regexp (%s): %s", val, regexp);
}
ALL_PSYMTABS (objfile, ps)
{
struct partial_symbol **bound, **gbound, **sbound;
int keep_going = 1;
if (ps->readin)
continue;
gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms;
bound = gbound;
psym = objfile->global_psymbols.list + ps->globals_offset;
while (keep_going)
{
if (psym >= bound)
{
if (bound == gbound && ps->n_static_syms != 0)
{
psym = objfile->static_psymbols.list + ps->statics_offset;
bound = sbound;
}
else
keep_going = 0;
continue;
}
else
{
QUIT;
if (file_matches (ps->filename, files, nfiles)
&& ((regexp == NULL || SYMBOL_MATCHES_REGEXP (*psym))
&& ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
&& SYMBOL_CLASS (*psym) != LOC_BLOCK)
|| (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK)
|| (kind == TYPES_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)
|| (kind == METHODS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK))))
{
PSYMTAB_TO_SYMTAB (ps);
keep_going = 0;
}
}
psym++;
}
}
if (nfiles == 0 && (kind == VARIABLES_NAMESPACE || kind == FUNCTIONS_NAMESPACE))
{
ALL_OBJFILES (objfile)
{
objfile_demangle_msymbols (objfile);
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
if (MSYMBOL_TYPE (msymbol) == ourtype ||
MSYMBOL_TYPE (msymbol) == ourtype2 ||
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
{
if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
{
if (kind == FUNCTIONS_NAMESPACE
|| lookup_symbol (SYMBOL_NAME (msymbol),
(struct block *) NULL,
VAR_NAMESPACE,
0, (struct symtab **) NULL) == NULL)
found_misc = 1;
}
}
}
}
}
}
ALL_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
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);
for (j = 0; j < BLOCK_NSYMS (b); j++)
{
QUIT;
sym = BLOCK_SYM (b, j);
if (file_matches (s->filename, files, nfiles)
&& ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym))
&& ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK
&& SYMBOL_CLASS (sym) != LOC_CONST)
|| (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK)
|| (kind == TYPES_NAMESPACE && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|| (kind == METHODS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK))))
{
psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
psr->block = i;
psr->symtab = s;
psr->symbol = sym;
psr->msymbol = NULL;
psr->next = NULL;
if (tail == NULL)
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;
}
if (found_misc || kind != FUNCTIONS_NAMESPACE)
{
ALL_OBJFILES (objfile)
{
objfile_demangle_msymbols (objfile);
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
if (MSYMBOL_TYPE (msymbol) == ourtype ||
MSYMBOL_TYPE (msymbol) == ourtype2 ||
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
{
if (kind != FUNCTIONS_NAMESPACE ||
(0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
{
if (lookup_symbol (SYMBOL_NAME (msymbol),
(struct block *) NULL, VAR_NAMESPACE,
0, (struct symtab **) NULL) == NULL)
{
psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
psr->block = i;
psr->msymbol = msymbol;
psr->symtab = NULL;
psr->symbol = NULL;
psr->next = NULL;
if (tail == NULL)
{
sr = psr;
old_chain = make_cleanup_free_search_symbols (sr);
}
else
tail->next = psr;
tail = psr;
}
}
}
}
}
}
}
*matches = sr;
if (sr != NULL)
discard_cleanups (old_chain);
}
static void
print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym,
int block, char *last)
{
if (last == NULL || strcmp (last, s->filename) != 0)
{
fputs_filtered ("\nFile ", gdb_stdout);
fputs_filtered (s->filename, gdb_stdout);
fputs_filtered (":\n", gdb_stdout);
}
if (kind != TYPES_NAMESPACE && block == STATIC_BLOCK)
printf_filtered ("static ");
if (kind == TYPES_NAMESPACE
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
else if (kind < TYPES_NAMESPACE ||
(kind == TYPES_NAMESPACE &&
SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE))
{
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_SOURCE_NAME (sym)),
gdb_stdout, 0);
printf_filtered (";\n");
}
else
{
#if 0
char *demangled_name;
c_type_print_base (TYPE_FN_FIELD_TYPE (t, block),
gdb_stdout, 0, 0);
c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (t, block),
gdb_stdout, 0);
if (TYPE_FN_FIELD_STUB (t, block))
check_stub_method (TYPE_DOMAIN_TYPE (type), j, block);
demangled_name =
cplus_demangle (TYPE_FN_FIELD_PHYSNAME (t, block),
DMGL_ANSI | DMGL_PARAMS);
if (demangled_name == NULL)
fprintf_filtered (stream, "<badly mangled name %s>",
TYPE_FN_FIELD_PHYSNAME (t, block));
else
{
fputs_filtered (demangled_name, stream);
xfree (demangled_name);
}
#endif
}
}
static void
print_msymbol_info (struct minimal_symbol *msymbol)
{
char *tmp;
if (TARGET_ADDR_BIT <= 32)
tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
& (CORE_ADDR) 0xffffffff,
"08l");
else
tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
"016l");
printf_filtered ("%s %s\n",
tmp, SYMBOL_SOURCE_NAME (msymbol));
}
static void
symtab_symbol_info (char *regexp, namespace_enum kind, int from_tty)
{
static char *classnames[]
=
{"variable", "function", "type", "method"};
struct symbol_search *symbols;
struct symbol_search *p;
struct cleanup *old_chain;
char *last_filename = NULL;
int first = 1;
search_symbols (regexp, kind, 0, (char **) NULL, &symbols);
old_chain = make_cleanup_free_search_symbols (symbols);
printf_filtered (regexp
? "All %ss matching regular expression \"%s\":\n"
: "All defined %ss:\n",
classnames[(int) (kind - VARIABLES_NAMESPACE)], regexp);
for (p = symbols; p != NULL; p = p->next)
{
QUIT;
if (p->msymbol != NULL)
{
if (first)
{
printf_filtered ("\nNon-debugging symbols:\n");
first = 0;
}
print_msymbol_info (p->msymbol);
}
else
{
print_symbol_info (kind,
p->symtab,
p->symbol,
p->block,
last_filename);
last_filename = p->symtab->filename;
}
}
do_cleanups (old_chain);
}
static void
variables_info (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, VARIABLES_NAMESPACE, from_tty);
}
static void
functions_info (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, FUNCTIONS_NAMESPACE, from_tty);
}
static void
types_info (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, TYPES_NAMESPACE, from_tty);
}
#if 0
static void
methods_info (char *regexp)
{
symtab_symbol_info (regexp, METHODS_NAMESPACE, 0, from_tty);
}
#endif
void
rbreak_command_wrapper (char *regexp, int from_tty)
{
rbreak_command (regexp, from_tty);
}
static void
rbreak_command (char *regexp, int from_tty)
{
struct symbol_search *ss;
struct symbol_search *p;
struct cleanup *old_chain;
search_symbols (regexp, FUNCTIONS_NAMESPACE, 0, (char **) NULL, &ss);
old_chain = make_cleanup_free_search_symbols (ss);
for (p = ss; p != NULL; p = p->next)
{
if (p->msymbol == NULL)
{
char *string = (char *) alloca (strlen (p->symtab->filename)
+ strlen (SYMBOL_NAME (p->symbol))
+ 4);
strcpy (string, p->symtab->filename);
strcat (string, ":'");
strcat (string, SYMBOL_NAME (p->symbol));
strcat (string, "'");
break_command (string, from_tty);
print_symbol_info (FUNCTIONS_NAMESPACE,
p->symtab,
p->symbol,
p->block,
p->symtab->filename);
}
else
{
break_command (SYMBOL_NAME (p->msymbol), from_tty);
printf_filtered ("<function, no debug info> %s;\n",
SYMBOL_SOURCE_NAME (p->msymbol));
}
}
do_cleanups (old_chain);
}
int
contained_in (struct block *a, struct block *b)
{
if (!a || !b)
return 0;
return BLOCK_START (a) >= BLOCK_START (b)
&& BLOCK_END (a) <= BLOCK_END (b);
}
static int return_val_size;
static int return_val_index;
static char **return_val;
#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
do { \
if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
\
\
\
completion_list_add_name \
(SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \
else \
completion_list_add_name \
(SYMBOL_NAME (symbol), (sym_text), (len), (text), (word)); \
} while (0)
static void
completion_list_add_name (char *symname, char *sym_text, int sym_text_len,
char *text, char *word)
{
int newsize;
int i;
if (strncmp (symname, sym_text, sym_text_len) != 0)
{
return;
}
{
char *new;
if (word == sym_text)
{
new = xmalloc (strlen (symname) + 5);
strcpy (new, symname);
}
else if (word > sym_text)
{
new = xmalloc (strlen (symname) + 5);
strcpy (new, symname + (word - sym_text));
}
else
{
new = xmalloc (strlen (symname) + (sym_text - word) + 5);
strncpy (new, word, sym_text - word);
new[sym_text - word] = '\0';
strcat (new, symname);
}
if (return_val_index + 3 > return_val_size)
{
newsize = (return_val_size *= 2) * sizeof (char *);
return_val = (char **) xrealloc ((char *) return_val, newsize);
}
return_val[return_val_index++] = new;
return_val[return_val_index] = NULL;
}
}
char **
make_symbol_completion_list (char *text, char *word)
{
register struct symbol *sym;
register struct symtab *s;
register struct partial_symtab *ps;
register struct minimal_symbol *msymbol;
register struct objfile *objfile;
register struct block *b, *surrounding_static_block = 0;
register int i, j;
struct partial_symbol **psym;
char *sym_text;
int sym_text_len;
{
char *p;
char quote_found;
char *quote_pos = NULL;
quote_found = '\0';
for (p = text; *p != '\0'; ++p)
{
if (quote_found != '\0')
{
if (*p == quote_found)
quote_found = '\0';
else if (*p == '\\' && p[1] == quote_found)
++p;
}
else if (*p == '\'' || *p == '"')
{
quote_found = *p;
quote_pos = p;
}
}
if (quote_found == '\'')
sym_text = quote_pos + 1;
else if (quote_found == '"')
{
return_val = (char **) xmalloc (sizeof (char *));
return_val[0] = NULL;
return return_val;
}
else
{
while (p > text)
{
if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
--p;
else
break;
}
sym_text = p;
}
}
return_val_size = 100;
return_val_index = 0;
return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
return_val[0] = NULL;
if (((sym_text == NULL) || (*sym_text == '\0'))
&& ((word == NULL) || (*word == '\0')))
{
return return_val;
}
sym_text_len = strlen (sym_text);
ALL_PSYMTABS (objfile, ps)
{
if (ps->readin)
continue;
for (psym = objfile->global_psymbols.list + ps->globals_offset;
psym < (objfile->global_psymbols.list + ps->globals_offset
+ ps->n_global_syms);
psym++)
{
QUIT;
COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
}
for (psym = objfile->static_psymbols.list + ps->statics_offset;
psym < (objfile->static_psymbols.list + ps->statics_offset
+ ps->n_static_syms);
psym++)
{
QUIT;
COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
}
}
ALL_OBJFILES (objfile)
{
objfile_demangle_msymbols (objfile);
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
static char *tmp = NULL;
static unsigned int tmplen = 0;
char *method, *category, *selector;
char *tmp2 = NULL;
QUIT;
method = SYMBOL_DEMANGLED_NAME (msymbol);
if (method == NULL)
method = SYMBOL_NAME (msymbol);
if (method == NULL)
continue;
completion_list_add_name (method, sym_text, sym_text_len, text, word);
if ((method[0] != '-') && (method[0] != '+'))
continue;
if (sym_text[0] == '[')
completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
while ((strlen (method) + 1) >= tmplen)
{
tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
tmp = xrealloc (tmp, tmplen);
}
selector = strchr (method, ' ');
if (selector != NULL)
selector++;
category = strchr (method, '(');
if ((category != NULL) && (selector != NULL))
{
memcpy (tmp, method, (category - method));
tmp[category - method] = ' ';
memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
if (sym_text[0] == '[')
completion_list_add_name (tmp + 1, sym_text, sym_text_len, text, word);
}
if (selector != NULL)
{
strcpy (tmp, selector);
tmp2 = strchr (tmp, ']');
if (tmp2 != NULL)
*tmp2 = '\0';
completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
}
}
}
for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{
surrounding_static_block = b;
}
ALL_BLOCK_SYMBOLS (b, i, sym)
{
QUIT;
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
struct type *t = SYMBOL_TYPE (sym);
enum type_code c = TYPE_CODE (t);
if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
{
for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
{
if (TYPE_FIELD_NAME (t, j))
{
completion_list_add_name (TYPE_FIELD_NAME (t, j),
sym_text, sym_text_len, text, word);
}
}
}
}
}
}
ALL_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, i, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
ALL_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
if (b == surrounding_static_block)
continue;
ALL_BLOCK_SYMBOLS (b, i, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
return (return_val);
}
char **
make_file_symbol_completion_list (char *text, char *word, char *srcfile)
{
register struct symbol *sym;
register struct symtab *s;
register struct block *b;
register int i;
char *sym_text;
int sym_text_len;
{
char *p;
char quote_found;
char *quote_pos = NULL;
quote_found = '\0';
for (p = text; *p != '\0'; ++p)
{
if (quote_found != '\0')
{
if (*p == quote_found)
quote_found = '\0';
else if (*p == '\\' && p[1] == quote_found)
++p;
}
else if (*p == '\'' || *p == '"')
{
quote_found = *p;
quote_pos = p;
}
}
if (quote_found == '\'')
sym_text = quote_pos + 1;
else if (quote_found == '"')
{
return_val = (char **) xmalloc (sizeof (char *));
return_val[0] = NULL;
return return_val;
}
else
{
for (; p > text; --p)
{
if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
continue;
else
{
if ((current_language->la_language == language_objc) ||
(current_language->la_language == language_objcplus))
if (p[-1] == ':')
continue;
else if (p[-1] == '[' && (p[-2] == '-' || p[-2] == '+'))
p -= 2;
else if (p[-1] == ' ' || p[-1] == '(' || p[-1] == ')')
{
char *t = p;
while (t > text)
if (isalnum (t[-1]) || t[-1] == '_' ||
t[-1] == ' ' || t[-1] == ':' ||
t[-1] == '(' || t[-1] == ')')
--t;
else
break;
if (t[-1] == '[' && (t[-2] == '-' || t[-2] == '+'))
p = t - 2;
}
break;
}
}
sym_text = p;
}
}
return_val_size = 10;
return_val_index = 0;
return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
return_val[0] = NULL;
if (((sym_text == NULL) || (*sym_text == '\0'))
&& ((word == NULL) || (*word == '\0')))
{
return return_val;
}
sym_text_len = strlen (sym_text);
s = lookup_symtab (srcfile);
if (s == NULL)
{
const char *tail = lbasename (srcfile);
if (tail > srcfile)
s = lookup_symtab (tail);
}
if (s == NULL)
return (return_val);
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, i, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, i, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
return (return_val);
}
static void
add_filename_to_list (const char *fname, char *text, char *word,
char ***list, int *list_used, int *list_alloced)
{
char *new;
size_t fnlen = strlen (fname);
if (*list_used + 1 >= *list_alloced)
{
*list_alloced *= 2;
*list = (char **) xrealloc ((char *) *list,
*list_alloced * sizeof (char *));
}
if (word == text)
{
new = xmalloc (fnlen + 5);
strcpy (new, fname);
}
else if (word > text)
{
new = xmalloc (fnlen + 5);
strcpy (new, fname + (word - text));
}
else
{
new = xmalloc (fnlen + (text - word) + 5);
strncpy (new, word, text - word);
new[text - word] = '\0';
strcat (new, fname);
}
(*list)[*list_used] = new;
(*list)[++*list_used] = NULL;
}
static int
not_interesting_fname (const char *fname)
{
static const char *illegal_aliens[] = {
"_globals_",
NULL
};
int i;
for (i = 0; illegal_aliens[i]; i++)
{
if (strcmp (fname, illegal_aliens[i]) == 0)
return 1;
}
return 0;
}
char **
make_source_files_completion_list (char *text, char *word)
{
register struct symtab *s;
register struct partial_symtab *ps;
register struct objfile *objfile;
int first = 1;
int list_alloced = 1;
int list_used = 0;
size_t text_len = strlen (text);
char **list = (char **) xmalloc (list_alloced * sizeof (char *));
const char *base_name;
list[0] = NULL;
if (!have_full_symbols () && !have_partial_symbols ())
return list;
ALL_SYMTABS (objfile, s)
{
if (not_interesting_fname (s->filename))
continue;
if (!filename_seen (s->filename, 1, &first)
#if HAVE_DOS_BASED_FILE_SYSTEM
&& strncasecmp (s->filename, text, text_len) == 0
#else
&& strncmp (s->filename, text, text_len) == 0
#endif
)
{
add_filename_to_list (s->filename, text, word,
&list, &list_used, &list_alloced);
}
else
{
base_name = lbasename (s->filename);
if (base_name != s->filename
&& !filename_seen (base_name, 1, &first)
#if HAVE_DOS_BASED_FILE_SYSTEM
&& strncasecmp (base_name, text, text_len) == 0
#else
&& strncmp (base_name, text, text_len) == 0
#endif
)
add_filename_to_list (base_name, text, word,
&list, &list_used, &list_alloced);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (not_interesting_fname (ps->filename))
continue;
if (!ps->readin)
{
if (!filename_seen (ps->filename, 1, &first)
#if HAVE_DOS_BASED_FILE_SYSTEM
&& strncasecmp (ps->filename, text, text_len) == 0
#else
&& strncmp (ps->filename, text, text_len) == 0
#endif
)
{
add_filename_to_list (ps->filename, text, word,
&list, &list_used, &list_alloced);
}
else
{
base_name = lbasename (ps->filename);
if (base_name != ps->filename
&& !filename_seen (base_name, 1, &first)
#if HAVE_DOS_BASED_FILE_SYSTEM
&& strncasecmp (base_name, text, text_len) == 0
#else
&& strncmp (base_name, text, text_len) == 0
#endif
)
add_filename_to_list (base_name, text, word,
&list, &list_used, &list_alloced);
}
}
}
return list;
}
int
in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
CORE_ADDR prologue_end;
CORE_ADDR scan_from;
if (!func_start)
{
return 1;
}
else
scan_from = func_start;
prologue_end = SKIP_PROLOGUE (scan_from);
return scan_from <= pc && pc < prologue_end;
}
sal = find_pc_line (func_addr, 0);
if (sal.line == 0
|| sal.end <= func_addr
|| func_end <= sal.end)
{
CORE_ADDR prologue_end = SKIP_PROLOGUE (func_addr);
if (func_addr <= pc && pc < prologue_end)
return 1;
prologue_end = SKIP_PROLOGUE (pc);
if (prologue_end > pc + 4)
return 1;
else
return 0;
}
return func_addr <= pc && pc < sal.end;
}
static int sym_return_val_size;
static int sym_return_val_index;
static struct symbol **sym_return_val;
static void
overload_list_add_symbol (struct symbol *sym, char *oload_name)
{
int newsize;
int i;
char *sym_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ARM | DMGL_ANSI);
if (!sym_name)
{
sym_name = (char *) xmalloc (strlen (SYMBOL_NAME (sym)) + 1);
strcpy (sym_name, SYMBOL_NAME (sym));
}
if (strcmp (sym_name, oload_name) != 0)
{
xfree (sym_name);
return;
}
if (SYMBOL_TYPE (sym) == NULL)
return;
for (i = 0; i < sym_return_val_index; ++i)
if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i])))
return;
if (sym_return_val_index + 3 > sym_return_val_size)
{
newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *);
sym_return_val = (struct symbol **) xrealloc ((char *) sym_return_val, newsize);
}
sym_return_val[sym_return_val_index++] = sym;
sym_return_val[sym_return_val_index] = NULL;
xfree (sym_name);
}
struct symbol **
make_symbol_overload_list (struct symbol *fsym)
{
register struct symbol *sym;
register struct symtab *s;
register struct partial_symtab *ps;
register struct objfile *objfile;
register struct block *b, *surrounding_static_block = 0;
register int i;
char *oload_name = NULL;
int oload_name_len = 0;
oload_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_ARM | DMGL_ANSI);
if (!oload_name)
{
oload_name = (char *) xmalloc (strlen (SYMBOL_NAME (fsym)) + 1);
strcpy (oload_name, SYMBOL_NAME (fsym));
}
oload_name_len = strlen (oload_name);
sym_return_val_size = 100;
sym_return_val_index = 0;
sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *));
sym_return_val[0] = NULL;
if (oload_name[0] = '\0')
return sym_return_val;
ALL_PSYMTABS (objfile, ps)
{
struct partial_symbol **psym;
if (ps->readin)
continue;
for (psym = objfile->global_psymbols.list + ps->globals_offset;
psym < (objfile->global_psymbols.list + ps->globals_offset
+ ps->n_global_syms);
psym++)
{
QUIT;
s = PSYMTAB_TO_SYMTAB (ps);
}
for (psym = objfile->static_psymbols.list + ps->statics_offset;
psym < (objfile->static_psymbols.list + ps->statics_offset
+ ps->n_static_syms);
psym++)
{
QUIT;
s = PSYMTAB_TO_SYMTAB (ps);
}
}
for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
{
if (!BLOCK_SUPERBLOCK (b))
{
surrounding_static_block = b;
}
ALL_BLOCK_SYMBOLS (b, i, sym)
{
overload_list_add_symbol (sym, oload_name);
}
}
ALL_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, i, sym)
{
overload_list_add_symbol (sym, oload_name);
}
}
ALL_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
if (b == surrounding_static_block)
continue;
ALL_BLOCK_SYMBOLS (b, i, sym)
{
overload_list_add_symbol (sym, oload_name);
}
}
xfree (oload_name);
return (sym_return_val);
}
struct symtabs_and_lines
decode_line_spec (char *string, int funfirstline)
{
struct symtabs_and_lines sals;
if (string == 0)
error ("Empty line specification.");
sals = decode_line_1 (&string, funfirstline,
current_source_symtab, current_source_line,
(char ***) NULL);
if (*string)
error ("Junk at end of line specification: %s", string);
return sals;
}
static char *name_of_main;
void
set_main_name (const char *name)
{
if (name_of_main != NULL)
{
xfree (name_of_main);
name_of_main = NULL;
}
if (name != NULL)
{
name_of_main = xstrdup (name);
}
}
char *
main_name (void)
{
if (name_of_main != NULL)
return name_of_main;
else
return "main";
}
void
_initialize_symtab (void)
{
struct cmd_list_element *cmd;
add_info ("variables", variables_info,
"All global and static variable names, or those matching REGEXP.");
if (dbx_commands)
add_com ("whereis", class_info, variables_info,
"All global and static variable names, or those matching REGEXP.");
add_info ("functions", functions_info,
"All function names, or those matching REGEXP.");
add_info ("types", types_info,
"All type names, or those matching REGEXP.");
#if 0
add_info ("methods", methods_info,
"All method names, or those matching REGEXP::REGEXP.\n\
If the class qualifier is omitted, it is assumed to be the current scope.\n\
If the first REGEXP is omitted, then all methods matching the second REGEXP\n\
are listed.");
#endif
add_info ("sources", sources_info,
"Source files in the program.");
add_com ("rbreak", class_breakpoint, rbreak_command,
"Set a breakpoint for all functions matching REGEXP.");
if (xdb_commands)
{
add_com ("lf", class_info, sources_info, "Source files in the program");
add_com ("lg", class_info, variables_info,
"All global and static variable names, or those matching REGEXP.");
}
builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0,
"<unknown type>", (struct objfile *) NULL);
cmd = add_set_cmd ("metrowerks-ignore-breakpoint-errors", class_obscure, var_boolean,
(char *) &metrowerks_ignore_breakpoint_errors_flag,
"Set if GDB should avoid printing an error message when unable to set a breakpoint.",
&setlist);
add_show_from_set (cmd, &showlist);
}