/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
This file is part of GDB.
const char *name,
struct obstack *obstack)
{
- if (gsymbol->language == language_ada)
+ if (gsymbol->language () == language_ada)
{
if (name == NULL)
{
const char *
symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
{
- if (gsymbol->language == language_ada)
+ if (gsymbol->language () == language_ada)
{
if (!gsymbol->ada_mangled)
return NULL;
depending upon the language for the symbol. */
void
-symbol_set_language (struct general_symbol_info *gsymbol,
- enum language language,
- struct obstack *obstack)
+general_symbol_info::set_language (enum language language,
+ struct obstack *obstack)
{
- gsymbol->language = language;
- if (gsymbol->language == language_cplus
- || gsymbol->language == language_d
- || gsymbol->language == language_go
- || gsymbol->language == language_objc
- || gsymbol->language == language_fortran)
+ m_language = language;
+ if (language == language_cplus
+ || language == language_d
+ || language == language_go
+ || language == language_objc
+ || language == language_fortran)
{
- symbol_set_demangled_name (gsymbol, NULL, obstack);
+ symbol_set_demangled_name (this, NULL, obstack);
}
- else if (gsymbol->language == language_ada)
+ else if (language == language_ada)
{
- gdb_assert (gsymbol->ada_mangled == 0);
- gsymbol->language_specific.obstack = obstack;
+ gdb_assert (ada_mangled == 0);
+ language_specific.obstack = obstack;
}
else
{
- memset (&gsymbol->language_specific, 0,
- sizeof (gsymbol->language_specific));
+ memset (&language_specific, 0, sizeof (language_specific));
}
}
char *demangled = NULL;
int i;
- if (gsymbol->language == language_unknown)
- gsymbol->language = language_auto;
+ if (gsymbol->language () == language_unknown)
+ gsymbol->m_language = language_auto;
- if (gsymbol->language != language_auto)
+ if (gsymbol->language () != language_auto)
{
- const struct language_defn *lang = language_def (gsymbol->language);
+ const struct language_defn *lang = language_def (gsymbol->language ());
language_sniff_from_mangled_name (lang, mangled, &demangled);
return demangled;
if (language_sniff_from_mangled_name (lang, mangled, &demangled))
{
- gsymbol->language = l;
+ gsymbol->m_language = l;
return demangled;
}
}
so the pointer can be discarded after calling this function. */
void
-symbol_set_names (struct general_symbol_info *gsymbol,
- gdb::string_view linkage_name, bool copy_name,
- struct objfile_per_bfd_storage *per_bfd,
- gdb::optional<hashval_t> hash)
+general_symbol_info::compute_and_set_names (gdb::string_view linkage_name,
+ bool copy_name,
+ objfile_per_bfd_storage *per_bfd,
+ gdb::optional<hashval_t> hash)
{
struct demangled_name_entry **slot;
- if (gsymbol->language == language_ada)
+ if (language () == language_ada)
{
/* In Ada, we do the symbol lookups using the mangled name, so
we can save some space by not storing the demangled name. */
if (!copy_name)
- gsymbol->name = linkage_name.data ();
+ m_name = linkage_name.data ();
else
- {
- char *name = (char *) obstack_alloc (&per_bfd->storage_obstack,
- linkage_name.length () + 1);
-
- memcpy (name, linkage_name.data (), linkage_name.length ());
- name[linkage_name.length ()] = '\0';
- gsymbol->name = name;
- }
- symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack);
+ m_name = obstack_strndup (&per_bfd->storage_obstack,
+ linkage_name.data (),
+ linkage_name.length ());
+ symbol_set_demangled_name (this, NULL, &per_bfd->storage_obstack);
return;
}
htab_find_slot_with_hash (per_bfd->demangled_names_hash.get (),
&entry, *hash, INSERT));
+ /* The const_cast is safe because the only reason it is already
+ initialized is if we purposefully set it from a background
+ thread to avoid doing the work here. However, it is still
+ allocated from the heap and needs to be freed by us, just
+ like if we called symbol_find_demangled_name here. If this is
+ nullptr, we call symbol_find_demangled_name below, but we put
+ this smart pointer here to be sure that we don't leak this name. */
+ gdb::unique_xmalloc_ptr<char> demangled_name
+ (const_cast<char *> (language_specific.demangled_name));
+
/* If this name is not in the hash table, add it. */
if (*slot == NULL
/* A C version of the symbol may have already snuck into the table.
This happens to, e.g., main.init (__go_init_main). Cope. */
- || (gsymbol->language == language_go && (*slot)->demangled == nullptr))
+ || (language () == language_go && (*slot)->demangled == nullptr))
{
/* A 0-terminated copy of the linkage name. Callers must set COPY_NAME
to true if the string might not be nullterminated. We have to make
else
linkage_name_copy = linkage_name;
- /* The const_cast is safe because the only reason it is already
- initialized is if we purposefully set it from a background
- thread to avoid doing the work here. However, it is still
- allocated from the heap and needs to be freed by us, just
- like if we called symbol_find_demangled_name here. */
- gdb::unique_xmalloc_ptr<char> demangled_name
- (gsymbol->language_specific.demangled_name
- ? const_cast<char *> (gsymbol->language_specific.demangled_name)
- : symbol_find_demangled_name (gsymbol, linkage_name_copy.data ()));
+ if (demangled_name.get () == nullptr)
+ demangled_name.reset
+ (symbol_find_demangled_name (this, linkage_name_copy.data ()));
/* Suppose we have demangled_name==NULL, copy_name==0, and
linkage_name_copy==linkage_name. In this case, we already have the
(gdb::string_view (mangled_ptr, linkage_name.length ()));
}
(*slot)->demangled = std::move (demangled_name);
- (*slot)->language = gsymbol->language;
+ (*slot)->language = language ();
}
- else if (gsymbol->language == language_unknown
- || gsymbol->language == language_auto)
- gsymbol->language = (*slot)->language;
+ else if (language () == language_unknown || language () == language_auto)
+ m_language = (*slot)->language;
- gsymbol->name = (*slot)->mangled.data ();
- if ((*slot)->demangled != nullptr)
- symbol_set_demangled_name (gsymbol, (*slot)->demangled.get (),
- &per_bfd->storage_obstack);
- else
- symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack);
+ m_name = (*slot)->mangled.data ();
+ symbol_set_demangled_name (this, (*slot)->demangled.get (),
+ &per_bfd->storage_obstack);
}
/* See symtab.h. */
const char *
general_symbol_info::natural_name () const
{
- switch (language)
+ switch (language ())
{
case language_cplus:
case language_d:
default:
break;
}
- return name;
+ return linkage_name ();
}
/* See symtab.h. */
{
const char *dem_name = NULL;
- switch (language)
+ switch (language ())
{
case language_cplus:
case language_d:
const char *
general_symbol_info::search_name () const
{
- if (language == language_ada)
- return name;
+ if (language () == language_ada)
+ return linkage_name ();
else
return natural_name ();
}
const lookup_name_info &name)
{
symbol_name_matcher_ftype *name_match
- = get_symbol_name_matcher (language_def (gsymbol->language), name);
+ = get_symbol_name_matcher (language_def (gsymbol->language ()), name);
return name_match (gsymbol->search_name (), name, NULL);
}
if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
return 0;
- if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym),
- slot_domain, domain))
+ if (!symbol_matches_domain (sym->language (), slot_domain, domain))
return 0;
}
}
e.g. on PowerPC64, where the minimal symbol for a function will
point to the function descriptor, while the debug symbol will
point to the actual function code. */
- msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->name, objfile);
+ msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->linkage_name (),
+ objfile);
if (msym)
ginfo->section = MSYMBOL_SECTION (msym);
else
So, instead, search the section table when lookup by name has
failed. The ``addr'' and ``endaddr'' fields may have already
- been relocated. If so, the relocation offset (i.e. the
- ANOFFSET value) needs to be subtracted from these values when
- performing the comparison. We unconditionally subtract it,
- because, when no relocation has been performed, the ANOFFSET
- value will simply be zero.
+ been relocated. If so, the relocation offset needs to be
+ subtracted from these values when performing the comparison.
+ We unconditionally subtract it, because, when no relocation
+ has been performed, the value will simply be zero.
The address of the symbol whose section we're fixing up HAS
NOT BEEN adjusted (relocated) yet. It can't have been since
ALL_OBJFILE_OSECTIONS (objfile, s)
{
int idx = s - objfile->sections;
- CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx);
+ CORE_ADDR offset = objfile->section_offsets[idx];
if (fallback == -1)
fallback = idx;
ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
{
- if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
- SYMBOL_DOMAIN (sym), domain))
+ if (symbol_matches_domain (sym->language (), SYMBOL_DOMAIN (sym), domain))
{
struct block_symbol block_sym = {sym, block};
;
/* fall through */
else
- return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0);
+ {
+ /* Detect an obvious case of infinite recursion. If this
+ should occur, we'd like to know about it, so error out,
+ fatally. */
+ if (BMSYMBOL_VALUE_ADDRESS (mfunsym) == pc)
+ internal_error (__FILE__, __LINE__,
+ _("Infinite recursion detected in find_pc_sect_line;"
+ "please file a bug report"));
+
+ return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0);
+ }
}
symtab_and_line val;
struct linetable_entry *last = item + len;
item = std::upper_bound (first, last, pc, pc_compare);
if (item != first)
- prev = item - 1; /* Found a matching item. */
+ {
+ /* Found a matching item. Skip backwards over any end of
+ sequence markers. */
+ for (prev = item - 1; prev->line == 0 && prev != first; prev--)
+ /* Nothing. */;
+ }
/* At this point, prev points at the line whose start addr is <= pc, and
item points at the next line. If we ran off the end of the linetable
best = prev;
best_symtab = iter_s;
+ /* If during the binary search we land on a non-statement entry,
+ scan backward through entries at the same address to see if
+ there is an entry marked as is-statement. In theory this
+ duplication should have been removed from the line table
+ during construction, this is just a double check. If the line
+ table has had the duplication removed then this should be
+ pretty cheap. */
+ if (!best->is_stmt)
+ {
+ struct linetable_entry *tmp = best;
+ while (tmp > first && (tmp - 1)->pc == tmp->pc
+ && (tmp - 1)->line != 0 && !tmp->is_stmt)
+ --tmp;
+ if (tmp->is_stmt)
+ best = tmp;
+ }
+
/* Discard BEST_END if it's before the PC of the current BEST. */
if (best_end <= best->pc)
best_end = 0;
}
else
{
+ val.is_stmt = best->is_stmt;
val.symtab = best_symtab;
val.line = best->line;
val.pc = best->pc;
{
struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
- if (*best_item == NULL || item->line < (*best_item)->line)
+ if (*best_item == NULL
+ || (item->line < (*best_item)->line && item->is_stmt))
*best_item = item;
break;
{
struct linetable_entry *item = &(l->item[i]);
+ /* Ignore non-statements. */
+ if (!item->is_stmt)
+ continue;
+
if (item->line == lineno)
{
/* Return the first (lowest address) entry which matches. */
and 'info functions' commands. These correspond to the -q, -t, and -n
options. */
-struct info_print_options
+struct info_vars_funcs_options
{
bool quiet = false;
bool exclude_minsyms = false;
char *type_regexp = nullptr;
- ~info_print_options ()
+ ~info_vars_funcs_options ()
{
xfree (type_regexp);
}
/* The options used by the 'info variables' and 'info functions'
commands. */
-static const gdb::option::option_def info_print_options_defs[] = {
- gdb::option::boolean_option_def<info_print_options> {
+static const gdb::option::option_def info_vars_funcs_options_defs[] = {
+ gdb::option::boolean_option_def<info_vars_funcs_options> {
"q",
- [] (info_print_options *opt) { return &opt->quiet; },
+ [] (info_vars_funcs_options *opt) { return &opt->quiet; },
nullptr, /* show_cmd_cb */
nullptr /* set_doc */
},
- gdb::option::boolean_option_def<info_print_options> {
+ gdb::option::boolean_option_def<info_vars_funcs_options> {
"n",
- [] (info_print_options *opt) { return &opt->exclude_minsyms; },
+ [] (info_vars_funcs_options *opt) { return &opt->exclude_minsyms; },
nullptr, /* show_cmd_cb */
nullptr /* set_doc */
},
- gdb::option::string_option_def<info_print_options> {
+ gdb::option::string_option_def<info_vars_funcs_options> {
"t",
- [] (info_print_options *opt) { return &opt->type_regexp; },
+ [] (info_vars_funcs_options *opt) { return &opt->type_regexp;
+ },
nullptr, /* show_cmd_cb */
nullptr /* set_doc */
}
functions'. */
static gdb::option::option_def_group
-make_info_print_options_def_group (info_print_options *opts)
+make_info_vars_funcs_options_def_group (info_vars_funcs_options *opts)
{
- return {{info_print_options_defs}, opts};
+ return {{info_vars_funcs_options_defs}, opts};
}
/* Command completer for 'info variables' and 'info functions'. */
static void
-info_print_command_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char * /* word */)
+info_vars_funcs_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
{
const auto group
- = make_info_print_options_def_group (nullptr);
+ = make_info_vars_funcs_options_def_group (nullptr);
if (gdb::option::complete_options
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
return;
static void
info_variables_command (const char *args, int from_tty)
{
- info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
+ info_vars_funcs_options opts;
+ auto grp = make_info_vars_funcs_options_def_group (&opts);
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
if (args != nullptr && *args == '\0')
static void
info_functions_command (const char *args, int from_tty)
{
- info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
+ info_vars_funcs_options opts;
+
+ auto grp = make_info_vars_funcs_options_def_group (&opts);
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
if (args != nullptr && *args == '\0')
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+ completion_list_add_name (tracker, sym->language (),
sym->natural_name (),
lookup_name, text, word);
}
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym),
+ completion_list_add_name (tracker, sym->language (),
sym->natural_name (),
lookup_name, text, word);
}
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 (tracker, SYMBOL_LANGUAGE (sym),
+ completion_list_add_name (tracker, sym->language (),
TYPE_FIELD_NAME (t, j),
lookup_name, text, word);
}
return BMSYMBOL_VALUE_ADDRESS (found);
}
}
- return (minsym->value.address
- + ANOFFSET (objf->section_offsets, minsym->section));
+ return minsym->value.address + objf->section_offsets[minsym->section];
}
\f
\f
+void _initialize_symtab ();
void
-_initialize_symtab (void)
+_initialize_symtab ()
{
cmd_list_element *c;
Prints the global and static variables.\n"),
_("global and static variables"),
true));
- set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+ set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
if (dbx_commands)
{
c = add_com ("whereis", class_info, info_variables_command,
Prints the global and static variables.\n"),
_("global and static variables"),
true));
- set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+ set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
}
c = add_info ("functions", info_functions_command,
Prints the functions.\n"),
_("functions"),
true));
- set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+ set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
c = add_info ("types", info_types_command, _("\
All type names, or those matching REGEXP.\n\