if (!copy_name)
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';
- m_name = name;
- }
+ 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.
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
- (language_specific.demangled_name
- ? const_cast<char *> (language_specific.demangled_name)
- : symbol_find_demangled_name (this, 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
m_language = (*slot)->language;
m_name = (*slot)->mangled.data ();
- if ((*slot)->demangled != nullptr)
- symbol_set_demangled_name (this, (*slot)->demangled.get (),
- &per_bfd->storage_obstack);
- else
- symbol_set_demangled_name (this, NULL, &per_bfd->storage_obstack);
+ symbol_set_demangled_name (this, (*slot)->demangled.get (),
+ &per_bfd->storage_obstack);
}
/* See symtab.h. */
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;
if (lookup_name.ignore_parameters () && lang == language_cplus)
{
gdb::unique_xmalloc_ptr<char> without_params
- = cp_remove_params_if_any (lookup_name.name ().c_str (),
+ = cp_remove_params_if_any (lookup_name.c_str (),
lookup_name.completion_mode ());
if (without_params != NULL)
}
if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
- m_demangled_name = lookup_name.name ();
+ m_demangled_name = lookup_name.c_str ();
else
- m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
+ m_demangled_name = demangle_for_lookup (lookup_name.c_str (),
lang, storage);
}
{
/* Lookup any symbol that "" would complete. I.e., this matches all
symbol names. */
- static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
+ static const lookup_name_info lookup_name ("", symbol_name_match_type::FULL,
true);
return lookup_name;
return result;
}
+/* Find the language for partial symbol with NAME. */
+
+static enum language
+find_quick_global_symbol_language (const char *name, const domain_enum domain)
+{
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ if (objfile->sf && objfile->sf->qf
+ && objfile->sf->qf->lookup_global_symbol_language)
+ continue;
+ return language_unknown;
+ }
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ bool symbol_found_p;
+ enum language lang
+ = objfile->sf->qf->lookup_global_symbol_language (objfile, name, domain,
+ &symbol_found_p);
+ if (!symbol_found_p)
+ continue;
+ return lang;
+ }
+
+ return language_unknown;
+}
+
/* Private data to be used with lookup_symbol_global_iterator_cb. */
struct global_or_static_sym_lookup_data
;
/* 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')
completion_list_add_name (tracker, sym->language (),
sym->natural_name (),
lookup_name, text, word);
+
+ /* C++ function symbols include the parameters within both the msymbol
+ name and the symbol name. The problem is that the msymbol name will
+ describe the parameters in the most basic way, with typedefs stripped
+ out, while the symbol name will represent the types as they appear in
+ the program. This means we will see duplicate entries in the
+ completion tracker. The following converts the symbol name back to
+ the msymbol name and removes the msymbol name from the completion
+ tracker. */
+ if (sym->language () == language_cplus
+ && SYMBOL_DOMAIN (sym) == VAR_DOMAIN
+ && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* The call to canonicalize returns the empty string if the input
+ string is already in canonical form, thanks to this we don't
+ remove the symbol we just added above. */
+ std::string str
+ = cp_canonicalize_string_no_typedefs (sym->natural_name ());
+ if (!str.empty ())
+ tracker.remove_completion (str.c_str ());
+ }
}
/* completion_list_add_name wrapper for struct minimal_symbol. */
/* The languages above didn't identify the name of the main procedure.
Fallback to "main". */
+
+ /* Try to find language for main in psymtabs. */
+ enum language lang
+ = find_quick_global_symbol_language ("main", VAR_DOMAIN);
+ if (lang != language_unknown)
+ {
+ set_main_name ("main", lang);
+ return;
+ }
+
set_main_name ("main", language_unknown);
}
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\