aboutsummaryrefslogtreecommitdiff
path: root/gdb/linespec.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r--gdb/linespec.c575
1 files changed, 268 insertions, 307 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7a1fbc2..b59c055 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1,6 +1,6 @@
/* Parser for linespec for the GNU debugger, GDB.
- Copyright (C) 1986-2024 Free Software Foundation, Inc.
+ Copyright (C) 1986-2025 Free Software Foundation, Inc.
This file is part of GDB.
@@ -23,7 +23,6 @@
#include "symfile.h"
#include "objfiles.h"
#include "source.h"
-#include "demangle.h"
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
@@ -34,7 +33,6 @@
#include "linespec.h"
#include "language.h"
#include "interps.h"
-#include "mi/mi-cmds.h"
#include "target.h"
#include "arch-utils.h"
#include <ctype.h>
@@ -47,6 +45,7 @@
#include "gdbsupport/def-vector.h"
#include <algorithm>
#include "inferior.h"
+#include "gdbsupport/unordered_set.h"
/* An enumeration of the various things a user might attempt to
complete for a linespec location. */
@@ -77,16 +76,6 @@ enum class linespec_complete_what
KEYWORD,
};
-/* An address entry is used to ensure that any given location is only
- added to the result a single time. It holds an address and the
- program space from which the address came. */
-
-struct address_entry
-{
- struct program_space *pspace;
- CORE_ADDR addr;
-};
-
/* A linespec. Elements of this structure are filled in by a parser
(either parse_linespec or some other function). The structure is
then converted into SALs by convert_linespec_to_sals. */
@@ -127,7 +116,7 @@ struct linespec
struct linespec_canonical_name
{
/* Remaining text part of the linespec string. */
- char *suffix;
+ std::string suffix;
/* If NULL then SUFFIX is the whole linespec string. */
struct symtab *symtab;
@@ -139,6 +128,37 @@ struct linespec_canonical_name
struct linespec_state
{
+ linespec_state (int flags, const language_defn *language,
+ program_space *pspace,
+ program_space *search_pspace,
+ symtab *default_symtab,
+ int default_line,
+ linespec_result *canonical)
+ : language (language),
+ program_space (pspace),
+ search_pspace (search_pspace),
+ default_symtab (default_symtab),
+ default_line (default_line),
+ funfirstline ((flags & DECODE_LINE_FUNFIRSTLINE) != 0),
+ list_mode ((flags & DECODE_LINE_LIST_MODE) != 0),
+ canonical (canonical)
+ {
+ }
+
+ linespec_state (const language_defn *language, program_space *program_space)
+ : linespec_state (0, language, program_space, nullptr, nullptr, 0, nullptr)
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (linespec_state);
+
+ /* Add ADDR to the address set. Return true if this is a new
+ entry. */
+ bool maybe_add_address (program_space *pspace, CORE_ADDR addr)
+ {
+ return addr_set.emplace (pspace, addr).second;
+ }
+
/* The language in use during linespec processing. */
const struct language_defn *language;
@@ -157,23 +177,30 @@ struct linespec_state
/* The 'funfirstline' value that was passed in to decode_line_1 or
decode_line_full. */
- int funfirstline;
+ bool funfirstline;
- /* Nonzero if we are running in 'list' mode; see decode_line_list. */
- int list_mode;
+ /* True if we are running in 'list' mode; see decode_line_list. */
+ bool list_mode;
/* The 'canonical' value passed to decode_line_full, or NULL. */
struct linespec_result *canonical;
/* Canonical strings that mirror the std::vector<symtab_and_line> result. */
- struct linespec_canonical_name *canonical_names;
+ std::vector<linespec_canonical_name> canonical_names;
+
+ /* Are we building a linespec? */
+ bool is_linespec = false;
+
+private:
+
+ /* An address entry is used to ensure that any given location is
+ only added to the result a single time. It holds an address and
+ the program space from which the address came. */
+ using address_entry = std::pair<::program_space *, CORE_ADDR>;
/* This is a set of address_entry objects which is used to prevent
duplicate symbols from being entered into the result. */
- htab_t addr_set;
-
- /* Are we building a linespec? */
- int is_linespec;
+ gdb::unordered_set<address_entry> addr_set;
};
/* This is a helper object that is used when collecting symbols into a
@@ -285,8 +312,6 @@ struct linespec_parser
int default_line,
struct linespec_result *canonical);
- ~linespec_parser ();
-
DISABLE_COPY_AND_ASSIGN (linespec_parser);
/* Lexer internal data */
@@ -303,10 +328,10 @@ struct linespec_parser
} lexer {};
/* Is the entire linespec quote-enclosed? */
- int is_quote_enclosed = 0;
+ bool is_quote_enclosed = false;
/* The state of the parse. */
- struct linespec_state state {};
+ linespec_state state;
/* The result of the parse. */
linespec result;
@@ -371,8 +396,8 @@ static struct line_offset
linespec_parse_variable (struct linespec_state *self,
const char *variable);
-static int symbol_to_sal (struct symtab_and_line *result,
- int funfirstline, struct symbol *sym);
+static bool symbol_to_sal (struct symtab_and_line *result,
+ bool funfirstline, struct symbol *sym);
static void add_matching_symbols_to_info (const char *name,
symbol_name_match_type name_match_type,
@@ -991,7 +1016,7 @@ linespec_lexer_consume_token (linespec_parser *parser)
if (*parser->lexer.stream != '\0')
{
parser->completion_quote_char = '\0';
- parser->completion_quote_end = NULL;;
+ parser->completion_quote_end = NULL;
}
}
@@ -1040,25 +1065,28 @@ linespec_lexer_peek_token (linespec_parser *parser)
the new sal, if needed. If not NULL, SYMNAME is the name of the
symbol to use when constructing the new canonical name.
- If LITERAL_CANONICAL is non-zero, SYMNAME will be used as the
+ If LITERAL_CANONICAL is true, SYMNAME will be used as the
canonical name for the SAL. */
static void
add_sal_to_sals (struct linespec_state *self,
std::vector<symtab_and_line> *sals,
struct symtab_and_line *sal,
- const char *symname, int literal_canonical)
+ const char *symname, bool literal_canonical)
{
+ /* We don't want two SALs with the same PC from the
+ same program space. */
+ for (const auto &s : *sals)
+ if (sal->pc == s.pc && sal->pspace == s.pspace)
+ return;
+
sals->push_back (*sal);
if (self->canonical)
{
- struct linespec_canonical_name *canonical;
+ linespec_canonical_name &canonical
+ = self->canonical_names.emplace_back ();
- self->canonical_names = XRESIZEVEC (struct linespec_canonical_name,
- self->canonical_names,
- sals->size ());
- canonical = &self->canonical_names[sals->size () - 1];
if (!literal_canonical && sal->symtab)
{
symtab_to_fullname (sal->symtab);
@@ -1068,71 +1096,25 @@ add_sal_to_sals (struct linespec_state *self,
the time being. */
if (symname != NULL && sal->line != 0
&& self->language->la_language == language_ada)
- canonical->suffix = xstrprintf ("%s:%d", symname,
- sal->line).release ();
+ canonical.suffix = string_printf ("%s:%d", symname,
+ sal->line);
else if (symname != NULL)
- canonical->suffix = xstrdup (symname);
+ canonical.suffix = symname;
else
- canonical->suffix = xstrprintf ("%d", sal->line).release ();
- canonical->symtab = sal->symtab;
+ canonical.suffix = string_printf ("%d", sal->line);
+ canonical.symtab = sal->symtab;
}
else
{
if (symname != NULL)
- canonical->suffix = xstrdup (symname);
+ canonical.suffix = symname;
else
- canonical->suffix = xstrdup ("<unknown>");
- canonical->symtab = NULL;
+ canonical.suffix = "<unknown>";
+ canonical.symtab = NULL;
}
}
}
-/* A hash function for address_entry. */
-
-static hashval_t
-hash_address_entry (const void *p)
-{
- const struct address_entry *aep = (const struct address_entry *) p;
- hashval_t hash;
-
- hash = iterative_hash_object (aep->pspace, 0);
- return iterative_hash_object (aep->addr, hash);
-}
-
-/* An equality function for address_entry. */
-
-static int
-eq_address_entry (const void *a, const void *b)
-{
- const struct address_entry *aea = (const struct address_entry *) a;
- const struct address_entry *aeb = (const struct address_entry *) b;
-
- return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
-}
-
-/* Check whether the address, represented by PSPACE and ADDR, is
- already in the set. If so, return 0. Otherwise, add it and return
- 1. */
-
-static int
-maybe_add_address (htab_t set, struct program_space *pspace, CORE_ADDR addr)
-{
- struct address_entry e, *p;
- void **slot;
-
- e.pspace = pspace;
- e.addr = addr;
- slot = htab_find_slot (set, &e, INSERT);
- if (*slot)
- return 0;
-
- p = XNEW (struct address_entry);
- memcpy (p, &e, sizeof (struct address_entry));
- *slot = p;
-
- return 1;
-}
-
/* A helper that walks over all matching symtabs in all objfiles and
calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is
not NULL, then the search is restricted to just that program
@@ -1156,7 +1138,7 @@ iterate_over_all_matching_symtabs
set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
objfile->expand_symtabs_matching (NULL, &lookup_name, NULL, NULL,
(SEARCH_GLOBAL_BLOCK
@@ -1323,7 +1305,7 @@ canonical_to_fullform (const struct linespec_canonical_name *canonical)
return canonical->suffix;
else
return string_printf ("%s:%s", symtab_to_fullname (canonical->symtab),
- canonical->suffix);
+ canonical->suffix.c_str ());
}
/* Given FILTERS, a list of canonical names, filter the sals in RESULT
@@ -1388,29 +1370,24 @@ struct decode_line_2_item
{
}
+ /* Used for sorting. */
+ bool operator< (const decode_line_2_item &other) const
+ {
+ if (displayform != other.displayform)
+ return displayform < other.displayform;
+ return fullform < other.fullform;
+ }
+
/* The form using symtab_to_fullname. */
std::string fullform;
/* The form using symtab_to_filename_for_display. */
std::string displayform;
- /* Field is initialized to zero and it is set to one if the user
- requested breakpoint for this entry. */
- unsigned int selected : 1;
+ /* True if the user requested breakpoint for this entry. */
+ bool selected;
};
-/* Helper for std::sort to sort decode_line_2_item entries by
- DISPLAYFORM and secondarily by FULLFORM. */
-
-static bool
-decode_line_2_compare_items (const decode_line_2_item &a,
- const decode_line_2_item &b)
-{
- if (a.displayform != b.displayform)
- return a.displayform < b.displayform;
- return a.fullform < b.fullform;
-}
-
/* Handle multiple results in RESULT depending on SELECT_MODE. This
will either return normally, throw an exception on multiple
results, or present a menu to the user. On return, the SALS vector
@@ -1438,7 +1415,6 @@ decode_line_2 (struct linespec_state *self,
std::string displayform;
canonical = &self->canonical_names[i];
- gdb_assert (canonical->suffix != NULL);
std::string fullform = canonical_to_fullform (canonical);
@@ -1450,7 +1426,7 @@ decode_line_2 (struct linespec_state *self,
fn_for_display = symtab_to_filename_for_display (canonical->symtab);
displayform = string_printf ("%s:%s", fn_for_display,
- canonical->suffix);
+ canonical->suffix.c_str ());
}
items.emplace_back (std::move (fullform), std::move (displayform),
@@ -1458,7 +1434,7 @@ decode_line_2 (struct linespec_state *self,
}
/* Sort the list of method names. */
- std::sort (items.begin (), items.end (), decode_line_2_compare_items);
+ std::sort (items.begin (), items.end ());
/* Remove entries with the same FULLFORM. */
items.erase (std::unique (items.begin (), items.end (),
@@ -1524,7 +1500,7 @@ decode_line_2 (struct linespec_state *self,
if (!item->selected)
{
filters.push_back (item->fullform.c_str ());
- item->selected = 1;
+ item->selected = true;
}
else
{
@@ -1544,15 +1520,15 @@ decode_line_2 (struct linespec_state *self,
/* Throw an appropriate error when SYMBOL is not found (optionally in
FILENAME). */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
symbol_not_found_error (const char *symbol, const char *filename)
{
if (symbol == NULL)
symbol = "";
- if (!have_full_symbols ()
- && !have_partial_symbols ()
- && !have_minimal_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space)
+ && !have_minimal_symbols (current_program_space))
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. Use the \"file\" command."));
@@ -1586,7 +1562,7 @@ symbol_not_found_error (const char *symbol, const char *filename)
/* Throw an appropriate error when an unexpected token is encountered
in the input. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
unexpected_linespec_error (linespec_parser *parser)
{
linespec_token token;
@@ -1613,7 +1589,7 @@ unexpected_linespec_error (linespec_parser *parser)
/* Throw an undefined label error. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
undefined_label_error (const char *function, const char *label)
{
if (function != NULL)
@@ -1628,7 +1604,7 @@ undefined_label_error (const char *function, const char *label)
/* Throw a source file not found error. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
source_file_not_found_error (const char *name)
{
throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
@@ -2015,7 +1991,7 @@ static std::vector<symtab_and_line>
create_sals_line_offset (struct linespec_state *self,
linespec *ls)
{
- int use_default = 0;
+ bool use_default = false;
/* This is where we need to make sure we have good defaults.
We must guarantee that this section of code is never executed
@@ -2034,7 +2010,7 @@ create_sals_line_offset (struct linespec_state *self,
ls->file_symtabs
= collect_symtabs_from_filename (self->default_symtab->filename,
self->search_pspace);
- use_default = 1;
+ use_default = true;
}
symtab_and_line val;
@@ -2069,12 +2045,19 @@ create_sals_line_offset (struct linespec_state *self,
const linetable_entry *best_entry = NULL;
int i, j;
+ /* True if the provided line gave an exact match. False if we had to
+ search for the next following line with code. */
+ bool was_exact = true;
+
std::vector<symtab_and_line> intermediate_results
= decode_digits_ordinary (self, ls, val.line, &best_entry);
if (intermediate_results.empty () && best_entry != NULL)
- intermediate_results = decode_digits_ordinary (self, ls,
- best_entry->line,
- &best_entry);
+ {
+ was_exact = false;
+ intermediate_results = decode_digits_ordinary (self, ls,
+ best_entry->line,
+ &best_entry);
+ }
/* For optimized code, the compiler can scatter one source line
across disjoint ranges of PC values, even when no duplicate
@@ -2117,22 +2100,58 @@ create_sals_line_offset (struct linespec_state *self,
struct symbol *sym = (blocks[i]
? blocks[i]->containing_function ()
: NULL);
+ symtab_and_line &sal = intermediate_results[i];
+
+ /* Don't consider a match if:
+
+ - the provided line did not give an exact match (so we
+ started looking for lines below until we found one with
+ code associated to it)
+ - the found location is exactly the start of a function
+ - the provided line is above the declaration line of the
+ function
+
+ Consider the following source:
+
+ 10 } // end of a previous function
+ 11
+ 12 int
+ 13 main (void)
+ 14 {
+ 15 int i = 1;
+ 16
+ 17 return 0;
+ 18 }
+
+ The intent of this heuristic is that a breakpoint requested on
+ line 11 and 12 will not result in a breakpoint on main, but a
+ breakpoint on line 13 will. A breakpoint requested on the empty
+ line 16 will also result in a breakpoint in main, at line 17. */
+ if (!was_exact
+ && sym != nullptr
+ && sym->aclass () == LOC_BLOCK
+ && sal.pc == sym->value_block ()->entry_pc ()
+ && val.line < sym->line ())
+ continue;
if (self->funfirstline)
- skip_prologue_sal (&intermediate_results[i]);
- intermediate_results[i].symbol = sym;
- add_sal_to_sals (self, &values, &intermediate_results[i],
- sym ? sym->natural_name () : NULL, 0);
+ skip_prologue_sal (&sal);
+
+ sal.symbol = sym;
+ add_sal_to_sals (self, &values, &sal,
+ sym ? sym->natural_name () : nullptr, false);
}
}
if (values.empty ())
{
if (ls->explicit_loc.source_filename)
- throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
+ throw_error (NOT_FOUND_ERROR,
+ _("No compiled code for line %d in file \"%s\"."),
val.line, ls->explicit_loc.source_filename.get ());
else
- throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
+ throw_error (NOT_FOUND_ERROR,
+ _("No compiled code for line %d in the current file."),
val.line);
}
@@ -2152,7 +2171,7 @@ convert_address_location_to_sals (struct linespec_state *self,
sal.symbol = find_pc_sect_containing_function (sal.pc, sal.section);
std::vector<symtab_and_line> sals;
- add_sal_to_sals (self, &sals, &sal, core_addr_to_string (address), 1);
+ add_sal_to_sals (self, &sals, &sal, core_addr_to_string (address), true);
return sals;
}
@@ -2172,12 +2191,12 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &sym : ls->labels.label_symbols)
{
struct program_space *pspace
- = sym.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ = sym.symbol->symtab ()->compunit ()->objfile ()->pspace ();
if (symbol_to_sal (&sal, state->funfirstline, sym.symbol)
- && maybe_add_address (state->addr_set, pspace, sal.pc))
+ && state->maybe_add_address (pspace, sal.pc))
add_sal_to_sals (state, &sals, &sal,
- sym.symbol->natural_name (), 0);
+ sym.symbol->natural_name (), false);
}
}
else if (!ls->function_symbols.empty () || !ls->minimal_symbols.empty ())
@@ -2194,7 +2213,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &sym : ls->function_symbols)
{
program_space *pspace
- = sym.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ = sym.symbol->symtab ()->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
/* Don't skip to the first line of the function if we
@@ -2240,9 +2259,9 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
{
symtab_and_line sal;
if (symbol_to_sal (&sal, state->funfirstline, sym.symbol)
- && maybe_add_address (state->addr_set, pspace, sal.pc))
+ && state->maybe_add_address (pspace, sal.pc))
add_sal_to_sals (state, &sals, &sal,
- sym.symbol->natural_name (), 0);
+ sym.symbol->natural_name (), false);
}
}
}
@@ -2256,7 +2275,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &elem : ls->minimal_symbols)
{
- program_space *pspace = elem.objfile->pspace;
+ program_space *pspace = elem.objfile->pspace ();
set_current_program_space (pspace);
minsym_found (state, elem.objfile, elem.minsym, &sals);
}
@@ -2447,7 +2466,7 @@ parse_linespec (linespec_parser *parser, const char *arg,
/* A special case to start. It has become quite popular for
IDEs to work around bugs in the previous parser by quoting
the entire linespec, so we attempt to deal with this nicely. */
- parser->is_quote_enclosed = 0;
+ parser->is_quote_enclosed = false;
if (parser->completion_tracker == NULL
&& !is_ada_operator (arg)
&& *arg != '\0'
@@ -2459,7 +2478,7 @@ parse_linespec (linespec_parser *parser, const char *arg,
/* Here's the special case. Skip ARG past the initial
quote. */
++arg;
- parser->is_quote_enclosed = 1;
+ parser->is_quote_enclosed = true;
}
}
@@ -2629,30 +2648,6 @@ parse_linespec (linespec_parser *parser, const char *arg,
}
-/* A constructor for linespec_state. */
-
-static void
-linespec_state_constructor (struct linespec_state *self,
- int flags, const struct language_defn *language,
- struct program_space *search_pspace,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical)
-{
- memset (self, 0, sizeof (*self));
- self->language = language;
- self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
- self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
- self->search_pspace = search_pspace;
- self->default_symtab = default_symtab;
- self->default_line = default_line;
- self->canonical = canonical;
- self->program_space = current_program_space;
- self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
- xfree, xcalloc, xfree);
- self->is_linespec = 0;
-}
-
/* Initialize a new linespec parser. */
linespec_parser::linespec_parser (int flags,
@@ -2661,30 +2656,13 @@ linespec_parser::linespec_parser (int flags,
struct symtab *default_symtab,
int default_line,
struct linespec_result *canonical)
+ : state (flags, language, current_program_space, search_pspace,
+ default_symtab, default_line, canonical)
{
lexer.current.type = LSTOKEN_CONSUMED;
result.explicit_loc.func_name_match_type
= symbol_name_match_type::WILD;
result.explicit_loc.line_offset.sign = LINE_OFFSET_UNKNOWN;
- linespec_state_constructor (&state, flags, language,
- search_pspace,
- default_symtab, default_line, canonical);
-}
-
-/* A destructor for linespec_state. */
-
-static void
-linespec_state_destructor (struct linespec_state *self)
-{
- htab_delete (self->addr_set);
- xfree (self->canonical_names);
-}
-
-/* Delete a linespec parser. */
-
-linespec_parser::~linespec_parser ()
-{
- linespec_state_destructor (&state);
}
/* See description in linespec.h. */
@@ -2870,7 +2848,7 @@ linespec_complete (completion_tracker &tracker, const char *text,
parser.lexer.stream = text;
parser.completion_tracker = &tracker;
- parser.state.is_linespec = 1;
+ parser.state.is_linespec = true;
/* Parse as much as possible. parser.completion_word will hold
furthest completion point we managed to parse to. */
@@ -3061,7 +3039,7 @@ location_spec_to_sals (linespec_parser *parser,
case LINESPEC_LOCATION_SPEC:
{
const linespec_location_spec *ls = as_linespec_location_spec (locspec);
- parser->state.is_linespec = 1;
+ parser->state.is_linespec = true;
result = parse_linespec (parser, ls->spec_string.get (),
ls->match_type);
}
@@ -3148,14 +3126,6 @@ decode_line_full (struct location_spec *locspec, int flags,
gdb_assert (result.size () == 1 || canonical->pre_expanded);
canonical->pre_expanded = 1;
- /* Arrange for allocated canonical names to be freed. */
- std::vector<gdb::unique_xmalloc_ptr<char>> hold_names;
- for (int i = 0; i < result.size (); ++i)
- {
- gdb_assert (state->canonical_names[i].suffix != NULL);
- hold_names.emplace_back (state->canonical_names[i].suffix);
- }
-
if (select_mode == NULL)
{
if (top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
@@ -3205,7 +3175,8 @@ decode_line_with_current_source (const char *string, int flags)
/* We use whatever is set as the current source line. We do not try
and get a default source symtab+line or it will recursively call us! */
- symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
location_spec_up locspec = string_to_location_spec (&string,
current_language);
@@ -3255,9 +3226,9 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
/* Use whatever we have for the default source line. We don't use
get_current_or_default_symtab_and_line as it can recurse and call
us back! */
- struct symtab_and_line cursal =
- get_current_source_symtab_and_line ();
-
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
+
*default_symtab = cursal.symtab;
*default_line = cursal.line;
}
@@ -3362,12 +3333,9 @@ namespace {
class decode_compound_collector
{
public:
- decode_compound_collector ()
- : m_unique_syms (htab_create_alloc (1, htab_hash_pointer,
- htab_eq_pointer, NULL,
- xcalloc, xfree))
- {
- }
+ decode_compound_collector () = default;
+
+ DISABLE_COPY_AND_ASSIGN (decode_compound_collector);
/* Return all symbols collected. */
std::vector<block_symbol> release_symbols ()
@@ -3381,7 +3349,7 @@ public:
private:
/* A hash table of all symbols we found. We use this to avoid
adding any symbol more than once. */
- htab_up m_unique_syms;
+ gdb::unordered_set<const symbol *> m_unique_syms;
/* The result vector. */
std::vector<block_symbol> m_symbols;
@@ -3390,7 +3358,6 @@ private:
bool
decode_compound_collector::operator () (block_symbol *bsym)
{
- void **slot;
struct type *t;
struct symbol *sym = bsym->symbol;
@@ -3404,12 +3371,8 @@ decode_compound_collector::operator () (block_symbol *bsym)
&& t->code () != TYPE_CODE_NAMESPACE)
return true; /* Continue iterating. */
- slot = htab_find_slot (m_unique_syms.get (), sym, INSERT);
- if (!*slot)
- {
- *slot = sym;
- m_symbols.push_back (*bsym);
- }
+ if (m_unique_syms.insert (sym).second)
+ m_symbols.push_back (*bsym);
return true; /* Continue iterating. */
}
@@ -3437,7 +3400,7 @@ lookup_prefix_sym (struct linespec_state *state,
{
/* Program spaces that are executing startup should have
been filtered out earlier. */
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
gdb_assert (!pspace->executing_startup);
set_current_program_space (pspace);
@@ -3450,30 +3413,52 @@ lookup_prefix_sym (struct linespec_state *state,
return collector.release_symbols ();
}
-/* A std::sort comparison function for symbols. The resulting order does
- not actually matter; we just need to be able to sort them so that
- symbols with the same program space end up next to each other. */
+/* Compare pspace A and B based on program space ID. Return 0 if equal,
+ 1 if A->num > B->num, -1 otherwise (modeled on strcmp). */
-static bool
-compare_symbols (const block_symbol &a, const block_symbol &b)
+static int
+compare_pspace (const struct program_space *a, const struct program_space *b)
{
- uintptr_t uia, uib;
+ if (a->num > b->num)
+ return 1;
- uia = (uintptr_t) a.symbol->symtab ()->compunit ()->objfile ()->pspace;
- uib = (uintptr_t) b.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ if (a->num < b->num)
+ return -1;
- if (uia < uib)
- return true;
- if (uia > uib)
- return false;
+ return 0;
+}
- uia = (uintptr_t) a.symbol;
- uib = (uintptr_t) b.symbol;
+/* An std::sort comparison function for pointers. Don't use this if stable
+ sorting results are required. */
+
+static bool
+compare_pointers (void *a, void *b)
+{
+ return (uintptr_t)a < (uintptr_t)b;
+}
+
+/* An std::sort comparison function for symbols. The requirement is that
+ symbols with the same program space end up next to each other. This is for
+ the purpose of iterating over the symbols and doing something once for each
+ program space. */
- if (uia < uib)
+static bool
+compare_symbols (const block_symbol &a, const block_symbol &b)
+{
+ /* To check for same program space, we could just use a pointer comparison,
+ which gives unstable sorting results. While the assumption is that this
+ doesn't matter, play it safe and compare program space IDs instead. */
+ int cmp
+ = compare_pspace (a.symbol->symtab ()->compunit ()->objfile ()->pspace (),
+ b.symbol->symtab ()->compunit ()->objfile ()->pspace ());
+ if (cmp == -1)
return true;
+ if (cmp == 1)
+ return false;
- return false;
+ /* This gives unstable sorting results. We assume that this doesn't
+ matter. */
+ return compare_pointers (a.symbol, b.symbol);
}
/* Like compare_symbols but for minimal symbols. */
@@ -3481,23 +3466,16 @@ compare_symbols (const block_symbol &a, const block_symbol &b)
static bool
compare_msymbols (const bound_minimal_symbol &a, const bound_minimal_symbol &b)
{
- uintptr_t uia, uib;
-
- uia = (uintptr_t) a.objfile->pspace;
- uib = (uintptr_t) a.objfile->pspace;
-
- if (uia < uib)
+ /* See comment in compare_symbols for use of compare_pspace. */
+ int cmp = compare_pspace (a.objfile->pspace (), a.objfile->pspace ());
+ if (cmp == -1)
return true;
- if (uia > uib)
+ if (cmp == 1)
return false;
- uia = (uintptr_t) a.minsym;
- uib = (uintptr_t) b.minsym;
-
- if (uia < uib)
- return true;
-
- return false;
+ /* This gives unstable sorting results. We assume that this doesn't
+ matter. */
+ return compare_pointers (a.minsym, b.minsym);
}
/* Look for all the matching instances of each symbol in NAMES. Only
@@ -3584,7 +3562,7 @@ find_method (struct linespec_state *self,
/* Program spaces that are executing startup should have
been filtered out earlier. */
- pspace = sym->symtab ()->compunit ()->objfile ()->pspace;
+ pspace = sym->symtab ()->compunit ()->objfile ()->pspace ();
gdb_assert (!pspace->executing_startup);
set_current_program_space (pspace);
t = check_typedef (sym->type ());
@@ -3596,7 +3574,7 @@ find_method (struct linespec_state *self,
if (ix == sym_classes->size () - 1
|| (pspace
!= (sym_classes->at (ix + 1).symbol->symtab ()
- ->compunit ()->objfile ()->pspace)))
+ ->compunit ()->objfile ()->pspace ())))
{
/* If we did not find a direct implementation anywhere in
this program space, consider superclasses. */
@@ -3633,14 +3611,18 @@ namespace {
class symtab_collector
{
public:
- symtab_collector ()
- : m_symtab_table (htab_create (1, htab_hash_pointer, htab_eq_pointer,
- NULL))
- {
- }
+ symtab_collector () = default;
+
+ DISABLE_COPY_AND_ASSIGN (symtab_collector);
/* Callable as a symbol_found_callback_ftype callback. */
- bool operator () (symtab *sym);
+ bool operator () (struct symtab *symtab)
+ {
+ if (m_symtab_table.insert (symtab).second)
+ m_symtabs.push_back (symtab);
+
+ return false;
+ }
/* Return an rvalue reference to the collected symtabs. */
std::vector<symtab *> &&release_symtabs ()
@@ -3653,24 +3635,9 @@ private:
std::vector<symtab *> m_symtabs;
/* This is used to ensure the symtabs are unique. */
- htab_up m_symtab_table;
+ gdb::unordered_set<const symtab *> m_symtab_table;
};
-bool
-symtab_collector::operator () (struct symtab *symtab)
-{
- void **slot;
-
- slot = htab_find_slot (m_symtab_table.get (), symtab, INSERT);
- if (!*slot)
- {
- *slot = symtab;
- m_symtabs.push_back (symtab);
- }
-
- return false;
-}
-
} // namespace
/* Given a file name, return a list of all matching symtabs. If
@@ -3691,15 +3658,11 @@ collect_symtabs_from_filename (const char *file,
if (pspace->executing_startup)
continue;
- set_current_program_space (pspace);
- iterate_over_symtabs (file, collector);
+ iterate_over_symtabs (pspace, file, collector);
}
}
else
- {
- set_current_program_space (search_pspace);
- iterate_over_symtabs (file, collector);
- }
+ iterate_over_symtabs (search_pspace, file, collector);
return collector.release_symtabs ();
}
@@ -3716,7 +3679,8 @@ symtabs_from_filename (const char *filename,
if (result.empty ())
{
- if (!have_full_symbols () && !have_partial_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. "
"Use the \"file\" command."));
@@ -3736,10 +3700,8 @@ symbol_searcher::find_all_symbols (const std::string &name,
struct program_space *search_pspace)
{
symbol_searcher_collect_info info;
- struct linespec_state state;
+ linespec_state state (language, current_program_space);
- memset (&state, 0, sizeof (state));
- state.language = language;
info.state = &state;
info.result.symbols = &m_symbols;
@@ -3963,7 +3925,7 @@ find_label_symbols (struct linespec_state *self,
{
fn_sym = elt.symbol;
set_current_program_space
- (fn_sym->symtab ()->compunit ()->objfile ()->pspace);
+ (fn_sym->symtab ()->compunit ()->objfile ()->pspace ());
block = fn_sym->value_block ();
find_label_symbols_in_block (block, name, fn_sym, completion_mode,
@@ -3992,18 +3954,18 @@ decode_digits_list_mode (struct linespec_state *self,
/* The logic above should ensure this. */
gdb_assert (elt != NULL);
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
/* Simplistic search just for the list command. */
- val.symtab = find_line_symtab (elt, val.line, NULL, NULL);
+ val.symtab = find_line_symtab (elt, val.line, nullptr);
if (val.symtab == NULL)
val.symtab = elt;
val.pspace = pspace;
val.pc = 0;
val.explicit_line = true;
- add_sal_to_sals (self, &values, &val, NULL, 0);
+ add_sal_to_sals (self, &values, &val, NULL, false);
}
return values;
@@ -4027,7 +3989,7 @@ decode_digits_ordinary (struct linespec_state *self,
/* The logic above should ensure this. */
gdb_assert (elt != NULL);
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
pcs = find_pcs_for_symtab_line (elt, line, best_entry);
@@ -4153,8 +4115,8 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
sal.section = msymbol->obj_section (objfile);
- if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
- add_sal_to_sals (self, result, &sal, msymbol->natural_name (), 0);
+ if (self->maybe_add_address (objfile->pspace (), sal.pc))
+ add_sal_to_sals (self, result, &sal, msymbol->natural_name (), false);
}
/* Helper for search_minsyms_for_name that adds the symbol to the
@@ -4162,8 +4124,8 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
static void
add_minsym (struct minimal_symbol *minsym, struct objfile *objfile,
- struct symtab *symtab, int list_mode,
- std::vector<struct bound_minimal_symbol> *msyms)
+ struct symtab *symtab, bool list_mode,
+ std::vector<bound_minimal_symbol> *msyms)
{
if (symtab != NULL)
{
@@ -4180,11 +4142,8 @@ add_minsym (struct minimal_symbol *minsym, struct objfile *objfile,
}
/* Exclude data symbols when looking for breakpoint locations. */
- if (!list_mode && !msymbol_is_function (objfile, minsym))
- return;
-
- msyms->emplace_back (minsym, objfile);
- return;
+ if (list_mode || msymbol_is_function (objfile, minsym))
+ msyms->emplace_back (minsym, objfile);
}
/* Search for minimal symbols called NAME. If SEARCH_PSPACE
@@ -4200,7 +4159,7 @@ search_minsyms_for_name (struct collect_info *info,
struct program_space *search_pspace,
struct symtab *symtab)
{
- std::vector<struct bound_minimal_symbol> minsyms;
+ std::vector<bound_minimal_symbol> minsyms;
if (symtab == NULL)
{
@@ -4213,7 +4172,7 @@ search_minsyms_for_name (struct collect_info *info,
set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
iterate_over_minimal_symbols (objfile, name,
[&] (struct minimal_symbol *msym)
@@ -4228,7 +4187,7 @@ search_minsyms_for_name (struct collect_info *info,
}
else
{
- program_space *pspace = symtab->compunit ()->objfile ()->pspace;
+ program_space *pspace = symtab->compunit ()->objfile ()->pspace ();
if (search_pspace == NULL || pspace == search_pspace)
{
@@ -4311,6 +4270,11 @@ add_matching_symbols_to_info (const char *name,
{
lookup_name_info lookup_name (name, name_match_type);
+ auto add_symbol = [&] (block_symbol *bsym)
+ {
+ return info->add_symbol (bsym);
+ };
+
for (const auto &elt : *info->file_symtabs)
{
if (elt == nullptr)
@@ -4318,22 +4282,19 @@ add_matching_symbols_to_info (const char *name,
iterate_over_all_matching_symtabs (info->state, lookup_name,
domain_search_flags,
pspace, true,
- [&] (block_symbol *bsym)
- { return info->add_symbol (bsym); });
+ add_symbol);
search_minsyms_for_name (info, lookup_name, pspace, NULL);
}
- else if (pspace == NULL || pspace == elt->compunit ()->objfile ()->pspace)
+ else if (pspace == NULL || pspace == elt->compunit ()->objfile ()->pspace ())
{
int prev_len = info->result.symbols->size ();
/* Program spaces that are executing startup should have
been filtered out earlier. */
- program_space *elt_pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *elt_pspace = elt->compunit ()->objfile ()->pspace ();
gdb_assert (!elt_pspace->executing_startup);
set_current_program_space (elt_pspace);
- iterate_over_file_blocks (elt, lookup_name, SEARCH_VFT,
- [&] (block_symbol *bsym)
- { return info->add_symbol (bsym); });
+ iterate_over_file_blocks (elt, lookup_name, SEARCH_VFT, add_symbol);
/* If no new symbols were found in this iteration and this symtab
is in assembler, we might actually be looking for a label for
@@ -4351,14 +4312,14 @@ add_matching_symbols_to_info (const char *name,
/* Now come some functions that are called from multiple places within
decode_line_1. */
-static int
+static bool
symbol_to_sal (struct symtab_and_line *result,
- int funfirstline, struct symbol *sym)
+ bool funfirstline, struct symbol *sym)
{
if (sym->aclass () == LOC_BLOCK)
{
*result = find_function_start_sal (sym, funfirstline);
- return 1;
+ return true;
}
else
{
@@ -4369,9 +4330,9 @@ symbol_to_sal (struct symtab_and_line *result,
result->symbol = sym;
result->line = sym->line ();
result->pc = sym->value_address ();
- result->pspace = result->symtab->compunit ()->objfile ()->pspace;
+ result->pspace = result->symtab->compunit ()->objfile ()->pspace ();
result->explicit_pc = 1;
- return 1;
+ return true;
}
else if (funfirstline)
{
@@ -4385,12 +4346,12 @@ symbol_to_sal (struct symtab_and_line *result,
result->symbol = sym;
result->line = sym->line ();
result->pc = sym->value_address ();
- result->pspace = result->symtab->compunit ()->objfile ()->pspace;
- return 1;
+ result->pspace = result->symtab->compunit ()->objfile ()->pspace ();
+ return true;
}
}
- return 0;
+ return false;
}
linespec_result::~linespec_result ()