/* Partial symbol tables.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "cp-support.h"
#include "gdbcmd.h"
#include <algorithm>
+#include <set>
struct psymbol_bcache
{
struct partial_symtab *,
int,
const char *, domain_enum,
- symbol_compare_ftype *,
+ symbol_name_match_type,
symbol_compare_ftype *);
static struct partial_symbol *lookup_partial_symbol (struct objfile *,
const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
struct compunit_symtab *stab_best = NULL;
+ lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
{
if (!ps->readin && lookup_partial_symbol (objfile, ps, name,
information (but NAME might contain it). */
if (sym != NULL
- && SYMBOL_MATCHES_SEARCH_NAME (sym, name))
+ && SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
return stab;
if (with_opaque != NULL
- && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, name))
+ && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, lookup_name))
stab_best = stab;
/* Keep looking through other psymtabs. */
return stab_best;
}
+/* Returns true if PSYM matches LOOKUP_NAME. */
+
+static bool
+psymbol_name_matches (partial_symbol *psym,
+ const lookup_name_info &lookup_name)
+{
+ const language_defn *lang = language_def (SYMBOL_LANGUAGE (psym));
+ symbol_name_matcher_ftype *name_match
+ = get_symbol_name_matcher (lang, lookup_name);
+ return name_match (SYMBOL_SEARCH_NAME (psym), lookup_name, NULL);
+}
+
/* Look in PST for a symbol in DOMAIN whose name matches NAME. Search
the global block of PST if GLOBAL, and otherwise the static block.
MATCH is the comparison operation that returns true iff MATCH (s,
match_partial_symbol (struct objfile *objfile,
struct partial_symtab *pst, int global,
const char *name, domain_enum domain,
- symbol_compare_ftype *match,
+ symbol_name_match_type match_type,
symbol_compare_ftype *ordered_compare)
{
struct partial_symbol **start, **psym;
int do_linear_search = 1;
if (length == 0)
- return NULL;
+ return NULL;
+
+ lookup_name_info lookup_name (name, match_type);
+
start = (global ?
&objfile->global_psymbols[pst->globals_offset] :
&objfile->static_psymbols[pst->statics_offset]);
{
center = bottom + (top - bottom) / 2;
gdb_assert (center < top);
- if (ordered_compare (SYMBOL_SEARCH_NAME (*center), name) >= 0)
+
+ enum language lang = SYMBOL_LANGUAGE (*center);
+ const char *lang_ln
+ = lookup_name.language_lookup_name (lang).c_str ();
+
+ if (ordered_compare (SYMBOL_SEARCH_NAME (*center), lang_ln) >= 0)
top = center;
else
bottom = center + 1;
gdb_assert (top == bottom);
while (top <= real_top
- && match (SYMBOL_SEARCH_NAME (*top), name) == 0)
+ && psymbol_name_matches (*top, lookup_name))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
SYMBOL_DOMAIN (*top), domain))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
SYMBOL_DOMAIN (*psym), domain)
- && match (SYMBOL_SEARCH_NAME (*psym), name) == 0)
+ && psymbol_name_matches (*psym, lookup_name))
return *psym;
}
}
return NULL;
gdb::unique_xmalloc_ptr<char> search_name = psymtab_search_name (name);
+
+ lookup_name_info lookup_name (search_name.get (), symbol_name_match_type::FULL);
+
start = (global ?
&objfile->global_psymbols[pst->globals_offset] :
&objfile->static_psymbols[pst->statics_offset]);
/* For `case_sensitivity == case_sensitive_off' strcmp_iw_ordered will
search more exactly than what matches SYMBOL_MATCHES_SEARCH_NAME. */
- while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top,
- search_name.get ()))
+ while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top, lookup_name))
top--;
/* Fixup to have a symbol which matches SYMBOL_MATCHES_SEARCH_NAME. */
top++;
- while (top <= real_top
- && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name.get ()))
+ while (top <= real_top && SYMBOL_MATCHES_SEARCH_NAME (*top, lookup_name))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
SYMBOL_DOMAIN (*top), domain))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
SYMBOL_DOMAIN (*psym), domain)
- && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name.get ()))
+ && SYMBOL_MATCHES_SEARCH_NAME (*psym, lookup_name))
return *psym;
}
}
const struct section_offsets *new_offsets,
const struct section_offsets *delta)
{
- struct partial_symbol **psym;
struct partial_symtab *p;
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
if (SYMBOL_SECTION (psym) >= 0)
SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
}
+
+ objfile->psymbol_map.clear ();
}
/* Psymtab version of find_last_source_symtab. See its definition in
to handle cases like the file being moved. */
if (ps->fullname == NULL)
{
- int fd = find_and_open_source (ps->filename, ps->dirname, &ps->fullname);
+ gdb::unique_xmalloc_ptr<char> fullname;
+ int fd = find_and_open_source (ps->filename, ps->dirname, &fullname);
+ ps->fullname = fullname.release ();
if (fd >= 0)
close (fd);
else
{
- gdb::unique_xmalloc_ptr<char> fullname;
-
/* rewrite_source_path would be applied by find_and_open_source, we
should report the pathname where GDB tried to find the file. */
map_block (const char *name, domain_enum domain, struct objfile *objfile,
struct block *block,
int (*callback) (struct block *, struct symbol *, void *),
- void *data, symbol_compare_ftype *match)
+ void *data, symbol_name_match_type match)
{
struct block_iterator iter;
struct symbol *sym;
- for (sym = block_iter_match_first (block, name, match, &iter);
- sym != NULL; sym = block_iter_match_next (name, match, &iter))
+ lookup_name_info lookup_name (name, match);
+
+ for (sym = block_iter_match_first (block, lookup_name, &iter);
+ sym != NULL;
+ sym = block_iter_match_next (lookup_name, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
int (*callback) (struct block *,
struct symbol *, void *),
void *data,
- symbol_compare_ftype *match,
+ symbol_name_match_type match,
symbol_compare_ftype *ordered_compare)
{
const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
static bool
recursively_search_psymtabs
- (struct partial_symtab *ps, struct objfile *objfile, enum search_domain kind,
+ (struct partial_symtab *ps, struct objfile *objfile, enum search_domain domain,
+ const lookup_name_info &lookup_name,
gdb::function_view<expand_symtabs_symbol_matcher_ftype> sym_matcher)
{
int keep_going = 1;
continue;
r = recursively_search_psymtabs (ps->dependencies[i],
- objfile, kind, sym_matcher);
+ objfile, domain, lookup_name,
+ sym_matcher);
if (r != 0)
{
ps->searched_flag = PST_SEARCHED_AND_FOUND;
}
partial_symbol **gbound
- = &objfile->global_psymbols[ps->globals_offset + ps->n_global_syms];
+ = objfile->global_psymbols.data () + ps->globals_offset + ps->n_global_syms;
partial_symbol **sbound
- = &objfile->static_psymbols[ps->statics_offset + ps->n_static_syms];
+ = objfile->static_psymbols.data () + ps->statics_offset + ps->n_static_syms;
partial_symbol **bound = gbound;
/* Go through all of the symbols stored in a partial
symtab in one loop. */
- partial_symbol **psym = &objfile->global_psymbols[ps->globals_offset];
+ partial_symbol **psym = objfile->global_psymbols.data () + ps->globals_offset;
while (keep_going)
{
if (psym >= bound)
{
if (bound == gbound && ps->n_static_syms != 0)
{
- psym = &objfile->static_psymbols[ps->statics_offset];
+ psym = objfile->static_psymbols.data () + ps->statics_offset;
bound = sbound;
}
else
{
QUIT;
- if ((kind == ALL_DOMAIN
- || (kind == VARIABLES_DOMAIN
+ if ((domain == ALL_DOMAIN
+ || (domain == VARIABLES_DOMAIN
&& PSYMBOL_CLASS (*psym) != LOC_TYPEDEF
&& PSYMBOL_CLASS (*psym) != LOC_BLOCK)
- || (kind == FUNCTIONS_DOMAIN
+ || (domain == FUNCTIONS_DOMAIN
&& PSYMBOL_CLASS (*psym) == LOC_BLOCK)
- || (kind == TYPES_DOMAIN
+ || (domain == TYPES_DOMAIN
&& PSYMBOL_CLASS (*psym) == LOC_TYPEDEF))
- && sym_matcher (SYMBOL_SEARCH_NAME (*psym)))
+ && psymbol_name_matches (*psym, lookup_name)
+ && (sym_matcher == NULL || sym_matcher (SYMBOL_SEARCH_NAME (*psym))))
{
/* Found a match, so notify our caller. */
result = PST_SEARCHED_AND_FOUND;
psym_expand_symtabs_matching
(struct objfile *objfile,
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+ const lookup_name_info &lookup_name_in,
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
- enum search_domain kind)
+ enum search_domain domain)
{
struct partial_symtab *ps;
+ lookup_name_info lookup_name = lookup_name_in.make_ignore_params ();
+
/* Clear the search flags. */
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
{
continue;
}
- if (recursively_search_psymtabs (ps, objfile, kind, symbol_matcher))
+ if (recursively_search_psymtabs (ps, objfile, domain,
+ lookup_name, symbol_matcher))
{
struct compunit_symtab *symtab =
psymtab_to_symtab (objfile, ps);
return objfile->psymtabs != NULL;
}
+/* Helper function for psym_find_compunit_symtab_by_address that fills
+ in psymbol_map for a given range of psymbols. */
+
+static void
+psym_fill_psymbol_map (struct objfile *objfile,
+ struct partial_symtab *psymtab,
+ std::set<CORE_ADDR> *seen_addrs,
+ const std::vector<partial_symbol *> &symbols,
+ int start,
+ int length)
+{
+ for (int i = 0; i < length; ++i)
+ {
+ struct partial_symbol *psym = symbols[start + i];
+
+ if (PSYMBOL_CLASS (psym) == LOC_STATIC)
+ {
+ CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (psym);
+ if (seen_addrs->find (addr) == seen_addrs->end ())
+ {
+ seen_addrs->insert (addr);
+ objfile->psymbol_map.emplace_back (addr, psymtab);
+ }
+ }
+ }
+}
+
+/* See find_compunit_symtab_by_address in quick_symbol_functions, in
+ symfile.h. */
+
+static compunit_symtab *
+psym_find_compunit_symtab_by_address (struct objfile *objfile,
+ CORE_ADDR address)
+{
+ if (objfile->psymbol_map.empty ())
+ {
+ struct partial_symtab *pst;
+
+ std::set<CORE_ADDR> seen_addrs;
+
+ ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
+ {
+ psym_fill_psymbol_map (objfile, pst,
+ &seen_addrs,
+ objfile->global_psymbols,
+ pst->globals_offset,
+ pst->n_global_syms);
+ psym_fill_psymbol_map (objfile, pst,
+ &seen_addrs,
+ objfile->static_psymbols,
+ pst->statics_offset,
+ pst->n_static_syms);
+ }
+
+ objfile->psymbol_map.shrink_to_fit ();
+
+ std::sort (objfile->psymbol_map.begin (), objfile->psymbol_map.end (),
+ [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
+ const std::pair<CORE_ADDR, partial_symtab *> &b)
+ {
+ return a.first < b.first;
+ });
+ }
+
+ auto iter = std::lower_bound
+ (objfile->psymbol_map.begin (), objfile->psymbol_map.end (), address,
+ [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
+ CORE_ADDR b)
+ {
+ return a.first < b;
+ });
+
+ if (iter == objfile->psymbol_map.end () || iter->first != address)
+ return NULL;
+
+ return psymtab_to_symtab (objfile, iter->second);
+}
+
const struct quick_symbol_functions psym_functions =
{
psym_has_symbols,
psym_map_matching_symbols,
psym_expand_symtabs_matching,
psym_find_pc_sect_compunit_symtab,
+ psym_find_compunit_symtab_by_address,
psym_map_symbol_filenames
};
h = hash_continue (&lang, sizeof (unsigned int), h);
h = hash_continue (&domain, sizeof (unsigned int), h);
h = hash_continue (&theclass, sizeof (unsigned int), h);
- h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h);
+ /* Note that psymbol names are interned via symbol_set_names, so
+ there's no need to hash the contents of the name here. */
+ h = hash_continue (&psymbol->ginfo.name, sizeof (psymbol->ginfo.name), h);
return h;
}
&& sym1->ginfo.language == sym2->ginfo.language
&& PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
&& PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)
+ /* Note that psymbol names are interned via
+ symbol_set_names, so there's no need to compare the
+ contents of the name here. */
&& sym1->ginfo.name == sym2->ginfo.name);
}
length = ps->n_static_syms;
while (length--)
{
- sym = block_lookup_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+ sym = block_lookup_symbol (b, SYMBOL_SEARCH_NAME (*psym),
+ symbol_name_match_type::SEARCH_NAME,
SYMBOL_DOMAIN (*psym));
if (!sym)
{
length = ps->n_global_syms;
while (length--)
{
- sym = block_lookup_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+ sym = block_lookup_symbol (b, SYMBOL_SEARCH_NAME (*psym),
+ symbol_name_match_type::SEARCH_NAME,
SYMBOL_DOMAIN (*psym));
if (!sym)
{