#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 "source.h"
#include "filenames.h"
#include "objc-lang.h"
#include "ada-lang.h"
#include "hashtab.h"
#include "gdb_obstack.h"
#include "block.h"
#include "dictionary.h"
#include <sys/types.h>
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
#include "cp-abi.h"
#include "observer.h"
int metrowerks_ignore_breakpoint_errors_flag = 0;
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 (const char *, int *);
static int find_line_common (struct linetable *, int, int *);
char *operator_chars (char *p, char **end);
static struct symbol *lookup_symbol_aux (const char *name,
const char *linkage_name,
const struct block *block,
const domain_enum domain,
int *is_a_field_of_this,
struct symtab **symtab);
static
struct symbol *lookup_symbol_aux_local (const char *name,
const char *linkage_name,
const struct block *block,
const domain_enum domain,
struct symtab **symtab);
static
struct symbol *lookup_symbol_aux_symtabs (int block_index,
const char *name,
const char *linkage_name,
const domain_enum domain,
struct symtab **symtab);
static
struct symbol *lookup_symbol_aux_psymtabs (int block_index,
const char *name,
const char *linkage_name,
const domain_enum domain,
struct symtab **symtab);
#if 0
static
struct symbol *lookup_symbol_aux_minsyms (const char *name,
const char *linkage_name,
const domain_enum domain,
int *is_a_field_of_this,
struct symtab **symtab);
#endif
int deprecated_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 (domain_enum,
struct symtab *, struct symbol *, int, char *);
static void print_msymbol_info (struct minimal_symbol *);
static void symtab_symbol_info (char *, domain_enum, int);
void _initialize_symtab (void);
static int
skip_non_matching_bfd (asection *section, struct objfile *objfile)
{
if (section == NULL)
return 0;
if (section->owner == objfile->obfd)
return 0;
if (objfile->separate_debug_objfile_backlink == NULL)
return 1;
if (section->owner == objfile->separate_debug_objfile_backlink->obfd)
return 0;
return 1;
}
struct type *builtin_type_error;
const struct block *block_found;
struct symtab *
lookup_symtab (const char *name)
{
struct symtab *s;
struct partial_symtab *ps;
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_fullname (s);
if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
{
return s;
}
}
if (real_path != NULL)
{
char *fullname = symtab_to_fullname (s);
if (fullname != NULL)
{
char *rp = gdb_realpath (fullname);
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;
}
static struct symtab **
add_symtab_to_array (struct symtab **arr, void *sym,
int *num_elem, int *max_num)
{
if (*num_elem == *max_num - 1)
{
*max_num = (*max_num) * 2;
arr = xrealloc (arr, (*max_num) * sizeof (struct symtab *));
}
arr[(*num_elem)++] = sym;
arr[(*num_elem)] = NULL;
return arr;
}
struct symtab **
lookup_symtab_all (const char *name)
{
struct symtab *s;
struct partial_symtab **pst_arr;
struct objfile *objfile;
char *real_path = NULL;
char *full_path = NULL;
struct symtab **sym_arr;
int num_found;
int max_num;
num_found = 0;
max_num = 5;
sym_arr = (struct symtab **) xmalloc (max_num * sizeof (struct symtab *));
sym_arr[0] = 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);
}
pst_arr = lookup_partial_symtab_all (name, 1);
if (pst_arr)
{
int i;
for (i = 0; pst_arr[i] != NULL; i++)
{
if (pst_arr[i]->readin)
error ("Internal: readin %s pst for `%s' found when no symtab found.",
pst_arr[i]->filename, name);
PSYMTAB_TO_SYMTAB (pst_arr[i]);
}
xfree (pst_arr);
}
ALL_SYMTABS (objfile, s)
{
if (FILENAME_CMP (name, s->filename) == 0)
{
sym_arr = add_symtab_to_array (sym_arr, s, &num_found, &max_num);
continue;
}
if (full_path != NULL)
{
const char *fp = symtab_to_fullname (s);
if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
{
sym_arr = add_symtab_to_array (sym_arr, s, &num_found, &max_num);
continue;
}
}
if (real_path != NULL)
{
const char *fullname = symtab_to_fullname (s);
if (fullname != NULL)
{
char *rp = gdb_realpath (fullname);
make_cleanup (xfree, rp);
if (FILENAME_CMP (real_path, rp) == 0)
{
sym_arr = add_symtab_to_array (sym_arr, s, &num_found, &max_num);
continue;
}
}
}
}
if (lbasename (name) == name)
ALL_SYMTABS (objfile, s)
{
const char *s_basename = lbasename (s->filename);
if (s_basename != s->filename && FILENAME_CMP (s_basename, name) == 0)
{
sym_arr = add_symtab_to_array (sym_arr, s, &num_found, &max_num);
continue;
}
}
if (num_found == 0)
{
xfree (sym_arr);
return NULL;
}
else
return sym_arr;
}
struct partial_symtab *
lookup_partial_symtab (const char *name)
{
struct partial_symtab *pst;
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);
}
static struct partial_symtab **
add_partial_symtab_to_array (struct partial_symtab **arr, void *sym,
int *num_elem, int *max_num)
{
if (*num_elem == *max_num - 1)
{
*max_num = (*max_num) * 2;
arr = xrealloc (arr, (*max_num) * sizeof (struct partial_symtab *));
}
arr[(*num_elem)++] = sym;
arr[(*num_elem)] = NULL;
return arr;
}
struct partial_symtab **
lookup_partial_symtab_all (const char *name, int only_unread)
{
struct partial_symtab *pst;
struct objfile *objfile;
char *full_path = NULL;
char *real_path = NULL;
struct partial_symtab **psym_arr;
int num_found;
int max_num;
num_found = 0;
max_num = 5;
psym_arr = (struct partial_symtab **)
xmalloc (max_num * sizeof (struct partial_symtab *));
psym_arr[0] = 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)
{
if (only_unread && pst->readin)
continue;
psym_arr = add_partial_symtab_to_array (psym_arr, pst, &num_found,
&max_num);
continue;
}
if (full_path != NULL)
{
psymtab_to_fullname (pst);
if (pst->fullname != NULL
&& FILENAME_CMP (full_path, pst->fullname) == 0)
{
if (only_unread && pst->readin)
continue;
psym_arr = add_partial_symtab_to_array (psym_arr, pst, &num_found,
&max_num);
continue;
}
}
if (real_path != NULL)
{
char *rp = NULL;
psymtab_to_fullname (pst);
if (pst->fullname != NULL)
{
rp = gdb_realpath (pst->fullname);
make_cleanup (xfree, rp);
}
if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
{
if (only_unread && pst->readin)
continue;
psym_arr = add_partial_symtab_to_array (psym_arr, pst, &num_found, &max_num);
continue;
}
}
}
if (lbasename (name) == name)
ALL_PSYMTABS (objfile, pst)
{
const char *pst_name = lbasename (pst->filename);
if (pst_name != pst->filename && FILENAME_CMP (pst_name, name) == 0)
{
if (only_unread && pst->readin)
continue;
psym_arr = add_partial_symtab_to_array (psym_arr, pst, &num_found, &max_num);
}
}
if (num_found == 0)
{
xfree (psym_arr);
return NULL;
}
else
return (psym_arr);
}
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 && strcmp (field_name, newname) == 0);
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);
{
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_language_specific (struct general_symbol_info *gsymbol,
enum language language)
{
gsymbol->language = language;
if (gsymbol->language == language_cplus
|| gsymbol->language == language_java
|| gsymbol->language == language_objc
|| gsymbol->language == language_objcplus)
{
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
else
{
memset (&gsymbol->language_specific, 0,
sizeof (gsymbol->language_specific));
}
}
static void
create_demangled_names_hash (struct objfile *objfile)
{
objfile->demangled_names_hash = htab_create_alloc
(256, htab_hash_string, (int (*) (const void *, const void *)) streq,
NULL, xcalloc, xfree);
}
static char *
symbol_find_demangled_name (struct general_symbol_info *gsymbol,
const char *mangled)
{
char *demangled = NULL;
if (gsymbol->language == language_unknown)
gsymbol->language = language_auto;
if (gsymbol->language == language_objc
|| gsymbol->language == language_objcplus
|| gsymbol->language == language_auto)
{
demangled =
objc_demangle (mangled, 0);
if (demangled != NULL)
{
gsymbol->language = language_objc;
return demangled;
}
}
if (gsymbol->language == language_cplus
|| gsymbol->language == language_objcplus
|| gsymbol->language == language_auto)
{
demangled =
cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
if (demangled != NULL)
{
gsymbol->language = language_cplus;
return demangled;
}
}
if (gsymbol->language == language_java)
{
demangled =
cplus_demangle (mangled,
DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
if (demangled != NULL)
{
gsymbol->language = language_java;
return demangled;
}
}
return NULL;
}
#define JAVA_PREFIX "##JAVA$$"
#define JAVA_PREFIX_LEN 8
void
symbol_set_names (struct general_symbol_info *gsymbol,
const char *linkage_name, int len, struct objfile *objfile)
{
char **slot;
const char *linkage_name_copy;
const char *lookup_name;
int lookup_len;
if (objfile->demangled_names_hash == NULL)
create_demangled_names_hash (objfile);
if (gsymbol->language == language_java)
{
char *alloc_name;
lookup_len = len + JAVA_PREFIX_LEN;
alloc_name = alloca (lookup_len + 1);
memcpy (alloc_name, JAVA_PREFIX, JAVA_PREFIX_LEN);
memcpy (alloc_name + JAVA_PREFIX_LEN, linkage_name, len);
alloc_name[lookup_len] = '\0';
lookup_name = alloc_name;
linkage_name_copy = alloc_name + JAVA_PREFIX_LEN;
}
else if (linkage_name[len] != '\0')
{
char *alloc_name;
lookup_len = len;
alloc_name = alloca (lookup_len + 1);
memcpy (alloc_name, linkage_name, len);
alloc_name[lookup_len] = '\0';
lookup_name = alloc_name;
linkage_name_copy = alloc_name;
}
else
{
lookup_len = len;
lookup_name = linkage_name;
linkage_name_copy = linkage_name;
}
slot = (char **) htab_find_slot (objfile->demangled_names_hash,
lookup_name, INSERT);
if (*slot == NULL)
{
char *demangled_name = symbol_find_demangled_name (gsymbol,
linkage_name_copy);
int demangled_len = demangled_name ? strlen (demangled_name) : 0;
*slot = obstack_alloc (&objfile->objfile_obstack,
lookup_len + demangled_len + 2);
memcpy (*slot, lookup_name, lookup_len + 1);
if (demangled_name != NULL)
{
memcpy (*slot + lookup_len + 1, demangled_name, demangled_len + 1);
xfree (demangled_name);
}
else
(*slot)[lookup_len + 1] = '\0';
}
else
{
xfree (symbol_find_demangled_name (gsymbol, linkage_name_copy));
}
gsymbol->name = *slot + lookup_len - len;
if ((*slot)[lookup_len + 1] != '\0')
gsymbol->language_specific.cplus_specific.demangled_name
= &(*slot)[lookup_len + 1];
else
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
void
symbol_init_demangled_name (struct general_symbol_info *gsymbol,
struct obstack *obstack)
{
char *mangled = gsymbol->name;
char *demangled = NULL;
demangled = symbol_find_demangled_name (gsymbol, mangled);
if (gsymbol->language == language_cplus
|| gsymbol->language == language_java
|| gsymbol->language == language_objc
|| gsymbol->language == language_objcplus)
{
if (demangled)
{
gsymbol->language_specific.cplus_specific.demangled_name
= obsavestring (demangled, strlen (demangled), obstack);
xfree (demangled);
}
else
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
else
{
if (demangled)
xfree (demangled);
}
}
char *
symbol_natural_name (const struct general_symbol_info *gsymbol)
{
switch (gsymbol->language)
{
case language_cplus:
case language_java:
case language_objc:
case language_objcplus:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
break;
case language_ada:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
else
return ada_decode_symbol (gsymbol);
break;
default:
break;
}
return gsymbol->name;
}
char *
symbol_demangled_name (struct general_symbol_info *gsymbol)
{
switch (gsymbol->language)
{
case language_cplus:
case language_java:
case language_objc:
case language_objcplus:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
break;
case language_ada:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
else
return ada_decode_symbol (gsymbol);
break;
default:
break;
}
return NULL;
}
char *
symbol_search_name (const struct general_symbol_info *gsymbol)
{
if (gsymbol->language == language_ada)
return gsymbol->name;
else
return symbol_natural_name (gsymbol);
}
void
init_sal (struct symtab_and_line *sal)
{
sal->symtab = 0;
sal->section = 0;
sal->line = 0;
sal->pc = 0;
sal->end = 0;
}
struct partial_symtab *
find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
{
struct partial_symtab *pst;
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_OBJFILES (objfile)
{
if (skip_non_matching_bfd (section, objfile))
continue;
ALL_OBJFILE_PSYMTABS (objfile, pst)
{
if (pc >= pst->textlow && pc < pst->texthigh)
{
struct partial_symtab *tpst;
struct partial_symtab *best_pst = pst;
struct partial_symbol *best_psym = NULL;
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);
if (p != NULL)
{
if (best_psym == NULL
|| SYMBOL_VALUE_ADDRESS (p)
> SYMBOL_VALUE_ADDRESS (best_psym))
{
best_psym = p;
best_pst = tpst;
}
}
}
}
return (best_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_DOMAIN (p) == VAR_DOMAIN
&& 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_DOMAIN (p) == VAR_DOMAIN
&& 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)
{
if (ginfo->bfd_section != SYMBOL_BFD_SECTION (msym))
ginfo->bfd_section = SYMBOL_BFD_SECTION (msym);
if (ginfo->section != SYMBOL_SECTION (msym))
ginfo->section = SYMBOL_SECTION (msym);
}
else if (objfile)
{
CORE_ADDR addr;
struct obj_section *s;
addr = ginfo->value.address;
ALL_OBJFILE_OSECTIONS (objfile, s)
{
int idx = s->the_bfd_section->index;
CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx);
if (s->addr - offset <= addr && addr < s->endaddr - offset)
{
ginfo->bfd_section = s->the_bfd_section;
ginfo->section = idx;
return;
}
}
}
}
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 domain_enum domain, int *is_a_field_of_this,
struct symtab **symtab)
{
char *demangled_name = NULL;
const char *modified_name = NULL;
const char *mangled_name = NULL;
int needtofreename = 0;
struct symbol *returnval;
modified_name = name;
if (current_language->la_language == language_cplus ||
current_language->la_language == language_objcplus)
{
demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
if (demangled_name)
{
mangled_name = name;
modified_name = demangled_name;
needtofreename = 1;
}
}
else if (current_language->la_language == language_java)
{
demangled_name = cplus_demangle (name,
DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
if (demangled_name)
{
mangled_name = name;
modified_name = demangled_name;
needtofreename = 1;
}
}
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;
}
returnval = lookup_symbol_aux (modified_name, mangled_name, block,
domain, is_a_field_of_this, symtab);
if (needtofreename)
xfree (demangled_name);
return returnval;
}
static struct symbol *
lookup_symbol_aux (const char *name, const char *linkage_name,
const struct block *block, const domain_enum domain,
int *is_a_field_of_this, struct symtab **symtab)
{
struct symbol *sym;
if (is_a_field_of_this != NULL)
*is_a_field_of_this = 0;
sym = lookup_symbol_aux_local (name, linkage_name, block, domain,
symtab);
if (sym != NULL)
return sym;
if (current_language->la_value_of_this != NULL
&& is_a_field_of_this != NULL)
{
struct value *v = current_language->la_value_of_this (0);
if (v && check_field (v, name))
{
*is_a_field_of_this = 1;
if (symtab != NULL)
*symtab = NULL;
return NULL;
}
}
sym = current_language->la_lookup_symbol_nonlocal (name, linkage_name,
block, domain,
symtab);
if (sym != NULL)
return sym;
sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, linkage_name,
domain, symtab);
if (sym != NULL)
return sym;
sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name,
domain, symtab);
if (sym != NULL)
return sym;
if (symtab != NULL)
*symtab = NULL;
return NULL;
}
static struct symbol *
lookup_symbol_aux_local (const char *name, const char *linkage_name,
const struct block *block,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
const struct block *static_block = block_static_block (block);
if (static_block == NULL)
return NULL;
while (block != static_block)
{
sym = lookup_symbol_aux_block (name, linkage_name, block, domain,
symtab);
if (sym != NULL)
return sym;
block = BLOCK_SUPERBLOCK (block);
}
return NULL;
}
struct symbol *
lookup_symbol_aux_block (const char *name, const char *linkage_name,
const struct block *block,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
struct objfile *objfile = NULL;
struct blockvector *bv;
struct block *b;
struct symtab *s = NULL;
sym = lookup_block_symbol (block, name, linkage_name, domain);
if (sym && !SYMBOL_OBSOLETED (sym))
{
block_found = block;
if (symtab != NULL)
{
ALL_SYMTABS_INCL_OBSOLETED (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);
}
return NULL;
}
static struct symbol *
lookup_symbol_aux_symtabs (int block_index,
const char *name, const char *linkage_name,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
struct objfile *objfile;
struct blockvector *bv;
const struct block *block;
struct symtab *s;
ALL_SYMTABS_INCL_OBSOLETED (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = lookup_block_symbol (block, name, linkage_name, domain);
if (sym && !SYMBOL_OBSOLETED (sym))
{
block_found = block;
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
return NULL;
}
static struct symbol *
lookup_symbol_aux_psymtabs (int block_index, const char *name,
const char *linkage_name,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
struct objfile *objfile;
struct blockvector *bv;
const struct block *block;
struct partial_symtab *ps;
struct symtab *s;
const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin
&& lookup_partial_symbol (ps, name, linkage_name,
psymtab_index, domain))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = lookup_block_symbol (block, name, linkage_name, domain);
if (!sym || SYMBOL_OBSOLETED (sym))
{
block = BLOCKVECTOR_BLOCK (bv,
block_index == GLOBAL_BLOCK ?
STATIC_BLOCK : GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, linkage_name, domain);
if (!sym || SYMBOL_OBSOLETED (sym))
error (_("Internal: %s 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>)."),
block_index == GLOBAL_BLOCK ? "global" : "static",
name, ps->filename, name, name);
}
if (symtab != NULL)
*symtab = s;
return fixup_symbol_section (sym, objfile);
}
}
return NULL;
}
#if 0
static struct symbol *
lookup_symbol_aux_minsyms (const char *name,
const char *linkage_name,
const domain_enum domain,
int *is_a_field_of_this,
struct symtab **symtab)
{
struct symbol *sym;
struct blockvector *bv;
const struct block *block;
struct minimal_symbol *msymbol;
struct symtab *s;
if (domain == VAR_DOMAIN)
{
msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol != NULL && !MSYMBOL_OBSOLETED(msymbol))
{
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, name, linkage_name, domain);
if (!sym || SYMBOL_OBSOLETED (sym))
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name,
linkage_name, domain);
}
if (symtab != NULL && sym != NULL)
*symtab = s;
return fixup_symbol_section (sym, s->objfile);
}
}
}
return NULL;
}
#endif
struct symbol *
basic_lookup_symbol_nonlocal (const char *name,
const char *linkage_name,
const struct block *block,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
sym = lookup_symbol_static (name, linkage_name, block, domain, symtab);
if (sym != NULL)
return sym;
return lookup_symbol_global (name, linkage_name, domain, symtab);
}
struct symbol *
lookup_symbol_static (const char *name,
const char *linkage_name,
const struct block *block,
const domain_enum domain,
struct symtab **symtab)
{
const struct block *static_block = block_static_block (block);
if (static_block != NULL)
return lookup_symbol_aux_block (name, linkage_name, static_block,
domain, symtab);
else
return NULL;
}
struct symbol *
lookup_symbol_global (const char *name,
const char *linkage_name,
const domain_enum domain,
struct symtab **symtab)
{
struct symbol *sym;
sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name,
domain, symtab);
if (sym != NULL)
return sym;
return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name,
domain, symtab);
}
struct partial_symbol *
lookup_partial_symbol (struct partial_symtab *pst, const char *name,
const char *linkage_name, int global,
domain_enum domain)
{
struct partial_symbol **start, **psym;
struct partial_symbol **top, **real_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;
real_top = top;
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_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0)
{
top = center;
}
else
{
bottom = center + 1;
}
}
if (!(top == bottom))
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
while (top <= real_top)
{
if (!SYMBOL_MATCHES_NATURAL_NAME (*top,name))
break;
if (!linkage_name ||
strcmp (SYMBOL_LINKAGE_NAME (*top), linkage_name) == 0)
{
if (SYMBOL_DOMAIN (*top) == domain)
{
return (*top);
}
}
top++;
}
}
if (do_linear_search)
{
for (psym = start; psym < start + length; psym++)
{
if (domain == SYMBOL_DOMAIN (*psym))
{
if (linkage_name != NULL
? strcmp (SYMBOL_LINKAGE_NAME (*psym), linkage_name) == 0
: SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
{
return (*psym);
}
}
}
}
return (NULL);
}
struct type *
lookup_transparent_type (const char *name)
{
return current_language->la_lookup_transparent_type (name);
}
struct type *
basic_lookup_transparent_type (const char *name)
{
struct symbol *sym;
struct symtab *s = NULL;
struct partial_symtab *ps;
struct blockvector *bv;
struct objfile *objfile;
struct block *block;
ALL_SYMTABS_INCL_OBSOLETED (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)) && !SYMBOL_OBSOLETED (sym))
{
return SYMBOL_TYPE (sym);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, NULL,
1, STRUCT_DOMAIN))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (!sym || SYMBOL_OBSOLETED (sym))
{
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (!sym || SYMBOL_OBSOLETED (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_INCL_OBSOLETED (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)) && !SYMBOL_OBSOLETED (sym))
{
return SYMBOL_TYPE (sym);
}
}
ALL_PSYMTABS (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (ps, name, NULL, 0, STRUCT_DOMAIN))
{
s = PSYMTAB_TO_SYMTAB (ps);
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (!sym || SYMBOL_OBSOLETED (sym))
{
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
if (!sym || SYMBOL_OBSOLETED (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)
{
struct partial_symtab *pst;
struct objfile *objfile;
ALL_PSYMTABS (objfile, pst)
{
if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN))
{
return (pst);
}
}
return (NULL);
}
struct symbol *
lookup_block_symbol (const struct block *block, const char *name,
const char *linkage_name,
const domain_enum domain)
{
struct dict_iterator iter;
struct symbol *sym;
if (!BLOCK_FUNCTION (block))
{
for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
sym != NULL;
sym = dict_iter_name_next (name, &iter))
{
if (SYMBOL_DOMAIN (sym) == domain
&& (linkage_name != NULL
? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
return sym;
}
return NULL;
}
else
{
struct symbol *sym_found = NULL;
for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
sym != NULL;
sym = dict_iter_name_next (name, &iter))
{
if (SYMBOL_DOMAIN (sym) == domain
&& (linkage_name != NULL
? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
{
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 &&
SYMBOL_CLASS (sym) != LOC_COMPUTED_ARG)
{
break;
}
}
}
return (sym_found);
}
}
struct symtab *
find_pc_sect_symtab (CORE_ADDR pc, asection *section)
{
struct block *b;
struct blockvector *bv;
struct symtab *s = NULL;
struct symtab *best_s = NULL;
struct partial_symtab *ps;
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_INCL_OBSOLETED (objfile, s)
{
if (skip_non_matching_bfd (section, objfile))
continue;
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)
{
struct dict_iterator iter;
struct symbol *sym = NULL;
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
fixup_symbol_section (sym, objfile);
if (section == SYMBOL_BFD_SECTION (sym))
break;
}
if (sym == NULL)
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));
}
struct symtab_and_line
find_pc_sect_line (CORE_ADDR pc, struct bfd_section *section, int notcurrent)
{
struct symtab *s;
struct linetable *l;
int len;
int i;
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_LINKAGE_NAME (msymbol),
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 && prev->line && (!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 (strcmp (symtab->filename, s->filename) != 0)
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;
}
int
find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
{
CORE_ADDR end;
struct symtab_and_line sal;
*pc = 0;
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;
if (sal.symtab == NULL)
return 0;
if (sal.symtab->linetable == NULL)
return 0;
if ((sal.symtab->line_charpos == 0) && (sal.symtab->linetable->lines_are_chars))
{
int fd = open_source_file (sal.symtab);
if (fd < 0)
return 0;
find_source_lines (sal.symtab, fd);
close (fd);
}
if (sal.symtab->linetable->lines_are_chars)
line = sal.symtab->line_charpos[sal.line - 1];
else
line = sal.line;
if (sal.pc == 0)
{
struct symtab *symtab;
struct linetable *l;
int ind;
symtab = find_line_symtab (sal.symtab, line, &ind, NULL);
if (symtab == NULL)
return 0;
l = LINETABLE (symtab);
*startptr = l->item[ind].pc;
if (ind == l->nitems - 1)
*endptr = *startptr;
else if (l->item[ind].line != line)
*endptr = *startptr;
else
*endptr = l->item[ind + 1].pc;
return 1;
}
else
{
startaddr = sal.pc;
}
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 (struct linetable *l, int lineno,
int *exact_match)
{
int i;
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++)
{
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;
struct block *block;
block = SYMBOL_BLOCK_VALUE (sym);
if (block == NULL)
error ("Found function with NULL block: \"%s\"", SYMBOL_PRINT_NAME (sym));
pc = BLOCK_START (block);
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 += DEPRECATED_FUNCTION_START_OFFSET;
pc = SKIP_PROLOGUE (pc);
pc = overlay_mapped_address (pc, section);
}
sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
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;
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 == '$')
{
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 (const 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)
{
struct symtab *s;
struct partial_symtab *ps;
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)
{
const char *fullname = symtab_to_fullname (s);
output_source_filename (fullname ? fullname : 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)
{
const char *fullname = psymtab_to_fullname (ps);
output_source_filename (fullname ? fullname : 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_PRINT_NAME ((*sym_a)->symbol),
SYMBOL_PRINT_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, domain_enum kind, int nfiles, char *files[],
struct symbol_search **matches)
{
struct symtab *s;
struct partial_symtab *ps;
struct blockvector *bv;
struct blockvector *prev_bv = 0;
struct block *b;
int i = 0;
struct dict_iterator iter;
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_DOMAIN)
error (_("must search on specific domain"));
ourtype = types[(int) (kind - VARIABLES_DOMAIN)];
ourtype2 = types2[(int) (kind - VARIABLES_DOMAIN)];
ourtype3 = types3[(int) (kind - VARIABLES_DOMAIN)];
ourtype4 = types4[(int) (kind - VARIABLES_DOMAIN)];
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
|| re_exec (SYMBOL_NATURAL_NAME (*psym)) != 0)
&& ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
&& SYMBOL_CLASS (*psym) != LOC_BLOCK)
|| (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (*psym) == LOC_BLOCK)
|| (kind == TYPES_DOMAIN && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)
|| (kind == METHODS_DOMAIN && SYMBOL_CLASS (*psym) == LOC_BLOCK))))
{
PSYMTAB_TO_SYMTAB (ps);
keep_going = 0;
}
}
psym++;
}
}
if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
{
ALL_OBJFILES (objfile)
{
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
if (MSYMBOL_OBSOLETED (msymbol))
continue;
if (MSYMBOL_TYPE (msymbol) == ourtype ||
MSYMBOL_TYPE (msymbol) == ourtype2 ||
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (regexp == NULL
|| re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
{
if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
{
if (kind == FUNCTIONS_DOMAIN)
{
found_misc = 1;
}
else
{
struct symbol *sym;
sym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
(struct block *) NULL,
VAR_DOMAIN,
0, (struct symtab **) NULL);
if (!sym || SYMBOL_VALUE_ADDRESS (sym) != SYMBOL_VALUE_ADDRESS (msymbol))
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);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
QUIT;
if (SYMBOL_OBSOLETED (sym))
continue;
if (file_matches (s->filename, files, nfiles)
&& ((regexp == NULL
|| re_exec (SYMBOL_NATURAL_NAME (sym)) != 0)
&& ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK
&& SYMBOL_CLASS (sym) != LOC_CONST)
|| (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (sym) == LOC_BLOCK)
|| (kind == TYPES_DOMAIN && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|| (kind == METHODS_DOMAIN && 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_DOMAIN)
{
ALL_OBJFILES (objfile)
{
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
if (MSYMBOL_OBSOLETED (msymbol))
continue;
if (MSYMBOL_TYPE (msymbol) == ourtype ||
MSYMBOL_TYPE (msymbol) == ourtype2 ||
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (regexp == NULL
|| re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
{
if (kind != FUNCTIONS_DOMAIN ||
(0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
{
struct symbol *sym;
sym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
(struct block *) NULL, VAR_DOMAIN,
0, (struct symtab **) NULL);
if (sym == NULL || SYMBOL_VALUE_ADDRESS (sym) != SYMBOL_VALUE_ADDRESS (msymbol))
{
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 (domain_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_DOMAIN && block == STATIC_BLOCK)
printf_filtered ("static ");
if (kind == TYPES_DOMAIN
&& SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
else if (kind < TYPES_DOMAIN ||
(kind == TYPES_DOMAIN &&
SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
{
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_PRINT_NAME (sym)),
gdb_stdout, 0);
printf_filtered (";\n");
}
}
static void
print_msymbol_info (struct minimal_symbol *msymbol)
{
char *tmp;
if (TARGET_ADDR_BIT <= 32)
tmp = hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
& (CORE_ADDR) 0xffffffff,
8);
else
tmp = hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
16);
printf_filtered ("%s %s\n",
tmp, SYMBOL_PRINT_NAME (msymbol));
}
static void
symtab_symbol_info (char *regexp, domain_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_DOMAIN)], 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_DOMAIN, from_tty);
}
static void
functions_info (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
}
static void
types_info (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
}
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;
struct cleanup *objc_selectors_cleanup;
search_symbols (regexp, FUNCTIONS_DOMAIN, 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 *shlib_ptr = NULL;
int shlib_len = 0;
if (p->symtab->objfile != NULL && p->symtab->objfile->name != NULL)
{
shlib_ptr = p->symtab->objfile->name;
shlib_len = strlen (p->symtab->objfile->name)
+ strlen("-shlib \"\" ");
}
char *string = alloca (shlib_len
+ strlen (p->symtab->filename)
+ strlen (SYMBOL_LINKAGE_NAME (p->symbol))
+ 4);
if (shlib_ptr != NULL)
{
strcpy (string, "-shlib \"");
strcat (string, p->symtab->objfile->name);
strcat (string, "\" \"");
}
else
{
strcpy (string, "\"");
}
strcat (string, p->symtab->filename);
strcat (string, ":");
strcat (string, SYMBOL_LINKAGE_NAME (p->symbol));
strcat (string, "\"");
break_command (string, from_tty);
print_symbol_info (FUNCTIONS_DOMAIN,
p->symtab,
p->symbol,
p->block,
p->symtab->filename);
}
else
{
const char *shlib_ptr = NULL;
int shlib_len = 0;
if (p->msymbol->ginfo.bfd_section != NULL
&& p->msymbol->ginfo.bfd_section->owner != NULL
&& p->msymbol->ginfo.bfd_section->owner->filename != NULL)
{
shlib_ptr = p->msymbol->ginfo.bfd_section->owner->filename;
shlib_len = strlen (shlib_ptr)
+ strlen("-shlib \"\" ");
}
char *string = alloca (shlib_len
+ strlen (SYMBOL_LINKAGE_NAME (p->msymbol))
+ 4);
if (shlib_ptr != NULL)
{
strcpy (string, "-shlib \"");
strcat (string, shlib_ptr);
strcat (string, "\" '");
}
else
{
strcpy (string, "'");
}
strcat (string, SYMBOL_LINKAGE_NAME (p->msymbol));
strcat (string, "'");
allow_objc_selectors_flag = 0;
objc_selectors_cleanup =
make_cleanup (reset_allow_objc_selectors_flag, 0);
break_command (string, from_tty);
printf_filtered ("<function, no debug info> %s;\n",
SYMBOL_PRINT_NAME (p->msymbol));
}
}
do_cleanups (old_chain);
}
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) \
completion_list_add_name \
(SYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
static void
completion_list_add_name (char *symname, char *sym_text, int sym_text_len,
char *text, char *word)
{
int newsize;
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;
}
}
static void
completion_list_objc_symbol (struct minimal_symbol *msymbol, char *sym_text,
int sym_text_len, char *text, char *word)
{
static char *tmp = NULL;
static unsigned int tmplen = 0;
char *method, *category, *selector;
char *tmp2 = NULL;
method = SYMBOL_NATURAL_NAME (msymbol);
if ((method[0] != '-') && (method[0] != '+'))
return;
if (sym_text[0] == '[')
completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
while ((strlen (method) + 1) >= tmplen)
{
if (tmplen == 0)
tmplen = 1024;
else
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);
}
}
static char *
language_search_unquoted_string (char *text, char *p)
{
for (; p > text; --p)
{
if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
continue;
else
{
if ((current_language->la_language == language_objc))
{
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;
}
}
return p;
}
char **
make_symbol_completion_list (char *text, char *word)
{
struct symbol *sym;
struct symtab *s;
struct partial_symtab *ps;
struct minimal_symbol *msymbol;
struct objfile *objfile;
struct block *b, *surrounding_static_block = 0;
struct dict_iterator iter;
int 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;
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_MSYMBOLS (objfile, msymbol)
{
QUIT;
COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
completion_list_objc_symbol (msymbol, 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, iter, 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, iter, 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, iter, 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)
{
struct symbol *sym;
struct symtab *s;
struct block *b;
struct dict_iterator iter;
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
{
sym_text = language_search_unquoted_string (text, p);
}
}
return_val_size = 10;
return_val_index = 0;
return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
return_val[0] = NULL;
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, iter, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, 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)
{
struct symtab *s;
struct partial_symtab *ps;
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;
}
CORE_ADDR
skip_prologue_using_sal (CORE_ADDR func_addr)
{
struct symtab_and_line prologue_sal;
CORE_ADDR start_pc;
CORE_ADDR end_pc;
find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
start_pc += DEPRECATED_FUNCTION_START_OFFSET;
prologue_sal = find_pc_line (start_pc, 0);
if (prologue_sal.line != 0)
{
while (prologue_sal.end < end_pc)
{
struct symtab_and_line sal;
sal = find_pc_line (prologue_sal.end, 0);
if (sal.line == 0)
break;
if (sal.line >= prologue_sal.line)
break;
prologue_sal = sal;
}
}
return prologue_sal.end;
}
struct symtabs_and_lines
decode_line_spec (char *string, int funfirstline)
{
struct symtabs_and_lines sals;
struct symtab_and_line cursal;
if (string == 0)
error (_("Empty line specification."));
cursal = get_current_source_symtab_and_line ();
sals = decode_line_1 (&string, funfirstline,
cursal.symtab, cursal.line,
(char ***) NULL, 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);
}
}
static void
find_main_name (void)
{
char *new_main_name;
new_main_name = ada_main_name ();
if (new_main_name != NULL)
{
set_main_name (new_main_name);
return;
}
set_main_name ("main");
}
char *
main_name (void)
{
if (name_of_main == NULL)
find_main_name ();
return name_of_main;
}
static void
symtab_observer_executable_changed (void *unused)
{
set_main_name (NULL);
}
void
_initialize_symtab (void)
{
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."));
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);
add_setshow_boolean_cmd ("metrowerks-ignore-breakpoint-errors", class_obscure,
&metrowerks_ignore_breakpoint_errors_flag, _("\
Set if GDB should avoid printing an error message when unable to set a breakpoint."), _("\
Show if GDB should avoid printing an error message when unable to set a breakpoint."), _("\
what to say?"),
NULL,
NULL,
&setlist, &showlist);
observer_attach_executable_changed (symtab_observer_executable_changed);
}