gdb/dwarf2: split .gdb_index reading code to own file
Move everything related to reading .gdb_index from read.c to read-gdb-index.c. The only entry point exposed by read-gdb-index.{c,h} is dwarf2_read_gdb_index. Change-Id: I1e32c8f0720086538de8d2f612f27545377099bc Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
parent
6acd95be6a
commit
be932484aa
@ -1082,6 +1082,7 @@ COMMON_SFILES = \
|
||||
dwarf2/loc.c \
|
||||
dwarf2/macro.c \
|
||||
dwarf2/read.c \
|
||||
dwarf2/read-gdb-index.c \
|
||||
dwarf2/section.c \
|
||||
dwarf2/stringify.c \
|
||||
eval.c \
|
||||
@ -1325,6 +1326,7 @@ HFILES_NO_SRCDIR = \
|
||||
dwarf2/index-common.h \
|
||||
dwarf2/loc.h \
|
||||
dwarf2/read.h \
|
||||
dwarf2/read-gdb-index.h \
|
||||
event-top.h \
|
||||
exceptions.h \
|
||||
exec.h \
|
||||
|
874
gdb/dwarf2/read-gdb-index.c
Normal file
874
gdb/dwarf2/read-gdb-index.c
Normal file
@ -0,0 +1,874 @@
|
||||
/* Reading code for .gdb_index
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "read-gdb-index.h"
|
||||
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "complaints.h"
|
||||
#include "dwz.h"
|
||||
#include "gdb/gdb-index.h"
|
||||
#include "gdbsupport/gdb-checked-static-cast.h"
|
||||
#include "mapped-index.h"
|
||||
#include "read.h"
|
||||
|
||||
/* When true, do not reject deprecated .gdb_index sections. */
|
||||
static bool use_deprecated_index_sections = false;
|
||||
|
||||
/* This is a view into the index that converts from bytes to an
|
||||
offset_type, and allows indexing. Unaligned bytes are specifically
|
||||
allowed here, and handled via unpacking. */
|
||||
|
||||
class offset_view
|
||||
{
|
||||
public:
|
||||
offset_view () = default;
|
||||
|
||||
explicit offset_view (gdb::array_view<const gdb_byte> bytes)
|
||||
: m_bytes (bytes)
|
||||
{
|
||||
}
|
||||
|
||||
/* Extract the INDEXth offset_type from the array. */
|
||||
offset_type operator[] (size_t index) const
|
||||
{
|
||||
const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)];
|
||||
return (offset_type) extract_unsigned_integer (bytes,
|
||||
sizeof (offset_type),
|
||||
BFD_ENDIAN_LITTLE);
|
||||
}
|
||||
|
||||
/* Return the number of offset_types in this array. */
|
||||
size_t size () const
|
||||
{
|
||||
return m_bytes.size () / sizeof (offset_type);
|
||||
}
|
||||
|
||||
/* Return true if this view is empty. */
|
||||
bool empty () const
|
||||
{
|
||||
return m_bytes.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
/* The underlying bytes. */
|
||||
gdb::array_view<const gdb_byte> m_bytes;
|
||||
};
|
||||
|
||||
/* A description of .gdb_index index. The file format is described in
|
||||
a comment by the code that writes the index. */
|
||||
|
||||
struct mapped_gdb_index final : public mapped_index_base
|
||||
{
|
||||
/* Index data format version. */
|
||||
int version = 0;
|
||||
|
||||
/* The address table data. */
|
||||
gdb::array_view<const gdb_byte> address_table;
|
||||
|
||||
/* The symbol table, implemented as a hash table. */
|
||||
offset_view symbol_table;
|
||||
|
||||
/* A pointer to the constant pool. */
|
||||
gdb::array_view<const gdb_byte> constant_pool;
|
||||
|
||||
/* Return the index into the constant pool of the name of the IDXth
|
||||
symbol in the symbol table. */
|
||||
offset_type symbol_name_index (offset_type idx) const
|
||||
{
|
||||
return symbol_table[2 * idx];
|
||||
}
|
||||
|
||||
/* Return the index into the constant pool of the CU vector of the
|
||||
IDXth symbol in the symbol table. */
|
||||
offset_type symbol_vec_index (offset_type idx) const
|
||||
{
|
||||
return symbol_table[2 * idx + 1];
|
||||
}
|
||||
|
||||
bool symbol_name_slot_invalid (offset_type idx) const override
|
||||
{
|
||||
return (symbol_name_index (idx) == 0
|
||||
&& symbol_vec_index (idx) == 0);
|
||||
}
|
||||
|
||||
/* Convenience method to get at the name of the symbol at IDX in the
|
||||
symbol table. */
|
||||
const char *symbol_name_at
|
||||
(offset_type idx, dwarf2_per_objfile *per_objfile) const override
|
||||
{
|
||||
return (const char *) (this->constant_pool.data ()
|
||||
+ symbol_name_index (idx));
|
||||
}
|
||||
|
||||
size_t symbol_name_count () const override
|
||||
{ return this->symbol_table.size () / 2; }
|
||||
|
||||
quick_symbol_functions_up make_quick_functions () const override;
|
||||
|
||||
bool version_check () const override
|
||||
{
|
||||
return version >= 8;
|
||||
}
|
||||
};
|
||||
|
||||
struct dwarf2_gdb_index : public dwarf2_base_index_functions
|
||||
{
|
||||
/* This dumps minimal information about the index.
|
||||
It is called via "mt print objfiles".
|
||||
One use is to verify .gdb_index has been loaded by the
|
||||
gdb.dwarf2/gdb-index.exp testcase. */
|
||||
void dump (struct objfile *objfile) override;
|
||||
|
||||
void expand_matching_symbols
|
||||
(struct objfile *,
|
||||
const lookup_name_info &lookup_name,
|
||||
domain_enum domain,
|
||||
int global,
|
||||
symbol_compare_ftype *ordered_compare) override;
|
||||
|
||||
bool expand_symtabs_matching
|
||||
(struct objfile *objfile,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
const lookup_name_info *lookup_name,
|
||||
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
domain_enum domain,
|
||||
enum search_domain kind) override;
|
||||
};
|
||||
|
||||
/* This dumps minimal information about the index.
|
||||
It is called via "mt print objfiles".
|
||||
One use is to verify .gdb_index has been loaded by the
|
||||
gdb.dwarf2/gdb-index.exp testcase. */
|
||||
|
||||
void
|
||||
dwarf2_gdb_index::dump (struct objfile *objfile)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
mapped_gdb_index *index = (gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
gdb_printf (".gdb_index: version %d\n", index->version);
|
||||
gdb_printf ("\n");
|
||||
}
|
||||
|
||||
/* Struct used to manage iterating over all CUs looking for a symbol. */
|
||||
|
||||
struct dw2_symtab_iterator
|
||||
{
|
||||
/* The dwarf2_per_objfile owning the CUs we are iterating on. */
|
||||
dwarf2_per_objfile *per_objfile;
|
||||
/* If set, only look for symbols that match that block. Valid values are
|
||||
GLOBAL_BLOCK and STATIC_BLOCK. */
|
||||
gdb::optional<block_enum> block_index;
|
||||
/* The kind of symbol we're looking for. */
|
||||
domain_enum domain;
|
||||
/* The list of CUs from the index entry of the symbol,
|
||||
or NULL if not found. */
|
||||
offset_view vec;
|
||||
/* The next element in VEC to look at. */
|
||||
int next;
|
||||
/* The number of elements in VEC, or zero if there is no match. */
|
||||
int length;
|
||||
/* Have we seen a global version of the symbol?
|
||||
If so we can ignore all further global instances.
|
||||
This is to work around gold/15646, inefficient gold-generated
|
||||
indices. */
|
||||
int global_seen;
|
||||
};
|
||||
|
||||
/* Initialize the index symtab iterator ITER, offset_type NAMEI variant. */
|
||||
|
||||
static void
|
||||
dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
|
||||
dwarf2_per_objfile *per_objfile,
|
||||
gdb::optional<block_enum> block_index,
|
||||
domain_enum domain, offset_type namei,
|
||||
mapped_gdb_index &index)
|
||||
{
|
||||
iter->per_objfile = per_objfile;
|
||||
iter->block_index = block_index;
|
||||
iter->domain = domain;
|
||||
iter->next = 0;
|
||||
iter->global_seen = 0;
|
||||
iter->vec = {};
|
||||
iter->length = 0;
|
||||
|
||||
gdb_assert (!index.symbol_name_slot_invalid (namei));
|
||||
offset_type vec_idx = index.symbol_vec_index (namei);
|
||||
|
||||
iter->vec = offset_view (index.constant_pool.slice (vec_idx));
|
||||
iter->length = iter->vec[0];
|
||||
}
|
||||
|
||||
/* Return the next matching CU or NULL if there are no more. */
|
||||
|
||||
static struct dwarf2_per_cu_data *
|
||||
dw2_symtab_iter_next (struct dw2_symtab_iterator *iter,
|
||||
mapped_gdb_index &index)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = iter->per_objfile;
|
||||
|
||||
for ( ; iter->next < iter->length; ++iter->next)
|
||||
{
|
||||
offset_type cu_index_and_attrs = iter->vec[iter->next + 1];
|
||||
offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
||||
gdb_index_symbol_kind symbol_kind =
|
||||
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
||||
/* Only check the symbol attributes if they're present.
|
||||
Indices prior to version 7 don't record them,
|
||||
and indices >= 7 may elide them for certain symbols
|
||||
(gold does this). */
|
||||
int attrs_valid = (index.version >= 7
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
||||
|
||||
/* Don't crash on bad data. */
|
||||
if (cu_index >= per_objfile->per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index entry has bad CU index"
|
||||
" [in module %s]"), objfile_name (per_objfile->objfile));
|
||||
continue;
|
||||
}
|
||||
|
||||
dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
|
||||
|
||||
/* Skip if already read in. */
|
||||
if (per_objfile->symtab_set_p (per_cu))
|
||||
continue;
|
||||
|
||||
/* Check static vs global. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
bool is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
||||
|
||||
if (iter->block_index.has_value ())
|
||||
{
|
||||
bool want_static = *iter->block_index == STATIC_BLOCK;
|
||||
|
||||
if (is_static != want_static)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Work around gold/15646. */
|
||||
if (!is_static
|
||||
&& symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
{
|
||||
if (iter->global_seen)
|
||||
continue;
|
||||
|
||||
iter->global_seen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only check the symbol's kind if it has one. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
switch (iter->domain)
|
||||
{
|
||||
case VAR_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
|
||||
/* Some types are also in VAR_DOMAIN. */
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case STRUCT_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case LABEL_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
case MODULE_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++iter->next;
|
||||
return per_cu;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
dwarf2_gdb_index::expand_matching_symbols
|
||||
(struct objfile *objfile,
|
||||
const lookup_name_info &name, domain_enum domain,
|
||||
int global,
|
||||
symbol_compare_ftype *ordered_compare)
|
||||
{
|
||||
/* Used for Ada. */
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
|
||||
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
const char *match_name = name.ada ().lookup_name ().c_str ();
|
||||
auto matcher = [&] (const char *symname)
|
||||
{
|
||||
if (ordered_compare == nullptr)
|
||||
return true;
|
||||
return ordered_compare (symname, match_name) == 0;
|
||||
};
|
||||
|
||||
dw2_expand_symtabs_matching_symbol (index, name, matcher,
|
||||
[&] (offset_type namei)
|
||||
{
|
||||
struct dw2_symtab_iterator iter;
|
||||
struct dwarf2_per_cu_data *per_cu;
|
||||
|
||||
dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain, namei,
|
||||
index);
|
||||
while ((per_cu = dw2_symtab_iter_next (&iter, index)) != NULL)
|
||||
dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
|
||||
nullptr);
|
||||
return true;
|
||||
}, per_objfile);
|
||||
}
|
||||
|
||||
/* Helper for dw2_expand_matching symtabs. Called on each symbol
|
||||
matched, to expand corresponding CUs that were marked. IDX is the
|
||||
index of the symbol name that matched. */
|
||||
|
||||
static bool
|
||||
dw2_expand_marked_cus
|
||||
(dwarf2_per_objfile *per_objfile, offset_type idx,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
search_domain kind)
|
||||
{
|
||||
offset_type vec_len, vec_idx;
|
||||
bool global_seen = false;
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
|
||||
vec_len = vec[0];
|
||||
for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
|
||||
{
|
||||
offset_type cu_index_and_attrs = vec[vec_idx + 1];
|
||||
/* This value is only valid for index versions >= 7. */
|
||||
int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
||||
gdb_index_symbol_kind symbol_kind =
|
||||
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
||||
int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
||||
/* Only check the symbol attributes if they're present.
|
||||
Indices prior to version 7 don't record them,
|
||||
and indices >= 7 may elide them for certain symbols
|
||||
(gold does this). */
|
||||
int attrs_valid =
|
||||
(index.version >= 7
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
||||
|
||||
/* Work around gold/15646. */
|
||||
if (attrs_valid
|
||||
&& !is_static
|
||||
&& symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
{
|
||||
if (global_seen)
|
||||
continue;
|
||||
|
||||
global_seen = true;
|
||||
}
|
||||
|
||||
/* Only check the symbol's kind if it has one. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
if (is_static)
|
||||
{
|
||||
if ((search_flags & SEARCH_STATIC_BLOCK) == 0)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case VARIABLES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
|
||||
continue;
|
||||
break;
|
||||
case FUNCTIONS_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
|
||||
continue;
|
||||
break;
|
||||
case TYPES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case MODULES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't crash on bad data. */
|
||||
if (cu_index >= per_objfile->per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index entry has bad CU index"
|
||||
" [in module %s]"), objfile_name (per_objfile->objfile));
|
||||
continue;
|
||||
}
|
||||
|
||||
dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
|
||||
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
|
||||
expansion_notify))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
dwarf2_gdb_index::expand_symtabs_matching
|
||||
(struct objfile *objfile,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
const lookup_name_info *lookup_name,
|
||||
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
domain_enum domain,
|
||||
enum search_domain kind)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
|
||||
|
||||
/* This invariant is documented in quick-functions.h. */
|
||||
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
|
||||
if (lookup_name == nullptr)
|
||||
{
|
||||
for (dwarf2_per_cu_data *per_cu
|
||||
: all_units_range (per_objfile->per_bfd))
|
||||
{
|
||||
QUIT;
|
||||
|
||||
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
|
||||
file_matcher,
|
||||
expansion_notify))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
bool result
|
||||
= dw2_expand_symtabs_matching_symbol (index, *lookup_name,
|
||||
symbol_matcher,
|
||||
[&] (offset_type idx)
|
||||
{
|
||||
if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
|
||||
expansion_notify, search_flags, kind))
|
||||
return false;
|
||||
return true;
|
||||
}, per_objfile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
quick_symbol_functions_up
|
||||
mapped_gdb_index::make_quick_functions () const
|
||||
{
|
||||
return quick_symbol_functions_up (new dwarf2_gdb_index);
|
||||
}
|
||||
|
||||
/* A helper function that reads the .gdb_index from BUFFER and fills
|
||||
in MAP. FILENAME is the name of the file containing the data;
|
||||
it is used for error reporting. DEPRECATED_OK is true if it is
|
||||
ok to use deprecated sections.
|
||||
|
||||
CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are
|
||||
out parameters that are filled in with information about the CU and
|
||||
TU lists in the section.
|
||||
|
||||
Returns true if all went well, false otherwise. */
|
||||
|
||||
static bool
|
||||
read_gdb_index_from_buffer (const char *filename,
|
||||
bool deprecated_ok,
|
||||
gdb::array_view<const gdb_byte> buffer,
|
||||
mapped_gdb_index *map,
|
||||
const gdb_byte **cu_list,
|
||||
offset_type *cu_list_elements,
|
||||
const gdb_byte **types_list,
|
||||
offset_type *types_list_elements)
|
||||
{
|
||||
const gdb_byte *addr = &buffer[0];
|
||||
offset_view metadata (buffer);
|
||||
|
||||
/* Version check. */
|
||||
offset_type version = metadata[0];
|
||||
/* Versions earlier than 3 emitted every copy of a psymbol. This
|
||||
causes the index to behave very poorly for certain requests. Version 3
|
||||
contained incomplete addrmap. So, it seems better to just ignore such
|
||||
indices. */
|
||||
if (version < 4)
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("Skipping obsolete .gdb_index section in %s."),
|
||||
filename);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Index version 4 uses a different hash function than index version
|
||||
5 and later.
|
||||
|
||||
Versions earlier than 6 did not emit psymbols for inlined
|
||||
functions. Using these files will cause GDB not to be able to
|
||||
set breakpoints on inlined functions by name, so we ignore these
|
||||
indices unless the user has done
|
||||
"set use-deprecated-index-sections on". */
|
||||
if (version < 6 && !deprecated_ok)
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("\
|
||||
Skipping deprecated .gdb_index section in %s.\n\
|
||||
Do \"set use-deprecated-index-sections on\" before the file is read\n\
|
||||
to use the section anyway."),
|
||||
filename);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Version 7 indices generated by gold refer to the CU for a symbol instead
|
||||
of the TU (for symbols coming from TUs),
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
|
||||
Plus gold-generated indices can have duplicate entries for global symbols,
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=15646.
|
||||
These are just performance bugs, and we can't distinguish gdb-generated
|
||||
indices from gold-generated ones, so issue no warning here. */
|
||||
|
||||
/* Indexes with higher version than the one supported by GDB may be no
|
||||
longer backward compatible. */
|
||||
if (version > 8)
|
||||
return 0;
|
||||
|
||||
map->version = version;
|
||||
|
||||
int i = 1;
|
||||
*cu_list = addr + metadata[i];
|
||||
*cu_list_elements = (metadata[i + 1] - metadata[i]) / 8;
|
||||
++i;
|
||||
|
||||
*types_list = addr + metadata[i];
|
||||
*types_list_elements = (metadata[i + 1] - metadata[i]) / 8;
|
||||
++i;
|
||||
|
||||
const gdb_byte *address_table = addr + metadata[i];
|
||||
const gdb_byte *address_table_end = addr + metadata[i + 1];
|
||||
map->address_table
|
||||
= gdb::array_view<const gdb_byte> (address_table, address_table_end);
|
||||
++i;
|
||||
|
||||
const gdb_byte *symbol_table = addr + metadata[i];
|
||||
const gdb_byte *symbol_table_end = addr + metadata[i + 1];
|
||||
map->symbol_table
|
||||
= offset_view (gdb::array_view<const gdb_byte> (symbol_table,
|
||||
symbol_table_end));
|
||||
|
||||
++i;
|
||||
map->constant_pool = buffer.slice (metadata[i]);
|
||||
|
||||
if (map->constant_pool.empty () && !map->symbol_table.empty ())
|
||||
{
|
||||
/* An empty constant pool implies that all symbol table entries are
|
||||
empty. Make map->symbol_table.empty () == true. */
|
||||
map->symbol_table
|
||||
= offset_view (gdb::array_view<const gdb_byte> (symbol_table,
|
||||
symbol_table));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A helper for create_cus_from_gdb_index that handles a given list of
|
||||
CUs. */
|
||||
|
||||
static void
|
||||
create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
|
||||
const gdb_byte *cu_list, offset_type n_elements,
|
||||
struct dwarf2_section_info *section,
|
||||
int is_dwz)
|
||||
{
|
||||
for (offset_type i = 0; i < n_elements; i += 2)
|
||||
{
|
||||
gdb_static_assert (sizeof (ULONGEST) >= 8);
|
||||
|
||||
sect_offset sect_off
|
||||
= (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
|
||||
ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
|
||||
cu_list += 2 * 8;
|
||||
|
||||
dwarf2_per_cu_data_up per_cu
|
||||
= create_cu_from_index_list (per_bfd, section, is_dwz, sect_off,
|
||||
length);
|
||||
per_bfd->all_units.push_back (std::move (per_cu));
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the CU list from the mapped index, and use it to create all
|
||||
the CU objects for PER_BFD. */
|
||||
|
||||
static void
|
||||
create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
|
||||
const gdb_byte *cu_list, offset_type cu_list_elements,
|
||||
const gdb_byte *dwz_list, offset_type dwz_elements)
|
||||
{
|
||||
gdb_assert (per_bfd->all_units.empty ());
|
||||
per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
|
||||
|
||||
create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
|
||||
&per_bfd->info, 0);
|
||||
|
||||
if (dwz_elements == 0)
|
||||
return;
|
||||
|
||||
dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
|
||||
create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements,
|
||||
&dwz->info, 1);
|
||||
}
|
||||
|
||||
/* Create the signatured type hash table from the index. */
|
||||
|
||||
static void
|
||||
create_signatured_type_table_from_gdb_index
|
||||
(dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
|
||||
const gdb_byte *bytes, offset_type elements)
|
||||
{
|
||||
htab_up sig_types_hash = allocate_signatured_type_table ();
|
||||
|
||||
for (offset_type i = 0; i < elements; i += 3)
|
||||
{
|
||||
signatured_type_up sig_type;
|
||||
ULONGEST signature;
|
||||
void **slot;
|
||||
cu_offset type_offset_in_tu;
|
||||
|
||||
gdb_static_assert (sizeof (ULONGEST) >= 8);
|
||||
sect_offset sect_off
|
||||
= (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
|
||||
type_offset_in_tu
|
||||
= (cu_offset) extract_unsigned_integer (bytes + 8, 8,
|
||||
BFD_ENDIAN_LITTLE);
|
||||
signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
|
||||
bytes += 3 * 8;
|
||||
|
||||
sig_type = per_bfd->allocate_signatured_type (signature);
|
||||
sig_type->type_offset_in_tu = type_offset_in_tu;
|
||||
sig_type->section = section;
|
||||
sig_type->sect_off = sect_off;
|
||||
|
||||
slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
|
||||
*slot = sig_type.get ();
|
||||
|
||||
per_bfd->all_units.emplace_back (sig_type.release ());
|
||||
}
|
||||
|
||||
per_bfd->signatured_types = std::move (sig_types_hash);
|
||||
}
|
||||
|
||||
/* Read the address map data from the mapped GDB index, and use it to
|
||||
populate the index_addrmap. */
|
||||
|
||||
static void
|
||||
create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
|
||||
mapped_gdb_index *index)
|
||||
{
|
||||
struct objfile *objfile = per_objfile->objfile;
|
||||
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
|
||||
struct gdbarch *gdbarch = objfile->arch ();
|
||||
const gdb_byte *iter, *end;
|
||||
CORE_ADDR baseaddr;
|
||||
|
||||
addrmap_mutable mutable_map;
|
||||
|
||||
iter = index->address_table.data ();
|
||||
end = iter + index->address_table.size ();
|
||||
|
||||
baseaddr = objfile->text_section_offset ();
|
||||
|
||||
while (iter < end)
|
||||
{
|
||||
ULONGEST hi, lo, cu_index;
|
||||
lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
|
||||
iter += 8;
|
||||
hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
|
||||
iter += 8;
|
||||
cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
|
||||
iter += 4;
|
||||
|
||||
if (lo > hi)
|
||||
{
|
||||
complaint (_(".gdb_index address table has invalid range (%s - %s)"),
|
||||
hex_string (lo), hex_string (hi));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cu_index >= per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index address table has invalid CU number %u"),
|
||||
(unsigned) cu_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr;
|
||||
hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr;
|
||||
mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index));
|
||||
}
|
||||
|
||||
per_bfd->index_addrmap
|
||||
= new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack, &mutable_map);
|
||||
}
|
||||
|
||||
/* See read-gdb-index.h. */
|
||||
|
||||
int
|
||||
dwarf2_read_gdb_index
|
||||
(dwarf2_per_objfile *per_objfile,
|
||||
get_gdb_index_contents_ftype get_gdb_index_contents,
|
||||
get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz)
|
||||
{
|
||||
const gdb_byte *cu_list, *types_list, *dwz_list = NULL;
|
||||
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
|
||||
struct dwz_file *dwz;
|
||||
struct objfile *objfile = per_objfile->objfile;
|
||||
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
|
||||
|
||||
gdb::array_view<const gdb_byte> main_index_contents
|
||||
= get_gdb_index_contents (objfile, per_bfd);
|
||||
|
||||
if (main_index_contents.empty ())
|
||||
return 0;
|
||||
|
||||
std::unique_ptr<mapped_gdb_index> map (new mapped_gdb_index);
|
||||
if (!read_gdb_index_from_buffer (objfile_name (objfile),
|
||||
use_deprecated_index_sections,
|
||||
main_index_contents, map.get (), &cu_list,
|
||||
&cu_list_elements, &types_list,
|
||||
&types_list_elements))
|
||||
return 0;
|
||||
|
||||
/* Don't use the index if it's empty. */
|
||||
if (map->symbol_table.empty ())
|
||||
return 0;
|
||||
|
||||
/* If there is a .dwz file, read it so we can get its CU list as
|
||||
well. */
|
||||
dwz = dwarf2_get_dwz_file (per_bfd);
|
||||
if (dwz != NULL)
|
||||
{
|
||||
mapped_gdb_index dwz_map;
|
||||
const gdb_byte *dwz_types_ignore;
|
||||
offset_type dwz_types_elements_ignore;
|
||||
|
||||
gdb::array_view<const gdb_byte> dwz_index_content
|
||||
= get_gdb_index_contents_dwz (objfile, dwz);
|
||||
|
||||
if (dwz_index_content.empty ())
|
||||
return 0;
|
||||
|
||||
if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.get ()),
|
||||
1, dwz_index_content, &dwz_map,
|
||||
&dwz_list, &dwz_list_elements,
|
||||
&dwz_types_ignore,
|
||||
&dwz_types_elements_ignore))
|
||||
{
|
||||
warning (_("could not read '.gdb_index' section from %s; skipping"),
|
||||
bfd_get_filename (dwz->dwz_bfd.get ()));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list,
|
||||
dwz_list_elements);
|
||||
|
||||
if (types_list_elements)
|
||||
{
|
||||
/* We can only handle a single .debug_types when we have an
|
||||
index. */
|
||||
if (per_bfd->types.size () > 1)
|
||||
{
|
||||
per_bfd->all_units.clear ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwarf2_section_info *section
|
||||
= (per_bfd->types.size () == 1
|
||||
? &per_bfd->types[0]
|
||||
: &per_bfd->info);
|
||||
|
||||
create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
|
||||
types_list_elements);
|
||||
}
|
||||
|
||||
finalize_all_units (per_bfd);
|
||||
|
||||
create_addrmap_from_gdb_index (per_objfile, map.get ());
|
||||
|
||||
per_bfd->index_table = std::move (map);
|
||||
per_bfd->quick_file_names_table =
|
||||
create_quick_file_names_table (per_bfd->all_units.size ());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _initialize_read_gdb_index ();
|
||||
|
||||
void
|
||||
_initialize_read_gdb_index ()
|
||||
{
|
||||
add_setshow_boolean_cmd ("use-deprecated-index-sections",
|
||||
no_class, &use_deprecated_index_sections, _("\
|
||||
Set whether to use deprecated gdb_index sections."), _("\
|
||||
Show whether to use deprecated gdb_index sections."), _("\
|
||||
When enabled, deprecated .gdb_index sections are used anyway.\n\
|
||||
Normally they are ignored either because of a missing feature or\n\
|
||||
performance issue.\n\
|
||||
Warning: This option must be enabled before gdb reads the file."),
|
||||
NULL,
|
||||
NULL,
|
||||
&setlist, &showlist);
|
||||
}
|
47
gdb/dwarf2/read-gdb-index.h
Normal file
47
gdb/dwarf2/read-gdb-index.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Reading code for .gdb_index
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef DWARF2_READ_GDB_INDEX_H
|
||||
#define DWARF2_READ_GDB_INDEX_H
|
||||
|
||||
#include "gdbsupport/function-view.h"
|
||||
|
||||
struct dwarf2_per_bfd;
|
||||
struct dwarf2_per_objfile;
|
||||
struct dwz_file;
|
||||
struct objfile;
|
||||
|
||||
/* Callback types for dwarf2_read_gdb_index. */
|
||||
|
||||
typedef gdb::function_view
|
||||
<gdb::array_view<const gdb_byte>(objfile *, dwarf2_per_bfd *)>
|
||||
get_gdb_index_contents_ftype;
|
||||
typedef gdb::function_view
|
||||
<gdb::array_view<const gdb_byte>(objfile *, dwz_file *)>
|
||||
get_gdb_index_contents_dwz_ftype;
|
||||
|
||||
/* Read .gdb_index. If everything went ok, initialize the "quick"
|
||||
elements of all the CUs and return 1. Otherwise, return 0. */
|
||||
|
||||
int dwarf2_read_gdb_index
|
||||
(dwarf2_per_objfile *per_objfile,
|
||||
get_gdb_index_contents_ftype get_gdb_index_contents,
|
||||
get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz);
|
||||
|
||||
#endif /* DWARF2_READ_GDB_INDEX_H */
|
@ -41,6 +41,7 @@
|
||||
#include "dwarf2/dwz.h"
|
||||
#include "dwarf2/macro.h"
|
||||
#include "dwarf2/die.h"
|
||||
#include "dwarf2/read-gdb-index.h"
|
||||
#include "dwarf2/sect-names.h"
|
||||
#include "dwarf2/stringify.h"
|
||||
#include "dwarf2/public.h"
|
||||
@ -120,9 +121,6 @@ unsigned int dwarf_line_debug = 0;
|
||||
/* When true, cross-check physname against demangler. */
|
||||
static bool check_physname = false;
|
||||
|
||||
/* When true, do not reject deprecated .gdb_index sections. */
|
||||
static bool use_deprecated_index_sections = false;
|
||||
|
||||
/* This is used to store the data that is always per objfile. */
|
||||
static const registry<objfile>::key<dwarf2_per_objfile>
|
||||
dwarf2_objfile_data_key;
|
||||
@ -158,103 +156,6 @@ static int dwarf2_loclist_block_index;
|
||||
/* Size of .debug_rnglists section header for 64-bit DWARF format. */
|
||||
#define RNGLIST_HEADER_SIZE64 20
|
||||
|
||||
/* This is a view into the index that converts from bytes to an
|
||||
offset_type, and allows indexing. Unaligned bytes are specifically
|
||||
allowed here, and handled via unpacking. */
|
||||
|
||||
class offset_view
|
||||
{
|
||||
public:
|
||||
offset_view () = default;
|
||||
|
||||
explicit offset_view (gdb::array_view<const gdb_byte> bytes)
|
||||
: m_bytes (bytes)
|
||||
{
|
||||
}
|
||||
|
||||
/* Extract the INDEXth offset_type from the array. */
|
||||
offset_type operator[] (size_t index) const
|
||||
{
|
||||
const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)];
|
||||
return (offset_type) extract_unsigned_integer (bytes,
|
||||
sizeof (offset_type),
|
||||
BFD_ENDIAN_LITTLE);
|
||||
}
|
||||
|
||||
/* Return the number of offset_types in this array. */
|
||||
size_t size () const
|
||||
{
|
||||
return m_bytes.size () / sizeof (offset_type);
|
||||
}
|
||||
|
||||
/* Return true if this view is empty. */
|
||||
bool empty () const
|
||||
{
|
||||
return m_bytes.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
/* The underlying bytes. */
|
||||
gdb::array_view<const gdb_byte> m_bytes;
|
||||
};
|
||||
|
||||
/* A description of .gdb_index index. The file format is described in
|
||||
a comment by the code that writes the index. */
|
||||
|
||||
struct mapped_gdb_index final : public mapped_index_base
|
||||
{
|
||||
/* Index data format version. */
|
||||
int version = 0;
|
||||
|
||||
/* The address table data. */
|
||||
gdb::array_view<const gdb_byte> address_table;
|
||||
|
||||
/* The symbol table, implemented as a hash table. */
|
||||
offset_view symbol_table;
|
||||
|
||||
/* A pointer to the constant pool. */
|
||||
gdb::array_view<const gdb_byte> constant_pool;
|
||||
|
||||
/* Return the index into the constant pool of the name of the IDXth
|
||||
symbol in the symbol table. */
|
||||
offset_type symbol_name_index (offset_type idx) const
|
||||
{
|
||||
return symbol_table[2 * idx];
|
||||
}
|
||||
|
||||
/* Return the index into the constant pool of the CU vector of the
|
||||
IDXth symbol in the symbol table. */
|
||||
offset_type symbol_vec_index (offset_type idx) const
|
||||
{
|
||||
return symbol_table[2 * idx + 1];
|
||||
}
|
||||
|
||||
bool symbol_name_slot_invalid (offset_type idx) const override
|
||||
{
|
||||
return (symbol_name_index (idx) == 0
|
||||
&& symbol_vec_index (idx) == 0);
|
||||
}
|
||||
|
||||
/* Convenience method to get at the name of the symbol at IDX in the
|
||||
symbol table. */
|
||||
const char *symbol_name_at
|
||||
(offset_type idx, dwarf2_per_objfile *per_objfile) const override
|
||||
{
|
||||
return (const char *) (this->constant_pool.data ()
|
||||
+ symbol_name_index (idx));
|
||||
}
|
||||
|
||||
size_t symbol_name_count () const override
|
||||
{ return this->symbol_table.size () / 2; }
|
||||
|
||||
quick_symbol_functions_up make_quick_functions () const override;
|
||||
|
||||
bool version_check () const override
|
||||
{
|
||||
return version >= 8;
|
||||
}
|
||||
};
|
||||
|
||||
/* A description of the mapped .debug_names.
|
||||
Uninitialized map has CU_COUNT 0. */
|
||||
struct mapped_debug_names final : public mapped_index_base
|
||||
@ -1763,28 +1664,6 @@ struct readnow_functions : public dwarf2_base_index_functions
|
||||
}
|
||||
};
|
||||
|
||||
struct dwarf2_gdb_index : public dwarf2_base_index_functions
|
||||
{
|
||||
void dump (struct objfile *objfile) override;
|
||||
|
||||
void expand_matching_symbols
|
||||
(struct objfile *,
|
||||
const lookup_name_info &lookup_name,
|
||||
domain_enum domain,
|
||||
int global,
|
||||
symbol_compare_ftype *ordered_compare) override;
|
||||
|
||||
bool expand_symtabs_matching
|
||||
(struct objfile *objfile,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
const lookup_name_info *lookup_name,
|
||||
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
domain_enum domain,
|
||||
enum search_domain kind) override;
|
||||
};
|
||||
|
||||
struct dwarf2_debug_names_index : public dwarf2_base_index_functions
|
||||
{
|
||||
void dump (struct objfile *objfile) override;
|
||||
@ -1807,12 +1686,6 @@ struct dwarf2_debug_names_index : public dwarf2_base_index_functions
|
||||
enum search_domain kind) override;
|
||||
};
|
||||
|
||||
quick_symbol_functions_up
|
||||
mapped_gdb_index::make_quick_functions () const
|
||||
{
|
||||
return quick_symbol_functions_up (new dwarf2_gdb_index);
|
||||
}
|
||||
|
||||
quick_symbol_functions_up
|
||||
mapped_debug_names::make_quick_functions () const
|
||||
{
|
||||
@ -1985,8 +1858,7 @@ dwarf2_per_bfd::allocate_signatured_type (ULONGEST signature)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return a new dwarf2_per_cu_data allocated on the per-bfd
|
||||
obstack, and constructed with the specified field values. */
|
||||
/* See read.h. */
|
||||
|
||||
dwarf2_per_cu_data_up
|
||||
create_cu_from_index_list (dwarf2_per_bfd *per_bfd,
|
||||
@ -2002,92 +1874,6 @@ create_cu_from_index_list (dwarf2_per_bfd *per_bfd,
|
||||
return the_cu;
|
||||
}
|
||||
|
||||
/* A helper for create_cus_from_index that handles a given list of
|
||||
CUs. */
|
||||
|
||||
static void
|
||||
create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
|
||||
const gdb_byte *cu_list, offset_type n_elements,
|
||||
struct dwarf2_section_info *section,
|
||||
int is_dwz)
|
||||
{
|
||||
for (offset_type i = 0; i < n_elements; i += 2)
|
||||
{
|
||||
gdb_static_assert (sizeof (ULONGEST) >= 8);
|
||||
|
||||
sect_offset sect_off
|
||||
= (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
|
||||
ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
|
||||
cu_list += 2 * 8;
|
||||
|
||||
dwarf2_per_cu_data_up per_cu
|
||||
= create_cu_from_index_list (per_bfd, section, is_dwz, sect_off,
|
||||
length);
|
||||
per_bfd->all_units.push_back (std::move (per_cu));
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the CU list from the mapped index, and use it to create all
|
||||
the CU objects for PER_BFD. */
|
||||
|
||||
static void
|
||||
create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
|
||||
const gdb_byte *cu_list, offset_type cu_list_elements,
|
||||
const gdb_byte *dwz_list, offset_type dwz_elements)
|
||||
{
|
||||
gdb_assert (per_bfd->all_units.empty ());
|
||||
per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
|
||||
|
||||
create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
|
||||
&per_bfd->info, 0);
|
||||
|
||||
if (dwz_elements == 0)
|
||||
return;
|
||||
|
||||
dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
|
||||
create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements,
|
||||
&dwz->info, 1);
|
||||
}
|
||||
|
||||
/* Create the signatured type hash table from the index. */
|
||||
|
||||
static void
|
||||
create_signatured_type_table_from_gdb_index
|
||||
(dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
|
||||
const gdb_byte *bytes, offset_type elements)
|
||||
{
|
||||
htab_up sig_types_hash = allocate_signatured_type_table ();
|
||||
|
||||
for (offset_type i = 0; i < elements; i += 3)
|
||||
{
|
||||
signatured_type_up sig_type;
|
||||
ULONGEST signature;
|
||||
void **slot;
|
||||
cu_offset type_offset_in_tu;
|
||||
|
||||
gdb_static_assert (sizeof (ULONGEST) >= 8);
|
||||
sect_offset sect_off
|
||||
= (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
|
||||
type_offset_in_tu
|
||||
= (cu_offset) extract_unsigned_integer (bytes + 8, 8,
|
||||
BFD_ENDIAN_LITTLE);
|
||||
signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
|
||||
bytes += 3 * 8;
|
||||
|
||||
sig_type = per_bfd->allocate_signatured_type (signature);
|
||||
sig_type->type_offset_in_tu = type_offset_in_tu;
|
||||
sig_type->section = section;
|
||||
sig_type->sect_off = sect_off;
|
||||
|
||||
slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
|
||||
*slot = sig_type.get ();
|
||||
|
||||
per_bfd->all_units.emplace_back (sig_type.release ());
|
||||
}
|
||||
|
||||
per_bfd->signatured_types = std::move (sig_types_hash);
|
||||
}
|
||||
|
||||
/* Create the signatured type hash table from .debug_names. */
|
||||
|
||||
static void
|
||||
@ -2136,59 +1922,6 @@ create_signatured_type_table_from_debug_names
|
||||
per_objfile->per_bfd->signatured_types = std::move (sig_types_hash);
|
||||
}
|
||||
|
||||
/* Read the address map data from the mapped GDB index, and use it to
|
||||
populate the index_addrmap. */
|
||||
|
||||
static void
|
||||
create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
|
||||
mapped_gdb_index *index)
|
||||
{
|
||||
struct objfile *objfile = per_objfile->objfile;
|
||||
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
|
||||
struct gdbarch *gdbarch = objfile->arch ();
|
||||
const gdb_byte *iter, *end;
|
||||
CORE_ADDR baseaddr;
|
||||
|
||||
addrmap_mutable mutable_map;
|
||||
|
||||
iter = index->address_table.data ();
|
||||
end = iter + index->address_table.size ();
|
||||
|
||||
baseaddr = objfile->text_section_offset ();
|
||||
|
||||
while (iter < end)
|
||||
{
|
||||
ULONGEST hi, lo, cu_index;
|
||||
lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
|
||||
iter += 8;
|
||||
hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
|
||||
iter += 8;
|
||||
cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
|
||||
iter += 4;
|
||||
|
||||
if (lo > hi)
|
||||
{
|
||||
complaint (_(".gdb_index address table has invalid range (%s - %s)"),
|
||||
hex_string (lo), hex_string (hi));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cu_index >= per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index address table has invalid CU number %u"),
|
||||
(unsigned) cu_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr;
|
||||
hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr;
|
||||
mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index));
|
||||
}
|
||||
|
||||
per_bfd->index_addrmap
|
||||
= new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack, &mutable_map);
|
||||
}
|
||||
|
||||
/* Read the address map data from DWARF-5 .debug_aranges, and use it
|
||||
to populate given addrmap. Returns true on success, false on
|
||||
failure. */
|
||||
@ -2389,222 +2122,6 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
|
||||
&mutable_map);
|
||||
}
|
||||
|
||||
/* A helper function that reads the .gdb_index from BUFFER and fills
|
||||
in MAP. FILENAME is the name of the file containing the data;
|
||||
it is used for error reporting. DEPRECATED_OK is true if it is
|
||||
ok to use deprecated sections.
|
||||
|
||||
CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are
|
||||
out parameters that are filled in with information about the CU and
|
||||
TU lists in the section.
|
||||
|
||||
Returns true if all went well, false otherwise. */
|
||||
|
||||
static bool
|
||||
read_gdb_index_from_buffer (const char *filename,
|
||||
bool deprecated_ok,
|
||||
gdb::array_view<const gdb_byte> buffer,
|
||||
mapped_gdb_index *map,
|
||||
const gdb_byte **cu_list,
|
||||
offset_type *cu_list_elements,
|
||||
const gdb_byte **types_list,
|
||||
offset_type *types_list_elements)
|
||||
{
|
||||
const gdb_byte *addr = &buffer[0];
|
||||
offset_view metadata (buffer);
|
||||
|
||||
/* Version check. */
|
||||
offset_type version = metadata[0];
|
||||
/* Versions earlier than 3 emitted every copy of a psymbol. This
|
||||
causes the index to behave very poorly for certain requests. Version 3
|
||||
contained incomplete addrmap. So, it seems better to just ignore such
|
||||
indices. */
|
||||
if (version < 4)
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("Skipping obsolete .gdb_index section in %s."),
|
||||
filename);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Index version 4 uses a different hash function than index version
|
||||
5 and later.
|
||||
|
||||
Versions earlier than 6 did not emit psymbols for inlined
|
||||
functions. Using these files will cause GDB not to be able to
|
||||
set breakpoints on inlined functions by name, so we ignore these
|
||||
indices unless the user has done
|
||||
"set use-deprecated-index-sections on". */
|
||||
if (version < 6 && !deprecated_ok)
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("\
|
||||
Skipping deprecated .gdb_index section in %s.\n\
|
||||
Do \"set use-deprecated-index-sections on\" before the file is read\n\
|
||||
to use the section anyway."),
|
||||
filename);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Version 7 indices generated by gold refer to the CU for a symbol instead
|
||||
of the TU (for symbols coming from TUs),
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
|
||||
Plus gold-generated indices can have duplicate entries for global symbols,
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=15646.
|
||||
These are just performance bugs, and we can't distinguish gdb-generated
|
||||
indices from gold-generated ones, so issue no warning here. */
|
||||
|
||||
/* Indexes with higher version than the one supported by GDB may be no
|
||||
longer backward compatible. */
|
||||
if (version > 8)
|
||||
return 0;
|
||||
|
||||
map->version = version;
|
||||
|
||||
int i = 1;
|
||||
*cu_list = addr + metadata[i];
|
||||
*cu_list_elements = (metadata[i + 1] - metadata[i]) / 8;
|
||||
++i;
|
||||
|
||||
*types_list = addr + metadata[i];
|
||||
*types_list_elements = (metadata[i + 1] - metadata[i]) / 8;
|
||||
++i;
|
||||
|
||||
const gdb_byte *address_table = addr + metadata[i];
|
||||
const gdb_byte *address_table_end = addr + metadata[i + 1];
|
||||
map->address_table
|
||||
= gdb::array_view<const gdb_byte> (address_table, address_table_end);
|
||||
++i;
|
||||
|
||||
const gdb_byte *symbol_table = addr + metadata[i];
|
||||
const gdb_byte *symbol_table_end = addr + metadata[i + 1];
|
||||
map->symbol_table
|
||||
= offset_view (gdb::array_view<const gdb_byte> (symbol_table,
|
||||
symbol_table_end));
|
||||
|
||||
++i;
|
||||
map->constant_pool = buffer.slice (metadata[i]);
|
||||
|
||||
if (map->constant_pool.empty () && !map->symbol_table.empty ())
|
||||
{
|
||||
/* An empty constant pool implies that all symbol table entries are
|
||||
empty. Make map->symbol_table.empty () == true. */
|
||||
map->symbol_table
|
||||
= offset_view (gdb::array_view<const gdb_byte> (symbol_table,
|
||||
symbol_table));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Callback types for dwarf2_read_gdb_index. */
|
||||
|
||||
typedef gdb::function_view
|
||||
<gdb::array_view<const gdb_byte>(objfile *, dwarf2_per_bfd *)>
|
||||
get_gdb_index_contents_ftype;
|
||||
typedef gdb::function_view
|
||||
<gdb::array_view<const gdb_byte>(objfile *, dwz_file *)>
|
||||
get_gdb_index_contents_dwz_ftype;
|
||||
|
||||
/* Read .gdb_index. If everything went ok, initialize the "quick"
|
||||
elements of all the CUs and return 1. Otherwise, return 0. */
|
||||
|
||||
static int
|
||||
dwarf2_read_gdb_index
|
||||
(dwarf2_per_objfile *per_objfile,
|
||||
get_gdb_index_contents_ftype get_gdb_index_contents,
|
||||
get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz)
|
||||
{
|
||||
const gdb_byte *cu_list, *types_list, *dwz_list = NULL;
|
||||
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
|
||||
struct dwz_file *dwz;
|
||||
struct objfile *objfile = per_objfile->objfile;
|
||||
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
|
||||
|
||||
gdb::array_view<const gdb_byte> main_index_contents
|
||||
= get_gdb_index_contents (objfile, per_bfd);
|
||||
|
||||
if (main_index_contents.empty ())
|
||||
return 0;
|
||||
|
||||
std::unique_ptr<mapped_gdb_index> map (new mapped_gdb_index);
|
||||
if (!read_gdb_index_from_buffer (objfile_name (objfile),
|
||||
use_deprecated_index_sections,
|
||||
main_index_contents, map.get (), &cu_list,
|
||||
&cu_list_elements, &types_list,
|
||||
&types_list_elements))
|
||||
return 0;
|
||||
|
||||
/* Don't use the index if it's empty. */
|
||||
if (map->symbol_table.empty ())
|
||||
return 0;
|
||||
|
||||
/* If there is a .dwz file, read it so we can get its CU list as
|
||||
well. */
|
||||
dwz = dwarf2_get_dwz_file (per_bfd);
|
||||
if (dwz != NULL)
|
||||
{
|
||||
mapped_gdb_index dwz_map;
|
||||
const gdb_byte *dwz_types_ignore;
|
||||
offset_type dwz_types_elements_ignore;
|
||||
|
||||
gdb::array_view<const gdb_byte> dwz_index_content
|
||||
= get_gdb_index_contents_dwz (objfile, dwz);
|
||||
|
||||
if (dwz_index_content.empty ())
|
||||
return 0;
|
||||
|
||||
if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.get ()),
|
||||
1, dwz_index_content, &dwz_map,
|
||||
&dwz_list, &dwz_list_elements,
|
||||
&dwz_types_ignore,
|
||||
&dwz_types_elements_ignore))
|
||||
{
|
||||
warning (_("could not read '.gdb_index' section from %s; skipping"),
|
||||
bfd_get_filename (dwz->dwz_bfd.get ()));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list,
|
||||
dwz_list_elements);
|
||||
|
||||
if (types_list_elements)
|
||||
{
|
||||
/* We can only handle a single .debug_types when we have an
|
||||
index. */
|
||||
if (per_bfd->types.size () > 1)
|
||||
{
|
||||
per_bfd->all_units.clear ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwarf2_section_info *section
|
||||
= (per_bfd->types.size () == 1
|
||||
? &per_bfd->types[0]
|
||||
: &per_bfd->info);
|
||||
|
||||
create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
|
||||
types_list_elements);
|
||||
}
|
||||
|
||||
finalize_all_units (per_bfd);
|
||||
|
||||
create_addrmap_from_gdb_index (per_objfile, map.get ());
|
||||
|
||||
per_bfd->index_table = std::move (map);
|
||||
per_bfd->quick_file_names_table =
|
||||
create_quick_file_names_table (per_bfd->all_units.size ());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* die_reader_func for dw2_get_file_names. */
|
||||
|
||||
static void
|
||||
@ -2796,150 +2313,6 @@ dwarf2_base_index_functions::forget_cached_source_info
|
||||
per_cu->free_cached_file_names ();
|
||||
}
|
||||
|
||||
/* Struct used to manage iterating over all CUs looking for a symbol. */
|
||||
|
||||
struct dw2_symtab_iterator
|
||||
{
|
||||
/* The dwarf2_per_objfile owning the CUs we are iterating on. */
|
||||
dwarf2_per_objfile *per_objfile;
|
||||
/* If set, only look for symbols that match that block. Valid values are
|
||||
GLOBAL_BLOCK and STATIC_BLOCK. */
|
||||
gdb::optional<block_enum> block_index;
|
||||
/* The kind of symbol we're looking for. */
|
||||
domain_enum domain;
|
||||
/* The list of CUs from the index entry of the symbol,
|
||||
or NULL if not found. */
|
||||
offset_view vec;
|
||||
/* The next element in VEC to look at. */
|
||||
int next;
|
||||
/* The number of elements in VEC, or zero if there is no match. */
|
||||
int length;
|
||||
/* Have we seen a global version of the symbol?
|
||||
If so we can ignore all further global instances.
|
||||
This is to work around gold/15646, inefficient gold-generated
|
||||
indices. */
|
||||
int global_seen;
|
||||
};
|
||||
|
||||
/* Initialize the index symtab iterator ITER, offset_type NAMEI variant. */
|
||||
|
||||
static void
|
||||
dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
|
||||
dwarf2_per_objfile *per_objfile,
|
||||
gdb::optional<block_enum> block_index,
|
||||
domain_enum domain, offset_type namei,
|
||||
mapped_gdb_index &index)
|
||||
{
|
||||
iter->per_objfile = per_objfile;
|
||||
iter->block_index = block_index;
|
||||
iter->domain = domain;
|
||||
iter->next = 0;
|
||||
iter->global_seen = 0;
|
||||
iter->vec = {};
|
||||
iter->length = 0;
|
||||
|
||||
gdb_assert (!index.symbol_name_slot_invalid (namei));
|
||||
offset_type vec_idx = index.symbol_vec_index (namei);
|
||||
|
||||
iter->vec = offset_view (index.constant_pool.slice (vec_idx));
|
||||
iter->length = iter->vec[0];
|
||||
}
|
||||
|
||||
/* Return the next matching CU or NULL if there are no more. */
|
||||
|
||||
static struct dwarf2_per_cu_data *
|
||||
dw2_symtab_iter_next (struct dw2_symtab_iterator *iter,
|
||||
mapped_gdb_index &index)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = iter->per_objfile;
|
||||
|
||||
for ( ; iter->next < iter->length; ++iter->next)
|
||||
{
|
||||
offset_type cu_index_and_attrs = iter->vec[iter->next + 1];
|
||||
offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
||||
gdb_index_symbol_kind symbol_kind =
|
||||
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
||||
/* Only check the symbol attributes if they're present.
|
||||
Indices prior to version 7 don't record them,
|
||||
and indices >= 7 may elide them for certain symbols
|
||||
(gold does this). */
|
||||
int attrs_valid = (index.version >= 7
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
||||
|
||||
/* Don't crash on bad data. */
|
||||
if (cu_index >= per_objfile->per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index entry has bad CU index"
|
||||
" [in module %s]"), objfile_name (per_objfile->objfile));
|
||||
continue;
|
||||
}
|
||||
|
||||
dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
|
||||
|
||||
/* Skip if already read in. */
|
||||
if (per_objfile->symtab_set_p (per_cu))
|
||||
continue;
|
||||
|
||||
/* Check static vs global. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
bool is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
||||
|
||||
if (iter->block_index.has_value ())
|
||||
{
|
||||
bool want_static = *iter->block_index == STATIC_BLOCK;
|
||||
|
||||
if (is_static != want_static)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Work around gold/15646. */
|
||||
if (!is_static
|
||||
&& symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
{
|
||||
if (iter->global_seen)
|
||||
continue;
|
||||
|
||||
iter->global_seen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only check the symbol's kind if it has one. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
switch (iter->domain)
|
||||
{
|
||||
case VAR_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
|
||||
/* Some types are also in VAR_DOMAIN. */
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case STRUCT_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case LABEL_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
case MODULE_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++iter->next;
|
||||
return per_cu;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
dwarf2_base_index_functions::print_stats (struct objfile *objfile,
|
||||
bool print_bcache)
|
||||
@ -2962,22 +2335,6 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
|
||||
gdb_printf (_(" Number of unread CUs: %d\n"), count);
|
||||
}
|
||||
|
||||
/* This dumps minimal information about the index.
|
||||
It is called via "mt print objfiles".
|
||||
One use is to verify .gdb_index has been loaded by the
|
||||
gdb.dwarf2/gdb-index.exp testcase. */
|
||||
|
||||
void
|
||||
dwarf2_gdb_index::dump (struct objfile *objfile)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
mapped_gdb_index *index = (gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
gdb_printf (".gdb_index: version %d\n", index->version);
|
||||
gdb_printf ("\n");
|
||||
}
|
||||
|
||||
void
|
||||
dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
|
||||
{
|
||||
@ -2997,44 +2354,6 @@ dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dwarf2_gdb_index::expand_matching_symbols
|
||||
(struct objfile *objfile,
|
||||
const lookup_name_info &name, domain_enum domain,
|
||||
int global,
|
||||
symbol_compare_ftype *ordered_compare)
|
||||
{
|
||||
/* Used for Ada. */
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
|
||||
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
const char *match_name = name.ada ().lookup_name ().c_str ();
|
||||
auto matcher = [&] (const char *symname)
|
||||
{
|
||||
if (ordered_compare == nullptr)
|
||||
return true;
|
||||
return ordered_compare (symname, match_name) == 0;
|
||||
};
|
||||
|
||||
dw2_expand_symtabs_matching_symbol (index, name, matcher,
|
||||
[&] (offset_type namei)
|
||||
{
|
||||
struct dw2_symtab_iterator iter;
|
||||
struct dwarf2_per_cu_data *per_cu;
|
||||
|
||||
dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain, namei,
|
||||
index);
|
||||
while ((per_cu = dw2_symtab_iter_next (&iter, index)) != NULL)
|
||||
dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
|
||||
nullptr);
|
||||
return true;
|
||||
}, per_objfile);
|
||||
}
|
||||
|
||||
/* Starting from a search name, return the string that finds the upper
|
||||
bound of all strings that start with SEARCH_NAME in a sorted name
|
||||
@ -3837,107 +3156,6 @@ dw2_expand_symtabs_matching_one
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Helper for dw2_expand_matching symtabs. Called on each symbol
|
||||
matched, to expand corresponding CUs that were marked. IDX is the
|
||||
index of the symbol name that matched. */
|
||||
|
||||
static bool
|
||||
dw2_expand_marked_cus
|
||||
(dwarf2_per_objfile *per_objfile, offset_type idx,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
search_domain kind)
|
||||
{
|
||||
offset_type vec_len, vec_idx;
|
||||
bool global_seen = false;
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
|
||||
vec_len = vec[0];
|
||||
for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
|
||||
{
|
||||
offset_type cu_index_and_attrs = vec[vec_idx + 1];
|
||||
/* This value is only valid for index versions >= 7. */
|
||||
int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
||||
gdb_index_symbol_kind symbol_kind =
|
||||
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
||||
int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
||||
/* Only check the symbol attributes if they're present.
|
||||
Indices prior to version 7 don't record them,
|
||||
and indices >= 7 may elide them for certain symbols
|
||||
(gold does this). */
|
||||
int attrs_valid =
|
||||
(index.version >= 7
|
||||
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
||||
|
||||
/* Work around gold/15646. */
|
||||
if (attrs_valid
|
||||
&& !is_static
|
||||
&& symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
{
|
||||
if (global_seen)
|
||||
continue;
|
||||
|
||||
global_seen = true;
|
||||
}
|
||||
|
||||
/* Only check the symbol's kind if it has one. */
|
||||
if (attrs_valid)
|
||||
{
|
||||
if (is_static)
|
||||
{
|
||||
if ((search_flags & SEARCH_STATIC_BLOCK) == 0)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case VARIABLES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
|
||||
continue;
|
||||
break;
|
||||
case FUNCTIONS_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
|
||||
continue;
|
||||
break;
|
||||
case TYPES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
||||
continue;
|
||||
break;
|
||||
case MODULES_DOMAIN:
|
||||
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't crash on bad data. */
|
||||
if (cu_index >= per_objfile->per_bfd->all_units.size ())
|
||||
{
|
||||
complaint (_(".gdb_index entry has bad CU index"
|
||||
" [in module %s]"), objfile_name (per_objfile->objfile));
|
||||
continue;
|
||||
}
|
||||
|
||||
dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
|
||||
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
|
||||
expansion_notify))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See read.h. */
|
||||
|
||||
void
|
||||
@ -4037,55 +3255,6 @@ dw_expand_symtabs_matching_file_matcher
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
dwarf2_gdb_index::expand_symtabs_matching
|
||||
(struct objfile *objfile,
|
||||
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
|
||||
const lookup_name_info *lookup_name,
|
||||
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
|
||||
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
|
||||
block_search_flags search_flags,
|
||||
domain_enum domain,
|
||||
enum search_domain kind)
|
||||
{
|
||||
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
||||
|
||||
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
|
||||
|
||||
/* This invariant is documented in quick-functions.h. */
|
||||
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
|
||||
if (lookup_name == nullptr)
|
||||
{
|
||||
for (dwarf2_per_cu_data *per_cu
|
||||
: all_units_range (per_objfile->per_bfd))
|
||||
{
|
||||
QUIT;
|
||||
|
||||
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
|
||||
file_matcher,
|
||||
expansion_notify))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mapped_gdb_index &index
|
||||
= *(gdb::checked_static_cast<mapped_gdb_index *>
|
||||
(per_objfile->per_bfd->index_table.get ()));
|
||||
|
||||
bool result
|
||||
= dw2_expand_symtabs_matching_symbol (index, *lookup_name,
|
||||
symbol_matcher,
|
||||
[&] (offset_type idx)
|
||||
{
|
||||
if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
|
||||
expansion_notify, search_flags, kind))
|
||||
return false;
|
||||
return true;
|
||||
}, per_objfile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
|
||||
symtab. */
|
||||
@ -23778,18 +22947,6 @@ the demangler."),
|
||||
NULL, show_check_physname,
|
||||
&setdebuglist, &showdebuglist);
|
||||
|
||||
add_setshow_boolean_cmd ("use-deprecated-index-sections",
|
||||
no_class, &use_deprecated_index_sections, _("\
|
||||
Set whether to use deprecated gdb_index sections."), _("\
|
||||
Show whether to use deprecated gdb_index sections."), _("\
|
||||
When enabled, deprecated .gdb_index sections are used anyway.\n\
|
||||
Normally they are ignored either because of a missing feature or\n\
|
||||
performance issue.\n\
|
||||
Warning: This option must be enabled before gdb reads the file."),
|
||||
NULL,
|
||||
NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
dwarf2_locexpr_index = register_symbol_computed_impl (LOC_COMPUTED,
|
||||
&dwarf2_locexpr_funcs);
|
||||
dwarf2_loclist_index = register_symbol_computed_impl (LOC_COMPUTED,
|
||||
|
Loading…
x
Reference in New Issue
Block a user