/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2021 Free Software Foundation, Inc.
+ Copyright (C) 1994-2022 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "block.h"
#include "addrmap.h"
#include "typeprint.h"
-#include "psympriv.h"
#include "c-lang.h"
#include "go-lang.h"
#include "valprint.h"
#include "gdbsupport/pathstuff.h"
#include "count-one-bits.h"
#include <unordered_set>
+#include "dwarf2/abbrev-cache.h"
+#include "cooked-index.h"
+#include "split-name.h"
+#include "gdbsupport/parallel-for.h"
+#include "gdbsupport/thread-pool.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
/* Size of .debug_rnglists section header for 64-bit DWARF format. */
#define RNGLIST_HEADER_SIZE64 20
-/* An index into a (C++) symbol name component in a symbol name as
- recorded in the mapped_index's symbol table. For each C++ symbol
- in the symbol table, we record one entry for the start of each
- component in the symbol in a table of name components, and then
- sort the table, in order to be able to binary search symbol names,
- ignoring leading namespaces, both completion and regular look up.
- For example, for symbol "A::B::C", we'll have an entry that points
- to "A::B::C", another that points to "B::C", and another for "C".
- Note that function symbols in GDB index have no parameter
- information, just the function/method names. You can convert a
- name_component to a "const char *" using the
- 'mapped_index::symbol_name_at(offset_type)' method. */
-
-struct name_component
-{
- /* Offset in the symbol name where the component starts. Stored as
- a (32-bit) offset instead of a pointer to save memory and improve
- locality on 64-bit architectures. */
- offset_type name_offset;
-
- /* The symbol's index in the symbol and constant pool tables of a
- mapped_index. */
- offset_type idx;
-};
-
-/* Base class containing bits shared by both .gdb_index and
- .debug_name indexes. */
-
-struct mapped_index_base
-{
- mapped_index_base () = default;
- DISABLE_COPY_AND_ASSIGN (mapped_index_base);
-
- /* The name_component table (a sorted vector). See name_component's
- description above. */
- std::vector<name_component> name_components;
-
- /* How NAME_COMPONENTS is sorted. */
- enum case_sensitivity name_components_casing;
-
- /* Return the number of names in the symbol table. */
- virtual size_t symbol_name_count () const = 0;
-
- /* Get the name of the symbol at IDX in the symbol table. */
- virtual const char *symbol_name_at
- (offset_type idx, dwarf2_per_objfile *per_objfile) const = 0;
-
- /* Return whether the name at IDX in the symbol table should be
- ignored. */
- virtual bool symbol_name_slot_invalid (offset_type idx) const
- {
- return false;
- }
-
- /* Build the symbol name component sorted vector, if we haven't
- yet. */
- void build_name_components (dwarf2_per_objfile *per_objfile);
-
- /* Returns the lower (inclusive) and upper (exclusive) bounds of the
- possible matches for LN_NO_PARAMS in the name component
- vector. */
- std::pair<std::vector<name_component>::const_iterator,
- std::vector<name_component>::const_iterator>
- find_name_components_bounds (const lookup_name_info &ln_no_params,
- enum language lang,
- dwarf2_per_objfile *per_objfile) const;
-
- /* Prevent deleting/destroying via a base class pointer. */
-protected:
- ~mapped_index_base() = default;
-};
-
/* 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. */
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.
size_t symbol_name_count () const override
{ return this->name_count; }
+
+ quick_symbol_functions_up make_quick_functions () const override;
};
-/* See dwarf2read.h. */
+/* See dwarf2/read.h. */
dwarf2_per_objfile *
get_dwarf2_per_objfile (struct objfile *objfile)
that can be shared across objfiles. The non-shareable parts are in
type_unit_group_unshareable. */
-struct type_unit_group : public dwarf2_per_cu_data
+struct type_unit_group
{
- /* The TUs that share this DW_AT_stmt_list entry.
- This is added to while parsing type units to build partial symtabs,
- and is deleted afterwards and not used again. */
- std::vector<signatured_type *> *tus = nullptr;
-
/* The data used to construct the hash key. */
struct stmt_list_hash hash {};
};
dwarf2_per_objfile *per_objfile,
struct abbrev_table *abbrev_table,
dwarf2_cu *existing_cu,
- bool skip_partial);
+ bool skip_partial,
+ abbrev_cache *cache = nullptr);
explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
DISABLE_COPY_AND_ASSIGN (cutu_reader);
+ cutu_reader (cutu_reader &&) = default;
+
const gdb_byte *info_ptr = nullptr;
struct die_info *comp_unit_die = nullptr;
bool dummy_p = false;
for dummy CUs. */
void keep ();
+ /* Release the abbrev table, transferring ownership to the
+ caller. */
+ abbrev_table_up release_abbrev_table ()
+ {
+ return std::move (m_abbrev_table_holder);
+ }
+
private:
void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
abbrev_table_up m_dwo_abbrev_table;
};
-/* When we construct a partial symbol table entry we only
- need this much information. */
-struct partial_die_info : public allocate_on_obstack
- {
- partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev);
-
- /* Disable assign but still keep copy ctor, which is needed
- load_partial_dies. */
- partial_die_info& operator=(const partial_die_info& rhs) = delete;
- partial_die_info (const partial_die_info &) = default;
-
- /* Adjust the partial die before generating a symbol for it. This
- function may set the is_external flag or change the DIE's
- name. */
- void fixup (struct dwarf2_cu *cu);
-
- /* Read a minimal amount of information into the minimal die
- structure. */
- const gdb_byte *read (const struct die_reader_specs *reader,
- const struct abbrev_info &abbrev,
- const gdb_byte *info_ptr);
-
- /* Compute the name of this partial DIE. This memoizes the
- result, so it is safe to call multiple times. */
- const char *name (dwarf2_cu *cu);
-
- /* Offset of this DIE. */
- const sect_offset sect_off;
-
- /* DWARF-2 tag for this DIE. */
- const ENUM_BITFIELD(dwarf_tag) tag : 16;
-
- /* Assorted flags describing the data found in this DIE. */
- const unsigned int has_children : 1;
-
- unsigned int is_external : 1;
- unsigned int is_declaration : 1;
- unsigned int has_type : 1;
- unsigned int has_specification : 1;
- unsigned int has_pc_info : 1;
- unsigned int has_range_info : 1;
- unsigned int may_be_inlined : 1;
-
- /* This DIE has been marked DW_AT_main_subprogram. */
- unsigned int main_subprogram : 1;
-
- /* Flag set if the SCOPE field of this structure has been
- computed. */
- unsigned int scope_set : 1;
-
- /* Flag set if the DIE has a byte_size attribute. */
- unsigned int has_byte_size : 1;
-
- /* Flag set if the DIE has a DW_AT_const_value attribute. */
- unsigned int has_const_value : 1;
-
- /* Flag set if any of the DIE's children are template arguments. */
- unsigned int has_template_arguments : 1;
-
- /* Flag set if fixup has been called on this die. */
- unsigned int fixup_called : 1;
-
- /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */
- unsigned int is_dwz : 1;
-
- /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt. */
- unsigned int spec_is_dwz : 1;
-
- unsigned int canonical_name : 1;
-
- /* The name of this DIE. Normally the value of DW_AT_name, but
- sometimes a default name for unnamed DIEs. */
- const char *raw_name = nullptr;
-
- /* The linkage name, if present. */
- const char *linkage_name = nullptr;
-
- /* The scope to prepend to our children. This is generally
- allocated on the comp_unit_obstack, so will disappear
- when this compilation unit leaves the cache. */
- const char *scope = nullptr;
-
- /* Some data associated with the partial DIE. The tag determines
- which field is live. */
- union
- {
- /* The location description associated with this DIE, if any. */
- struct dwarf_block *locdesc;
- /* The offset of an import, for DW_TAG_imported_unit. */
- sect_offset sect_off;
- } d {};
-
- union
- {
- /* If HAS_PC_INFO, the PC range associated with this DIE. */
- struct
- {
- CORE_ADDR lowpc;
- CORE_ADDR highpc;
- };
- /* If HAS_RANGE_INFO, the ranges offset associated with this DIE. */
- ULONGEST ranges_offset;
- };
-
- /* Pointer into the info_buffer (or types_buffer) pointing at the target of
- DW_AT_sibling, if any. */
- /* NOTE: This member isn't strictly necessary, partial_die_info::read
- could return DW_AT_sibling values to its caller load_partial_dies. */
- const gdb_byte *sibling = nullptr;
-
- /* If HAS_SPECIFICATION, the offset of the DIE referred to by
- DW_AT_specification (or DW_AT_abstract_origin or
- DW_AT_extension). */
- sect_offset spec_offset {};
-
- /* Pointers to this DIE's parent, first child, and next sibling,
- if any. */
- struct partial_die_info *die_parent = nullptr;
- struct partial_die_info *die_child = nullptr;
- struct partial_die_info *die_sibling = nullptr;
-
- friend struct partial_die_info *
- dwarf2_cu::find_partial_die (sect_offset sect_off);
-
- private:
- /* Only need to do look up in dwarf2_cu::find_partial_die. */
- partial_die_info (sect_offset sect_off)
- : partial_die_info (sect_off, DW_TAG_padding, 0)
- {
- }
-
- partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_,
- int has_children_)
- : sect_off (sect_off_), tag (tag_), has_children (has_children_)
- {
- is_external = 0;
- is_declaration = 0;
- has_type = 0;
- has_specification = 0;
- has_pc_info = 0;
- has_range_info = 0;
- may_be_inlined = 0;
- main_subprogram = 0;
- scope_set = 0;
- has_byte_size = 0;
- has_const_value = 0;
- has_template_arguments = 0;
- fixup_called = 0;
- is_dwz = 0;
- spec_is_dwz = 0;
- canonical_name = 0;
- /* Don't set these using NSDMI (Non-static data member initialisation),
- because g++-4.8 will error out. */
- lowpc = 0;
- highpc = 0;
- }
- };
-
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
but this would require a corresponding change in unpack_field_as_long
and friends. */
show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("The upper bound on the age of cached "
- "DWARF compilation units is %s.\n"),
- value);
+ gdb_printf (file, _("The upper bound on the age of cached "
+ "DWARF compilation units is %s.\n"),
+ value);
}
\f
/* local function prototypes */
static void dwarf2_find_base_address (struct die_info *die,
struct dwarf2_cu *cu);
-static dwarf2_psymtab *create_partial_symtab
- (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
- const char *name);
-
-static void build_type_psymtabs_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *type_unit_die);
+class cooked_index_storage;
+static void build_type_psymtabs_reader (cutu_reader *reader,
+ cooked_index_storage *storage);
static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
-static void scan_partial_symbols (struct partial_die_info *,
- CORE_ADDR *, CORE_ADDR *,
- int, struct dwarf2_cu *);
-
-static void add_partial_symbol (struct partial_die_info *,
- struct dwarf2_cu *);
-
-static void add_partial_namespace (struct partial_die_info *pdi,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int set_addrmap, struct dwarf2_cu *cu);
-
-static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int set_addrmap,
- struct dwarf2_cu *cu);
-
-static void add_partial_enumeration (struct partial_die_info *enum_pdi,
- struct dwarf2_cu *cu);
-
-static void add_partial_subprogram (struct partial_die_info *pdi,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu);
-
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
-static struct partial_die_info *load_partial_dies
- (const struct die_reader_specs *, const gdb_byte *, int);
-
-/* A pair of partial_die_info and compilation unit. */
-struct cu_partial_die_info
-{
- /* The compilation unit of the partial_die_info. */
- struct dwarf2_cu *cu;
- /* A partial_die_info. */
- struct partial_die_info *pdi;
-
- cu_partial_die_info (struct dwarf2_cu *cu, struct partial_die_info *pdi)
- : cu (cu),
- pdi (pdi)
- { /* Nothing. */ }
-
-private:
- cu_partial_die_info () = delete;
-};
-
-static const struct cu_partial_die_info find_partial_die (sect_offset, int,
- struct dwarf2_cu *);
-
static const gdb_byte *read_attribute (const struct die_reader_specs *,
struct attribute *,
const struct attr_abbrev *,
static line_header_up dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu);
-struct file_and_directory;
static void dwarf_decode_lines (struct line_header *,
- const file_and_directory &,
- struct dwarf2_cu *, dwarf2_psymtab *,
+ struct dwarf2_cu *,
CORE_ADDR, int decode_mapping);
static void dwarf2_start_subfile (struct dwarf2_cu *, const char *,
static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *,
- dwarf2_psymtab *);
+ addrmap *,
+ void *);
static void get_scope_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *,
static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
- const struct abbrev_info *abbrev);
-
-static hashval_t partial_die_hash (const void *item);
-
-static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+ const struct abbrev_info *abbrev,
+ bool do_skip_children = true);
static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
(sect_offset sect_off, unsigned int offset_in_dwz,
- dwarf2_per_objfile *per_objfile);
+ dwarf2_per_bfd *per_bfd);
static void prepare_one_comp_unit (struct dwarf2_cu *cu,
struct die_info *comp_unit_die,
delete data;
}
-/* The return type of find_file_and_directory. Note, the enclosed
- string pointers are only valid while this object is valid. */
-
-struct file_and_directory
-{
- /* The filename. This is never NULL. */
- const char *name;
-
- /* The compilation directory. NULL if not known. If we needed to
- compute a new string, it will be stored in the per-BFD string
- bcache; otherwise, points directly to the DW_AT_comp_dir string
- attribute owned by the obstack that owns the DIE. */
- const char *comp_dir;
-};
-
-static file_and_directory find_file_and_directory (struct die_info *die,
- struct dwarf2_cu *cu);
+static file_and_directory &find_file_and_directory
+ (struct die_info *die, struct dwarf2_cu *cu);
static const char *compute_include_file_name
(const struct line_header *lh,
const file_entry &fe,
const file_and_directory &cu_info,
- gdb::unique_xmalloc_ptr<char> *name_holder);
+ std::string &name_holder);
static htab_up allocate_signatured_type_table ();
*sizep = info->size;
}
+/* See dwarf2/read.h. */
+
+void
+dwarf2_per_bfd::map_info_sections (struct objfile *objfile)
+{
+ info.read (objfile);
+ abbrev.read (objfile);
+ line.read (objfile);
+ str.read (objfile);
+ str_offsets.read (objfile);
+ line_str.read (objfile);
+ ranges.read (objfile);
+ rnglists.read (objfile);
+ addr.read (objfile);
+
+ for (auto §ion : types)
+ section.read (objfile);
+}
+
\f
/* DWARF quick_symbol_functions support. */
const char **real_names;
};
-/* When using the index (and thus not using psymtabs), each CU has an
- object of this type. This is used to hold information needed by
- the various "quick" methods. */
-struct dwarf2_per_cu_quick_data
-{
- /* The file table. This can be NULL if there was no file table
- or it's currently not read in.
- NOTE: This points into dwarf2_per_objfile->per_bfd->quick_file_names_table. */
- struct quick_file_names *file_names;
-
- /* A temporary mark bit used when iterating over all CUs in
- expand_symtabs_matching. */
- unsigned int mark : 1;
-
- /* True if we've tried to read the file table. There will be no
- point in trying to read it again next time. */
- bool files_read : 1;
-};
-
-/* A subclass of psymbol_functions that arranges to read the DWARF
- partial symbols when needed. */
-struct lazy_dwarf_reader : public psymbol_functions
-{
- using psymbol_functions::psymbol_functions;
-
- bool can_lazily_read_symbols () override
- {
- return true;
- }
-
- void read_partial_symbols (struct objfile *objfile) override
- {
- if (dwarf2_has_info (objfile, nullptr))
- dwarf2_build_psymtabs (objfile, this);
- }
-};
-
-static quick_symbol_functions_up
-make_lazy_dwarf_reader ()
-{
- return quick_symbol_functions_up (new lazy_dwarf_reader);
-}
-
struct dwarf2_base_index_functions : public quick_symbol_functions
{
bool has_symbols (struct objfile *objfile) override;
bool need_fullname) override;
};
+/* With OBJF_READNOW, the DWARF reader expands all CUs immediately.
+ It's handy in this case to have an empty implementation of the
+ quick symbol functions, to avoid special cases in the rest of the
+ code. */
+
+struct readnow_functions : 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
+ {
+ return true;
+ }
+};
+
struct dwarf2_gdb_index : public dwarf2_base_index_functions
{
void dump (struct objfile *objfile) override;
enum search_domain kind) override;
};
-static quick_symbol_functions_up
-make_dwarf_gdb_index ()
+quick_symbol_functions_up
+mapped_index::make_quick_functions () const
{
return quick_symbol_functions_up (new dwarf2_gdb_index);
}
-static quick_symbol_functions_up
-make_dwarf_debug_names ()
+quick_symbol_functions_up
+mapped_debug_names::make_quick_functions () const
{
return quick_symbol_functions_up (new dwarf2_debug_names_index);
}
dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile, bool skip_partial)
{
- /* Skip type_unit_groups, reading the type units they contain
- is handled elsewhere. */
- if (per_cu->type_unit_group_p ())
- return;
-
{
/* The destructor of dwarf2_queue_guard frees any entries left on
the queue. After this point we're guaranteed to leave this function
&& cu != NULL
&& cu->dwo_unit != NULL
&& per_objfile->per_bfd->index_table != NULL
- && per_objfile->per_bfd->index_table->version <= 7
+ && !per_objfile->per_bfd->index_table->version_check ()
/* DWP files aren't supported yet. */
&& get_dwp_file (per_objfile) == NULL)
queue_and_load_all_dwo_tus (cu);
dwarf2_per_objfile *per_objfile,
bool skip_partial)
{
- gdb_assert (per_objfile->per_bfd->using_index);
-
if (!per_objfile->symtab_set_p (per_cu))
{
free_cached_comp_units freer (per_objfile);
the_cu->sect_off = sect_off;
the_cu->length = length;
the_cu->section = section;
- the_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
the_cu->is_dwz = is_dwz;
return the_cu;
}
sig_type->type_offset_in_tu = type_offset_in_tu;
sig_type->section = section;
sig_type->sect_off = sect_off;
- sig_type->v.quick
- = OBSTACK_ZALLOC (&per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
*slot = sig_type.get ();
sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
sig_type->section = section;
sig_type->sect_off = sect_off;
- sig_type->v.quick
- = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
*slot = sig_type.get ();
&per_bfd->obstack);
}
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
- populate the psymtabs_addrmap. */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it
+ to populate given addrmap. Returns true on success, false on
+ failure. */
-static void
-create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
- struct dwarf2_section_info *section)
+static bool
+read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+ struct dwarf2_section_info *section,
+ addrmap *mutable_map)
{
struct objfile *objfile = per_objfile->objfile;
bfd *abfd = objfile->obfd;
const CORE_ADDR baseaddr = objfile->text_section_offset ();
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- auto_obstack temp_obstack;
- addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
-
std::unordered_map<sect_offset,
dwarf2_per_cu_data *,
gdb::hash_enum<sect_offset>>
{
/* A TU will not need aranges, and skipping them here is an easy
way of ignoring .debug_types -- and possibly seeing a
- duplicate section offset -- entirely. */
- if (per_cu->is_debug_types)
+ duplicate section offset -- entirely. The same applies to
+ units coming from a dwz file. */
+ if (per_cu->is_debug_types || per_cu->is_dwz)
continue;
const auto insertpair
warning (_("Section .debug_aranges in %s has duplicate "
"debug_info_offset %s, ignoring .debug_aranges."),
objfile_name (objfile), sect_offset_str (per_cu->sect_off));
- return;
+ return false;
}
}
plongest (entry_addr - section->buffer),
plongest (bytes_read + entry_length),
pulongest (section->size));
- return;
+ return false;
}
/* The version number. */
"has unsupported version %d, ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer), version);
- return;
+ return false;
}
const uint64_t debug_info_offset
objfile_name (objfile),
plongest (entry_addr - section->buffer),
pulongest (debug_info_offset));
- return;
+ return false;
}
dwarf2_per_cu_data *const per_cu = per_cu_it->second;
"address_size %u is invalid, ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer), address_size);
- return;
+ return false;
}
const uint8_t segment_selector_size = *addr++;
objfile_name (objfile),
plongest (entry_addr - section->buffer),
segment_selector_size);
- return;
+ return false;
}
/* Must pad to an alignment boundary that is twice the address
bytes. */
addr += (entry_end - addr) % (2 * address_size);
- for (;;)
+ while (addr < entry_end)
{
if (addr + 2 * address_size > entry_end)
{
"ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer));
- return;
+ return false;
}
ULONGEST start = extract_unsigned_integer (addr, address_size,
dwarf5_byte_order);
dwarf5_byte_order);
addr += address_size;
if (start == 0 && length == 0)
- break;
+ {
+ /* This can happen on some targets with --gc-sections.
+ This pair of values is also used to mark the end of
+ the entries for a given CU, but we ignore it and
+ instead handle termination using the check at the top
+ of the loop. */
+ continue;
+ }
if (start == 0 && !per_bfd->has_section_at_zero)
{
/* Symbol was eliminated due to a COMDAT group. */
- baseaddr);
addrmap_set_empty (mutable_map, start, end - 1, per_cu);
}
+
+ per_cu->addresses_seen = true;
}
- per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
- &per_bfd->obstack);
+ return true;
+}
+
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+ populate the psymtabs_addrmap. */
+
+static void
+create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+ struct dwarf2_section_info *section)
+{
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+
+ auto_obstack temp_obstack;
+ addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+ if (read_addrmap_from_aranges (per_objfile, section, mutable_map))
+ per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+ &per_bfd->obstack);
}
/* A helper function that reads the .gdb_index from BUFFER and fills
create_addrmap_from_index (per_objfile, map.get ());
per_bfd->index_table = std::move (map);
- per_bfd->using_index = 1;
per_bfd->quick_file_names_table =
create_quick_file_names_table (per_bfd->all_comp_units.size ());
gdb_assert (! this_cu->is_debug_types);
- this_cu->v.quick->files_read = true;
+ this_cu->files_read = true;
/* Our callers never want to match partial units -- instead they
will match the enclosing full CU. */
if (comp_unit_die->tag == DW_TAG_partial_unit)
&find_entry, INSERT);
if (*slot != NULL)
{
- lh_cu->v.quick->file_names = (struct quick_file_names *) *slot;
+ lh_cu->file_names = (struct quick_file_names *) *slot;
return;
}
lh = dwarf_decode_line_header (line_offset, cu);
}
- file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
+ file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
int offset = 0;
- if (strcmp (fnd.name, "<unknown>") != 0)
+ if (!fnd.is_unknown ())
++offset;
else if (lh == nullptr)
return;
{
for (const auto &entry : lh->file_names ())
{
- gdb::unique_xmalloc_ptr<char> name_holder;
+ std::string name_holder;
const char *include_name =
- compute_include_file_name (lh.get (), entry, fnd, &name_holder);
+ compute_include_file_name (lh.get (), entry, fnd, name_holder);
if (include_name != nullptr)
{
include_name = per_objfile->objfile->intern (include_name);
}
qfn->num_file_names = offset + include_names.size ();
- qfn->comp_dir = fnd.comp_dir;
+ qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile);
qfn->file_names =
XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
qfn->num_file_names);
if (offset != 0)
- qfn->file_names[0] = xstrdup (fnd.name);
+ qfn->file_names[0] = xstrdup (fnd.get_name ());
if (!include_names.empty ())
memcpy (&qfn->file_names[offset], include_names.data (),
qfn->real_names = NULL;
- lh_cu->v.quick->file_names = qfn;
+ lh_cu->file_names = qfn;
}
/* A helper for the "quick" functions which attempts to read the line
{
/* This should never be called for TUs. */
gdb_assert (! this_cu->is_debug_types);
- /* Nor type unit groups. */
- gdb_assert (! this_cu->type_unit_group_p ());
- if (this_cu->v.quick->files_read)
- return this_cu->v.quick->file_names;
+ if (this_cu->files_read)
+ return this_cu->file_names;
cutu_reader reader (this_cu, per_objfile);
if (!reader.dummy_p)
dw2_get_file_names_reader (&reader, reader.comp_unit_die);
- return this_cu->v.quick->file_names;
+ return this_cu->file_names;
}
/* A helper for the "quick" functions which computes and caches the
if (cust == NULL)
return NULL;
- return compunit_primary_filetab (cust);
+ return cust->primary_filetab ();
}
/* See read.h. */
void
dwarf2_per_cu_data::free_cached_file_names ()
{
- if (per_bfd == nullptr || !per_bfd->using_index || v.quick == nullptr)
+ if (fnd != nullptr)
+ fnd->forget_fullname ();
+
+ if (per_bfd == nullptr)
return;
- struct quick_file_names *file_data = v.quick->file_names;
+ struct quick_file_names *file_data = file_names;
if (file_data != nullptr && file_data->real_names != nullptr)
{
for (int i = 0; i < file_data->num_file_names; ++i)
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)
+ domain_enum domain, offset_type namei,
+ mapped_index &index)
{
iter->per_objfile = per_objfile;
iter->block_index = block_index;
iter->vec = {};
iter->length = 0;
- mapped_index *index = per_objfile->per_bfd->index_table.get ();
- /* index is NULL if OBJF_READNOW. */
- if (index == NULL)
- return;
-
- gdb_assert (!index->symbol_name_slot_invalid (namei));
- offset_type vec_idx = index->symbol_vec_index (namei);
+ 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->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)
+dw2_symtab_iter_next (struct dw2_symtab_iterator *iter,
+ mapped_index &index)
{
dwarf2_per_objfile *per_objfile = iter->per_objfile;
Indices prior to version 7 don't record them,
and indices >= 7 may elide them for certain symbols
(gold does this). */
- int attrs_valid =
- (per_objfile->per_bfd->index_table->version >= 7
- && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+ 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_comp_units.size ())
if (!per_objfile->symtab_set_p (per_cu))
++count;
}
- printf_filtered (_(" Number of read CUs: %d\n"), total - count);
- printf_filtered (_(" Number of unread CUs: %d\n"), count);
+ gdb_printf (_(" Number of read CUs: %d\n"), total - count);
+ gdb_printf (_(" Number of unread CUs: %d\n"), count);
}
/* This dumps minimal information about the index.
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- gdb_assert (per_objfile->per_bfd->using_index);
- printf_filtered (".gdb_index:");
- if (per_objfile->per_bfd->index_table != NULL)
- {
- printf_filtered (" version %d\n",
- per_objfile->per_bfd->index_table->version);
- }
- else
- printf_filtered (" faked for \"readnow\"\n");
- printf_filtered ("\n");
+ mapped_index *index = (static_cast<mapped_index *>
+ (per_objfile->per_bfd->index_table.get ()));
+ gdb_printf (".gdb_index: version %d\n", index->version);
+ gdb_printf ("\n");
}
void
const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
- if (per_objfile->per_bfd->index_table != nullptr)
- {
- mapped_index &index = *per_objfile->per_bfd->index_table;
+ mapped_index &index
+ = (static_cast<mapped_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;
- };
+ 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);
- while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
- dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
- nullptr);
- return true;
- }, per_objfile);
- }
- else
+ dw2_expand_symtabs_matching_symbol (index, name, matcher,
+ [&] (offset_type namei)
{
- /* We have -readnow: no .gdb_index, but no partial symtabs either. So,
- proceed assuming all symtabs have been read in. */
- }
+ 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
return m_symbol_table[idx];
}
+ quick_symbol_functions_up make_quick_functions () const override
+ {
+ return nullptr;
+ }
+
private:
gdb::array_view<const char *> m_symbol_table;
};
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify)
{
- if (file_matcher == NULL || per_cu->v.quick->mark)
+ if (file_matcher == NULL || per_cu->mark)
{
bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
{
offset_type vec_len, vec_idx;
bool global_seen = false;
- mapped_index &index = *per_objfile->per_bfd->index_table;
+ mapped_index &index
+ = (static_cast<mapped_index &>
+ (*per_objfile->per_bfd->index_table.get ()));
offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
vec_len = vec[0];
if (per_cu->is_debug_types)
continue;
- per_cu->v.quick->mark = 0;
+ per_cu->mark = 0;
/* We only need to look at symtabs not already expanded. */
if (per_objfile->symtab_set_p (per_cu.get ()))
continue;
+ if (per_cu->fnd != nullptr)
+ {
+ file_and_directory *fnd = per_cu->fnd.get ();
+
+ if (file_matcher (fnd->get_name (), false))
+ {
+ per_cu->mark = 1;
+ continue;
+ }
+
+ /* Before we invoke realpath, which can get expensive when many
+ files are involved, do a quick comparison of the basenames. */
+ if ((basenames_may_differ
+ || file_matcher (lbasename (fnd->get_name ()), true))
+ && file_matcher (fnd->get_fullname (), false))
+ {
+ per_cu->mark = 1;
+ continue;
+ }
+ }
+
quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
per_objfile);
if (file_data == NULL)
continue;
else if (htab_find (visited_found.get (), file_data) != NULL)
{
- per_cu->v.quick->mark = 1;
+ per_cu->mark = 1;
continue;
}
if (file_matcher (file_data->file_names[j], false))
{
- per_cu->v.quick->mark = 1;
+ per_cu->mark = 1;
break;
}
this_real_name = dw2_get_real_path (per_objfile, file_data, j);
if (file_matcher (this_real_name, false))
{
- per_cu->v.quick->mark = 1;
+ per_cu->mark = 1;
break;
}
}
- void **slot = htab_find_slot (per_cu->v.quick->mark
+ void **slot = htab_find_slot (per_cu->mark
? visited_found.get ()
: visited_not_found.get (),
file_data, INSERT);
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- /* index_table is NULL if OBJF_READNOW. */
- if (!per_objfile->per_bfd->index_table)
- return true;
-
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
/* This invariant is documented in quick-functions.h. */
return true;
}
- mapped_index &index = *per_objfile->per_bfd->index_table;
+ mapped_index &index
+ = (static_cast<mapped_index &>
+ (*per_objfile->per_bfd->index_table.get ()));
bool result
= dw2_expand_symtabs_matching_symbol (index, *lookup_name,
{
int i;
- if (COMPUNIT_BLOCKVECTOR (cust) != NULL
- && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+ if (cust->blockvector () != nullptr
+ && blockvector_contains_pc (cust->blockvector (), pc))
return cust;
if (cust->includes == NULL)
if (!per_cu->is_debug_types
&& per_objfile->symtab_set_p (per_cu.get ()))
{
- if (per_cu->v.quick->file_names != nullptr)
- qfn_cache.insert (per_cu->v.quick->file_names);
+ if (per_cu->file_names != nullptr)
+ qfn_cache.insert (per_cu->file_names);
}
}
if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
continue;
- quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
- if (file_data == nullptr
- || qfn_cache.find (file_data) != qfn_cache.end ())
- continue;
-
- for (int j = 0; j < file_data->num_file_names; ++j)
+ if (per_cu->fnd != nullptr)
{
- const char *filename = file_data->file_names[j];
+ file_and_directory *fnd = per_cu->fnd.get ();
+
+ const char *filename = fnd->get_name ();
const char *key = filename;
const char *fullname = nullptr;
if (need_fullname)
{
- fullname = dw2_get_real_path (per_objfile, file_data, j);
+ fullname = fnd->get_fullname ();
key = fullname;
}
if (!filenames_cache.seen (key))
fun (filename, fullname);
}
- }
+
+ quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
+ if (file_data == nullptr
+ || qfn_cache.find (file_data) != qfn_cache.end ())
+ continue;
+
+ for (int j = 0; j < file_data->num_file_names; ++j)
+ {
+ const char *filename = file_data->file_names[j];
+ const char *key = filename;
+ const char *fullname = nullptr;
+
+ if (need_fullname)
+ {
+ fullname = dw2_get_real_path (per_objfile, file_data, j);
+ key = fullname;
+ }
+
+ if (!filenames_cache.seen (key))
+ fun (filename, fullname);
+ }
+ }
}
bool
create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges);
- per_bfd->debug_names_table = std::move (map);
- per_bfd->using_index = 1;
+ per_bfd->index_table = std::move (map);
per_bfd->quick_file_names_table =
create_quick_file_names_table (per_bfd->all_comp_units.size ());
void
dwarf2_debug_names_index::dump (struct objfile *objfile)
{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
- gdb_assert (per_objfile->per_bfd->using_index);
- printf_filtered (".debug_names:");
- if (per_objfile->per_bfd->debug_names_table)
- printf_filtered (" exists\n");
- else
- printf_filtered (" faked for \"readnow\"\n");
- printf_filtered ("\n");
+ gdb_printf (".debug_names: exists\n");
}
void
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- /* debug_names_table is NULL if OBJF_READNOW. */
- if (!per_objfile->per_bfd->debug_names_table)
- return;
-
- mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
+ mapped_debug_names &map
+ = (static_cast<mapped_debug_names &>
+ (*per_objfile->per_bfd->index_table.get ()));
const block_search_flags block_flags
= global ? SEARCH_GLOBAL_BLOCK : SEARCH_STATIC_BLOCK;
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- /* debug_names_table is NULL if OBJF_READNOW. */
- if (!per_objfile->per_bfd->debug_names_table)
- return true;
-
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
/* This invariant is documented in quick-functions.h. */
return true;
}
- mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
+ mapped_debug_names &map
+ = (static_cast<mapped_debug_names &>
+ (*per_objfile->per_bfd->index_table.get ()));
bool result
= dw2_expand_symtabs_matching_symbol (map, *lookup_name,
return global_index_cache.lookup_gdb_index (build_id, &dwz->index_cache_res);
}
+static quick_symbol_functions_up make_cooked_index_funcs ();
+
/* See dwarf2/public.h. */
void
{
dwarf_read_debug_printf ("readnow requested");
- /* When using READNOW, the using_index flag (set below) indicates that
- PER_BFD was already initialized, when we loaded some other objfile. */
- if (per_bfd->using_index)
- {
- dwarf_read_debug_printf ("using_index already set");
- objfile->qf.push_front (make_dwarf_gdb_index ());
- return;
- }
-
- per_bfd->using_index = 1;
create_all_comp_units (per_objfile);
per_bfd->quick_file_names_table
= create_quick_file_names_table (per_bfd->all_comp_units.size ());
- for (int i = 0; i < per_bfd->all_comp_units.size (); ++i)
- {
- dwarf2_per_cu_data *per_cu = per_bfd->get_cu (i);
-
- per_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
- }
-
- /* Arrange for gdb to see the "quick" functions. However, these
- functions will be no-ops because we will have expanded all
- symtabs. */
- objfile->qf.push_front (make_dwarf_gdb_index ());
- return;
- }
-
- /* Was a debug names index already read when we processed an objfile sharing
- PER_BFD? */
- if (per_bfd->debug_names_table != nullptr)
- {
- dwarf_read_debug_printf ("re-using shared debug names table");
- objfile->qf.push_front (make_dwarf_debug_names ());
+ objfile->qf.emplace_front (new readnow_functions);
return;
}
PER_BFD? */
if (per_bfd->index_table != nullptr)
{
- dwarf_read_debug_printf ("re-using shared index table");
- objfile->qf.push_front (make_dwarf_gdb_index ());
- return;
- }
-
- /* There might already be partial symtabs built for this BFD. This happens
- when loading the same binary twice with the index-cache enabled. If so,
- don't try to read an index. The objfile / per_objfile initialization will
- be completed in dwarf2_build_psymtabs, in the standard partial symtabs
- code path. */
- if (per_bfd->partial_symtabs != nullptr)
- {
- dwarf_read_debug_printf ("re-using shared partial symtabs");
- objfile->qf.push_front (make_lazy_dwarf_reader ());
+ dwarf_read_debug_printf ("re-using symbols");
+ objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
return;
}
if (dwarf2_read_debug_names (per_objfile))
{
dwarf_read_debug_printf ("found debug names");
- objfile->qf.push_front (make_dwarf_debug_names ());
+ objfile->qf.push_front
+ (per_bfd->index_table->make_quick_functions ());
return;
}
get_gdb_index_contents_from_section<dwz_file>))
{
dwarf_read_debug_printf ("found gdb index from file");
- objfile->qf.push_front (make_dwarf_gdb_index ());
+ objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
return;
}
{
dwarf_read_debug_printf ("found gdb index from cache");
global_index_cache.hit ();
- objfile->qf.push_front (make_dwarf_gdb_index ());
+ objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
return;
}
global_index_cache.miss ();
- objfile->qf.push_front (make_lazy_dwarf_reader ());
+ objfile->qf.push_front (make_cooked_index_funcs ());
}
\f
/* Build a partial symbol table. */
void
-dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf)
+dwarf2_build_psymtabs (struct objfile *objfile, bool already_attached)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-
- if (per_bfd->partial_symtabs != nullptr)
- {
- /* Partial symbols were already read, so now we can simply
- attach them. */
- if (psf == nullptr)
- {
- psf = new psymbol_functions (per_bfd->partial_symtabs);
- objfile->qf.emplace_front (psf);
- }
- else
- psf->set_partial_symtabs (per_bfd->partial_symtabs);
- return;
- }
- if (psf == nullptr)
+ if (already_attached)
{
- psf = new psymbol_functions;
- objfile->qf.emplace_front (psf);
+ if (per_objfile->per_bfd->index_table != nullptr)
+ return;
}
- const std::shared_ptr<psymtab_storage> &partial_symtabs
- = psf->get_partial_symtabs ();
-
- /* Set the local reference to partial symtabs, so that we don't try
- to read them again if reading another objfile with the same BFD.
- If we can't in fact share, this won't make a difference anyway as
- the dwarf2_per_bfd object won't be shared. */
- per_bfd->partial_symtabs = partial_symtabs;
+ else
+ objfile->qf.push_front (make_cooked_index_funcs ());
try
{
- /* This isn't really ideal: all the data we allocate on the
- objfile's obstack is still uselessly kept around. However,
- freeing it seems unsafe. */
- psymtab_discarder psymtabs (partial_symtabs.get ());
dwarf2_build_psymtabs_hard (per_objfile);
- psymtabs.keep ();
/* (maybe) store an index in the cache. */
global_index_cache.store (per_objfile);
return (sect_offset) read_offset (abfd, info_ptr, offset_size);
}
-/* A partial symtab that is used only for include files. */
-struct dwarf2_include_psymtab : public partial_symtab
-{
- dwarf2_include_psymtab (const char *filename,
- psymtab_storage *partial_symtabs,
- objfile_per_bfd_storage *objfile_per_bfd)
- : partial_symtab (filename, partial_symtabs, objfile_per_bfd)
- {
- }
-
- void read_symtab (struct objfile *objfile) override
- {
- /* It's an include file, no symbols to read for it.
- Everything is in the includer symtab. */
-
- /* The expansion of a dwarf2_include_psymtab is just a trigger for
- expansion of the includer psymtab. We use the dependencies[0] field to
- model the includer. But if we go the regular route of calling
- expand_psymtab here, and having expand_psymtab call expand_dependencies
- to expand the includer, we'll only use expand_psymtab on the includer
- (making it a non-toplevel psymtab), while if we expand the includer via
- another path, we'll use read_symtab (making it a toplevel psymtab).
- So, don't pretend a dwarf2_include_psymtab is an actual toplevel
- psymtab, and trigger read_symtab on the includer here directly. */
- includer ()->read_symtab (objfile);
- }
-
- void expand_psymtab (struct objfile *objfile) override
- {
- /* This is not called by read_symtab, and should not be called by any
- expand_dependencies. */
- gdb_assert (false);
- }
-
- bool readin_p (struct objfile *objfile) const override
- {
- return includer ()->readin_p (objfile);
- }
-
- compunit_symtab *get_compunit_symtab (struct objfile *objfile) const override
- {
- return nullptr;
- }
-
-private:
- partial_symtab *includer () const
- {
- /* An include psymtab has exactly one dependency: the psymtab that
- includes it. */
- gdb_assert (this->number_of_dependencies == 1);
- return this->dependencies[0];
- }
-};
-
-/* Allocate a new partial symtab for file named NAME and mark this new
- partial symtab as being an include of PST. */
-
-static void
-dwarf2_create_include_psymtab (dwarf2_per_bfd *per_bfd,
- const char *name,
- dwarf2_psymtab *pst,
- psymtab_storage *partial_symtabs,
- objfile_per_bfd_storage *objfile_per_bfd)
-{
- dwarf2_include_psymtab *subpst
- = new dwarf2_include_psymtab (name, partial_symtabs, objfile_per_bfd);
-
- if (!IS_ABSOLUTE_PATH (subpst->filename))
- subpst->dirname = pst->dirname;
-
- subpst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (1);
- subpst->dependencies[0] = pst;
- subpst->number_of_dependencies = 1;
-}
-
-/* Read the Line Number Program data and extract the list of files
- included by the source file represented by PST. Build an include
- partial symtab for each of these included files. */
-
-static void
-dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
- struct die_info *die,
- const file_and_directory &fnd,
- dwarf2_psymtab *pst)
-{
- line_header_up lh;
- struct attribute *attr;
-
- attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
- if (attr != nullptr && attr->form_is_unsigned ())
- lh = dwarf_decode_line_header ((sect_offset) attr->as_unsigned (), cu);
- if (lh == NULL)
- return; /* No linetable, so no includes. */
-
- /* NOTE: pst->dirname is DW_AT_comp_dir (if present). Also note
- that we pass in the raw text_low here; that is ok because we're
- only decoding the line table to make include partial symtabs, and
- so the addresses aren't really used. */
- dwarf_decode_lines (lh.get (), fnd, cu, pst,
- pst->raw_text_low (), 1);
-}
-
static hashval_t
hash_signatured_type (const void *item)
{
per_objfile->per_bfd->all_comp_units.emplace_back
(sig_type_holder.release ());
- if (per_objfile->per_bfd->using_index)
- {
- sig_type->v.quick =
- OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
- }
if (slot == NULL)
{
/* Make sure we're not clobbering something we don't expect to. */
gdb_assert (! sig_entry->queued);
gdb_assert (per_objfile->get_cu (sig_entry) == NULL);
- if (per_bfd->using_index)
- {
- gdb_assert (sig_entry->v.quick != NULL);
- gdb_assert (!per_objfile->symtab_set_p (sig_entry));
- }
- else
- gdb_assert (sig_entry->v.psymtab == NULL);
+ gdb_assert (!per_objfile->symtab_set_p (sig_entry));
gdb_assert (sig_entry->signature == dwo_entry->signature);
- gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
+ gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
+ || (to_underlying (sig_entry->type_offset_in_section)
+ == to_underlying (dwo_entry->type_offset_in_tu)));
gdb_assert (sig_entry->type_unit_group == NULL);
- gdb_assert (sig_entry->dwo_unit == NULL);
+ gdb_assert (sig_entry->dwo_unit == NULL
+ || sig_entry->dwo_unit == dwo_entry);
sig_entry->section = dwo_entry->section;
sig_entry->sect_off = dwo_entry->sect_off;
struct dwo_unit find_dwo_entry, *dwo_entry;
void **slot;
- gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+ gdb_assert (cu->dwo_unit);
/* If TU skeletons have been removed then we may not have read in any
TUs yet. */
if (sig_entry == NULL)
sig_entry = add_type_unit (per_objfile, sig, slot);
- fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
+ if (sig_entry->dwo_unit == nullptr)
+ fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
sig_entry->tu_read = 1;
return sig_entry;
}
struct dwo_unit *dwo_entry;
void **slot;
- gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+ gdb_assert (cu->dwo_unit);
gdb_assert (dwp_file != NULL);
/* If TU skeletons have been removed then we may not have read in any
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
- if (cu->dwo_unit && per_objfile->per_bfd->using_index)
+ if (cu->dwo_unit)
{
/* We're in a DWO/DWP file, and we're using .gdb_index.
These cases require special processing. */
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- section->get_name (),
- (unsigned) (begin_info_ptr - section->buffer),
- bfd_get_filename (abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ section->get_name (),
+ (unsigned) (begin_info_ptr - section->buffer),
+ bfd_get_filename (abfd));
dump_die (comp_unit_die, dwarf_die_debug);
}
static struct dwo_unit *
lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name)
{
+#if CXX_STD_THREAD
+ /* We need a lock here both to handle the DWO hash table, and BFD,
+ which is not thread-safe. */
+ static std::mutex dwo_lock;
+
+ std::lock_guard<std::mutex> guard (dwo_lock);
+#endif
+
dwarf2_per_cu_data *per_cu = cu->per_cu;
struct dwo_unit *dwo_unit;
const char *comp_dir;
dwarf2_per_objfile *per_objfile,
struct abbrev_table *abbrev_table,
dwarf2_cu *existing_cu,
- bool skip_partial)
+ bool skip_partial,
+ abbrev_cache *cache)
: die_reader_specs {},
m_this_cu (this_cu)
{
int rereading_dwo_cu = 0;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
- this_cu->is_debug_types ? "type" : "comp",
- sect_offset_str (this_cu->sect_off));
+ gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+ this_cu->is_debug_types ? "type" : "comp",
+ sect_offset_str (this_cu->sect_off));
/* If we're reading a TU directly from a DWO file, including a virtual DWO
file (instead of going through the stub), short-circuit all of this. */
}
else
{
- /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
- in per_objfile yet. */
- gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
+ /* If an existing_cu is provided, a dwarf2_cu must not exist for
+ this_cu in per_objfile yet. Here, CACHE doubles as a flag to
+ let us know that the CU is being scanned using the parallel
+ indexer. This assert is avoided in this case because (1) it
+ is irrelevant, and (2) the get_cu method is not
+ thread-safe. */
+ gdb_assert (cache != nullptr
+ || per_objfile->get_cu (this_cu) == nullptr);
m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
cu = m_new_cu.get ();
}
gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
else
{
- abbrev_section->read (objfile);
- m_abbrev_table_holder
- = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
- abbrev_table = m_abbrev_table_holder.get ();
+ if (cache != nullptr)
+ abbrev_table = cache->find (abbrev_section,
+ cu->header.abbrev_sect_off);
+ if (abbrev_table == nullptr)
+ {
+ abbrev_section->read (objfile);
+ m_abbrev_table_holder
+ = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
+ abbrev_table = m_abbrev_table_holder.get ();
+ }
}
/* Read the top level CU/TU die. */
const gdb_byte *begin_info_ptr, *info_ptr;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
- this_cu->is_debug_types ? "type" : "comp",
- sect_offset_str (this_cu->sect_off));
+ gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+ this_cu->is_debug_types ? "type" : "comp",
+ sect_offset_str (this_cu->sect_off));
gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
static std::unique_ptr<type_unit_group>
create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
{
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-
std::unique_ptr<type_unit_group> tu_group (new type_unit_group);
- tu_group->per_bfd = per_bfd;
-
- if (per_bfd->using_index)
- {
- tu_group->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
- struct dwarf2_per_cu_quick_data);
- }
- else
- {
- unsigned int line_offset = to_underlying (line_offset_struct);
- dwarf2_psymtab *pst;
- std::string name;
-
- /* Give the symtab a useful name for debug purposes. */
- if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0)
- name = string_printf ("<type_units_%d>",
- (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
- else
- name = string_printf ("<type_units_at_0x%x>", line_offset);
-
- pst = create_partial_symtab (tu_group.get (), per_objfile,
- name.c_str ());
- pst->anonymous = true;
- }
tu_group->hash.dwo_unit = cu->dwo_unit;
tu_group->hash.line_sect_off = line_offset_struct;
return tu_group;
}
\f
-/* Partial symbol tables. */
-
-/* Create a psymtab named NAME and assign it to PER_CU.
- The caller must fill in the following details:
- dirname, textlow, texthigh. */
+/* An instance of this is created when scanning DWARF to create a
+ cooked index. */
-static dwarf2_psymtab *
-create_partial_symtab (dwarf2_per_cu_data *per_cu,
- dwarf2_per_objfile *per_objfile,
- const char *name)
+class cooked_index_storage
{
- dwarf2_psymtab *pst
- = new dwarf2_psymtab (name, per_objfile->per_bfd->partial_symtabs.get (),
- per_objfile->objfile->per_bfd, per_cu);
-
- pst->psymtabs_addrmap_supported = true;
-
- /* This is the glue that links PST into GDB's symbol API. */
- per_cu->v.psymtab = pst;
-
- return pst;
-}
+public:
-/* DIE reader function for process_psymtab_comp_unit. */
+ cooked_index_storage ()
+ : m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
+ eq_cutu_reader,
+ htab_delete_entry<cutu_reader>,
+ xcalloc, xfree)),
+ m_index (new cooked_index),
+ m_addrmap_storage (),
+ m_addrmap (addrmap_create_mutable (&m_addrmap_storage))
+ {
+ }
-static void
-process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *comp_unit_die,
- enum language pretend_language)
-{
- struct dwarf2_cu *cu = reader->cu;
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- struct objfile *objfile = per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
- struct dwarf2_per_cu_data *per_cu = cu->per_cu;
- CORE_ADDR baseaddr;
- CORE_ADDR best_lowpc = 0, best_highpc = 0;
- dwarf2_psymtab *pst;
- enum pc_bounds_kind cu_bounds_kind;
+ DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
- gdb_assert (! per_cu->is_debug_types);
+ /* Return the current abbrev cache. */
+ abbrev_cache *get_abbrev_cache ()
+ {
+ return &m_abbrev_cache;
+ }
- prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
+ /* Return the DIE reader corresponding to PER_CU. If no such reader
+ has been registered, return NULL. */
+ cutu_reader *get_reader (dwarf2_per_cu_data *per_cu)
+ {
+ int index = per_cu->index;
+ return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
+ &index, index);
+ }
- /* Allocate a new partial symbol table structure. */
- gdb::unique_xmalloc_ptr<char> debug_filename;
- static const char artificial[] = "<artificial>";
- file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
- if (strcmp (fnd.name, artificial) == 0)
- {
- debug_filename.reset (concat (artificial, "@",
- sect_offset_str (per_cu->sect_off),
- (char *) NULL));
- fnd.name = debug_filename.get ();
- }
+ /* Preserve READER by storing it in the local hash table. */
+ cutu_reader *preserve (std::unique_ptr<cutu_reader> reader)
+ {
+ m_abbrev_cache.add (reader->release_abbrev_table ());
+
+ int index = reader->cu->per_cu->index;
+ void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
+ index, INSERT);
+ gdb_assert (*slot == nullptr);
+ cutu_reader *result = reader.get ();
+ *slot = reader.release ();
+ return result;
+ }
- pst = create_partial_symtab (per_cu, per_objfile, fnd.name);
+ /* Add an entry to the index. The arguments describe the entry; see
+ cooked-index.h. The new entry is returned. */
+ const cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
+ cooked_index_flag flags,
+ const char *name,
+ const cooked_index_entry *parent_entry,
+ dwarf2_per_cu_data *per_cu)
+ {
+ return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu);
+ }
- /* This must be done before calling dwarf2_build_include_psymtabs. */
- pst->dirname = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu);
+ /* Install the current addrmap into the index being constructed,
+ then transfer ownership of the index to the caller. */
+ std::unique_ptr<cooked_index> release ()
+ {
+ m_index->install_addrmap (m_addrmap);
+ return std::move (m_index);
+ }
- baseaddr = objfile->text_section_offset ();
+ /* Return the mutable addrmap that is currently being created. */
+ addrmap *get_addrmap ()
+ {
+ return m_addrmap;
+ }
- dwarf2_find_base_address (comp_unit_die, cu);
+private:
- /* Possibly set the default values of LOWPC and HIGHPC from
- `DW_AT_ranges'. */
- cu_bounds_kind = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
- &best_highpc, cu, pst);
- if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
- {
- CORE_ADDR low
- = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
- - baseaddr);
- CORE_ADDR high
- = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
- - baseaddr - 1);
- /* Store the contiguous range if it is not empty; it can be
- empty for CUs with no code. */
- addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
- low, high, pst);
- }
+ /* Hash function for a cutu_reader. */
+ static hashval_t hash_cutu_reader (const void *a)
+ {
+ const cutu_reader *reader = (const cutu_reader *) a;
+ return reader->cu->per_cu->index;
+ }
- /* Check if comp unit has_children.
- If so, read the rest of the partial symbols from this comp unit.
- If not, there's no more debug_info for this comp unit. */
- if (comp_unit_die->has_children)
- {
- struct partial_die_info *first_die;
- CORE_ADDR lowpc, highpc;
+ /* Equality function for cutu_reader. */
+ static int eq_cutu_reader (const void *a, const void *b)
+ {
+ const cutu_reader *ra = (const cutu_reader *) a;
+ const int *rb = (const int *) b;
+ return ra->cu->per_cu->index == *rb;
+ }
- lowpc = ((CORE_ADDR) -1);
- highpc = ((CORE_ADDR) 0);
+ /* The abbrev cache used by this indexer. */
+ abbrev_cache m_abbrev_cache;
+ /* A hash table of cutu_reader objects. */
+ htab_up m_reader_hash;
+ /* The index that is being constructed. */
+ std::unique_ptr<cooked_index> m_index;
+
+ /* Storage for the writeable addrmap. */
+ auto_obstack m_addrmap_storage;
+ /* A writeable addrmap being constructed by this scanner. */
+ addrmap *m_addrmap;
+};
- first_die = load_partial_dies (reader, info_ptr, 1);
+/* An instance of this is created to index a CU. */
- scan_partial_symbols (first_die, &lowpc, &highpc,
- cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
+class cooked_indexer
+{
+public:
- /* If we didn't find a lowpc, set it to highpc to avoid
- complaints from `maint check'. */
- if (lowpc == ((CORE_ADDR) -1))
- lowpc = highpc;
+ cooked_indexer (cooked_index_storage *storage,
+ dwarf2_per_cu_data *per_cu,
+ enum language language)
+ : m_index_storage (storage),
+ m_per_cu (per_cu),
+ m_language (language),
+ m_obstack (),
+ m_die_range_map (addrmap_create_mutable (&m_obstack))
+ {
+ }
- /* If the compilation unit didn't have an explicit address range,
- then use the information extracted from its child dies. */
- if (cu_bounds_kind <= PC_BOUNDS_INVALID)
- {
- best_lowpc = lowpc;
- best_highpc = highpc;
- }
- }
- pst->set_text_low (gdbarch_adjust_dwarf2_addr (gdbarch,
- best_lowpc + baseaddr)
- - baseaddr);
- pst->set_text_high (gdbarch_adjust_dwarf2_addr (gdbarch,
- best_highpc + baseaddr)
- - baseaddr);
+ DISABLE_COPY_AND_ASSIGN (cooked_indexer);
- pst->end ();
+ /* Index the given CU. */
+ void make_index (cutu_reader *reader);
- if (!cu->per_cu->imported_symtabs_empty ())
- {
- int i;
- int len = cu->per_cu->imported_symtabs_size ();
+private:
- /* Fill in 'dependencies' here; we fill in 'users' in a
- post-pass. */
- pst->number_of_dependencies = len;
- pst->dependencies
- = per_bfd->partial_symtabs->allocate_dependencies (len);
- for (i = 0; i < len; ++i)
- {
- pst->dependencies[i]
- = cu->per_cu->imported_symtabs->at (i)->v.psymtab;
- }
+ /* A helper function to turn a section offset into an address that
+ can be used in an addrmap. */
+ CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
+ {
+ CORE_ADDR value = to_underlying (offset);
+ if (is_dwz)
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
+ return value;
+ }
- cu->per_cu->imported_symtabs_free ();
- }
+ /* A helper function to scan the PC bounds of READER and record them
+ in the storage's addrmap. */
+ void check_bounds (cutu_reader *reader);
- /* Get the list of files included in the current compilation unit,
- and build a psymtab for each of them. */
- dwarf2_build_include_psymtabs (cu, comp_unit_die, fnd, pst);
+ /* Ensure that the indicated CU exists. The cutu_reader for it is
+ returned. FOR_SCANNING is true if the caller intends to scan all
+ the DIEs in the CU; when false, this use is assumed to be to look
+ up just a single DIE. */
+ cutu_reader *ensure_cu_exists (cutu_reader *reader,
+ dwarf2_per_objfile *per_objfile,
+ sect_offset sect_off,
+ bool is_dwz,
+ bool for_scanning);
+
+ /* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is
+ the entry for the enclosing scope (nullptr at top level). FULLY
+ is true when a full scan must be done -- in some languages,
+ function scopes must be fully explored in order to find nested
+ functions. This returns a pointer to just after the spot where
+ reading stopped. */
+ const gdb_byte *index_dies (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully);
+
+ /* Scan the attributes for a given DIE and update the out
+ parameters. Returns a pointer to the byte after the DIE. */
+ const gdb_byte *scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+ cutu_reader *reader,
+ const gdb_byte *watermark_ptr,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev,
+ const char **name,
+ const char **linkage_name,
+ cooked_index_flag *flags,
+ sect_offset *sibling_offset,
+ const cooked_index_entry **parent_entry,
+ CORE_ADDR *maybe_defer,
+ bool for_specification);
+
+ /* Handle DW_TAG_imported_unit, by scanning the DIE to find
+ DW_AT_import, and then scanning the referenced CU. Returns a
+ pointer to the byte after the DIE. */
+ const gdb_byte *index_imported_unit (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev);
+
+ /* Recursively read DIEs, recording the section offsets in
+ m_die_range_map and then calling index_dies. */
+ const gdb_byte *recurse (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully);
+
+ /* The storage object, where the results are kept. */
+ cooked_index_storage *m_index_storage;
+ /* The CU that we are reading on behalf of. This object might be
+ asked to index one CU but to treat the results as if they come
+ from some including CU; in this case the including CU would be
+ recorded here. */
+ dwarf2_per_cu_data *m_per_cu;
+ /* The language that we're assuming when reading. */
+ enum language m_language;
+
+ /* Temporary storage. */
+ auto_obstack m_obstack;
+ /* An addrmap that maps from section offsets (see the form_addr
+ method) to newly-created entries. See m_deferred_entries to
+ understand this. */
+ addrmap *m_die_range_map;
+
+ /* A single deferred entry. */
+ struct deferred_entry
+ {
+ sect_offset die_offset;
+ const char *name;
+ CORE_ADDR spec_offset;
+ dwarf_tag tag;
+ cooked_index_flag flags;
+ };
- dwarf_read_debug_printf ("Psymtab for %s unit @%s: %s - %s"
- ", %d global, %d static syms",
- per_cu->is_debug_types ? "type" : "comp",
- sect_offset_str (per_cu->sect_off),
- paddress (gdbarch, pst->text_low (objfile)),
- paddress (gdbarch, pst->text_high (objfile)),
- (int) pst->global_psymbols.size (),
- (int) pst->static_psymbols.size ());
-}
+ /* The generated DWARF can sometimes have the declaration for a
+ method in a class (or perhaps namespace) scope, with the
+ definition appearing outside this scope... just one of the many
+ bad things about DWARF. In order to handle this situation, we
+ defer certain entries until the end of scanning, at which point
+ we'll know the containing context of all the DIEs that we might
+ have scanned. This vector stores these deferred entries. */
+ std::vector<deferred_entry> m_deferred_entries;
+};
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
Process compilation unit THIS_CU for a psymtab. */
static void
process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
- bool want_partial_unit,
- enum language pretend_language)
+ cooked_index_storage *storage)
{
- /* If this compilation unit was already read in, free the
- cached copy in order to read it in again. This is
- necessary because we skipped some symbols when we first
- read in the compilation unit (see load_partial_dies).
- This problem could be avoided, but the benefit is unclear. */
- per_objfile->remove_cu (this_cu);
-
- cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false);
+ cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false,
+ storage->get_abbrev_cache ());
if (reader.comp_unit_die == nullptr)
return;
/* Nothing. */
}
else if (this_cu->is_debug_types)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
- else if (want_partial_unit
- || reader.comp_unit_die->tag != DW_TAG_partial_unit)
- process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
- reader.comp_unit_die,
- pretend_language);
-
- /* Age out any secondary CUs. */
- per_objfile->age_comp_units ();
+ build_type_psymtabs_reader (&reader, storage);
+ else if (reader.comp_unit_die->tag != DW_TAG_partial_unit)
+ {
+ bool nope = false;
+ if (this_cu->scanned.compare_exchange_strong (nope, true))
+ {
+ prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+ language_minimal);
+ gdb_assert (storage != nullptr);
+ cooked_indexer indexer (storage, this_cu, reader.cu->per_cu->lang);
+ indexer.make_index (&reader);
+ }
+ }
}
/* Reader function for build_type_psymtabs. */
static void
-build_type_psymtabs_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *type_unit_die)
+build_type_psymtabs_reader (cutu_reader *reader,
+ cooked_index_storage *storage)
{
- dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
struct dwarf2_cu *cu = reader->cu;
struct dwarf2_per_cu_data *per_cu = cu->per_cu;
- struct signatured_type *sig_type;
- struct type_unit_group *tu_group;
- struct attribute *attr;
- struct partial_die_info *first_die;
- CORE_ADDR lowpc, highpc;
- dwarf2_psymtab *pst;
+ struct die_info *type_unit_die = reader->comp_unit_die;
gdb_assert (per_cu->is_debug_types);
- sig_type = (struct signatured_type *) per_cu;
if (! type_unit_die->has_children)
return;
- attr = type_unit_die->attr (DW_AT_stmt_list);
- tu_group = get_type_unit_group (cu, attr);
-
- if (tu_group->tus == nullptr)
- tu_group->tus = new std::vector<signatured_type *>;
- tu_group->tus->push_back (sig_type);
-
prepare_one_comp_unit (cu, type_unit_die, language_minimal);
- pst = create_partial_symtab (per_cu, per_objfile, "");
- pst->anonymous = true;
- first_die = load_partial_dies (reader, info_ptr, 1);
-
- lowpc = (CORE_ADDR) -1;
- highpc = (CORE_ADDR) 0;
- scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
-
- pst->end ();
+ gdb_assert (storage != nullptr);
+ cooked_indexer indexer (storage, per_cu, cu->per_cu->lang);
+ indexer.make_index (reader);
}
/* Struct used to sort TUs by their abbreviation table offset. */
dwarf2_per_objfile->per_bfd->type_unit_groups. */
static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile,
+ cooked_index_storage *storage)
{
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
abbrev_table_up abbrev_table;
cutu_reader reader (tu.sig_type, per_objfile,
abbrev_table.get (), nullptr, false);
if (!reader.dummy_p)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
+ build_type_psymtabs_reader (&reader, storage);
}
}
tu_stats->nr_all_type_units_reallocs);
}
-/* Traversal function for build_type_psymtabs. */
-
-static int
-build_type_psymtab_dependencies (void **slot, void *info)
+struct skeleton_data
{
- dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
- dwarf2_psymtab *pst = tu_group->v.psymtab;
- int len = (tu_group->tus == nullptr) ? 0 : tu_group->tus->size ();
- int i;
-
- gdb_assert (len > 0);
- gdb_assert (tu_group->type_unit_group_p ());
-
- pst->number_of_dependencies = len;
- pst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (len);
- for (i = 0; i < len; ++i)
- {
- struct signatured_type *iter = tu_group->tus->at (i);
- gdb_assert (iter->is_debug_types);
- pst->dependencies[i] = iter->v.psymtab;
- iter->type_unit_group = tu_group;
- }
-
- delete tu_group->tus;
- tu_group->tus = nullptr;
-
- return 1;
-}
+ dwarf2_per_objfile *per_objfile;
+ cooked_index_storage *storage;
+};
/* Traversal function for process_skeletonless_type_unit.
Read a TU in a DWO file and build partial symbols for it. */
process_skeletonless_type_unit (void **slot, void *info)
{
struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
- dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
+ skeleton_data *data = (skeleton_data *) info;
/* If this TU doesn't exist in the global table, add it and read it in. */
- if (per_objfile->per_bfd->signatured_types == NULL)
- per_objfile->per_bfd->signatured_types = allocate_signatured_type_table ();
+ if (data->per_objfile->per_bfd->signatured_types == NULL)
+ data->per_objfile->per_bfd->signatured_types
+ = allocate_signatured_type_table ();
signatured_type find_entry (dwo_unit->signature);
- slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (),
+ slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (),
&find_entry, INSERT);
/* If we've already seen this type there's nothing to do. What's happening
is we're doing our own version of comdat-folding here. */
/* This does the job that create_all_comp_units would have done for
this TU. */
signatured_type *entry
- = add_type_unit (per_objfile, dwo_unit->signature, slot);
- fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
+ = add_type_unit (data->per_objfile, dwo_unit->signature, slot);
+ fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit);
*slot = entry;
/* This does the job that build_type_psymtabs would have done. */
- cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
+ cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false);
if (!reader.dummy_p)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
+ build_type_psymtabs_reader (&reader, data->storage);
return 1;
}
Note: This can't be done until we know what all the DWO files are. */
static void
-process_skeletonless_type_units (dwarf2_per_objfile *per_objfile)
+process_skeletonless_type_units (dwarf2_per_objfile *per_objfile,
+ cooked_index_storage *storage)
{
+ skeleton_data data { per_objfile, storage };
+
/* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
if (get_dwp_file (per_objfile) == NULL
&& per_objfile->per_bfd->dwo_files != NULL)
{
htab_traverse_noresize (per_objfile->per_bfd->dwo_files.get (),
process_dwo_file_for_skeletonless_type_units,
- per_objfile);
- }
-}
-
-/* Compute the 'user' field for each psymtab in DWARF2_PER_OBJFILE. */
-
-static void
-set_partial_user (dwarf2_per_objfile *per_objfile)
-{
- for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
- {
- dwarf2_psymtab *pst = per_cu->v.psymtab;
-
- if (pst == NULL)
- continue;
-
- for (int j = 0; j < pst->number_of_dependencies; ++j)
- {
- /* Set the 'user' field only if it is not already set. */
- if (pst->dependencies[j]->user == NULL)
- pst->dependencies[j]->user = pst;
- }
+ &data);
}
}
dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
objfile_name (objfile));
- scoped_restore restore_reading_psyms
- = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
-
- per_bfd->info.read (objfile);
-
- /* Any cached compilation units will be linked by the per-objfile
- read_in_chain. Make sure to free them when we're done. */
- free_cached_comp_units freer (per_objfile);
+ per_bfd->map_info_sections (objfile);
+ cooked_index_storage index_storage;
create_all_comp_units (per_objfile);
- build_type_psymtabs (per_objfile);
+ build_type_psymtabs (per_objfile, &index_storage);
+ std::vector<std::unique_ptr<cooked_index>> indexes;
- /* Create a temporary address map on a temporary obstack. We later
- copy this to the final obstack. */
- auto_obstack temp_obstack;
+ per_bfd->quick_file_names_table
+ = create_quick_file_names_table (per_bfd->all_comp_units.size ());
+ if (!per_bfd->debug_aranges.empty ())
+ read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+ index_storage.get_addrmap ());
- scoped_restore save_psymtabs_addrmap
- = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
- addrmap_create_mutable (&temp_obstack));
+ {
+ /* Ensure that complaints are handled correctly. */
+ complaint_interceptor complaint_handler;
+
+ using iter_type = decltype (per_bfd->all_comp_units.begin ());
+
+ /* Each thread returns a pair holding a cooked index, and a vector
+ of errors that should be printed. The latter is done because
+ GDB's I/O system is not thread-safe. run_on_main_thread could be
+ used, but that would mean the messages are printed after the
+ prompt, which looks weird. */
+ using result_type = std::pair<std::unique_ptr<cooked_index>,
+ std::vector<gdb_exception>>;
+ std::vector<result_type> results
+ = gdb::parallel_for_each (1, per_bfd->all_comp_units.begin (),
+ per_bfd->all_comp_units.end (),
+ [=] (iter_type iter, iter_type end)
+ {
+ std::vector<gdb_exception> errors;
+ cooked_index_storage thread_storage;
+ for (; iter != end; ++iter)
+ {
+ dwarf2_per_cu_data *per_cu = iter->get ();
+ try
+ {
+ process_psymtab_comp_unit (per_cu, per_objfile,
+ &thread_storage);
+ }
+ catch (gdb_exception &except)
+ {
+ errors.push_back (std::move (except));
+ }
+ }
+ return result_type (thread_storage.release (), std::move (errors));
+ });
- for (const auto &per_cu : per_bfd->all_comp_units)
- {
- if (per_cu->v.psymtab != NULL)
- /* In case a forward DW_TAG_imported_unit has read the CU already. */
- continue;
- process_psymtab_comp_unit (per_cu.get (), per_objfile, false,
- language_minimal);
- }
+ /* Only show a given exception a single time. */
+ std::unordered_set<gdb_exception> seen_exceptions;
+ for (auto &one_result : results)
+ {
+ indexes.push_back (std::move (one_result.first));
+ for (auto &one_exc : one_result.second)
+ if (seen_exceptions.insert (one_exc).second)
+ exception_print (gdb_stderr, one_exc);
+ }
+ }
/* This has to wait until we read the CUs, we need the list of DWOs. */
- process_skeletonless_type_units (per_objfile);
-
- /* Now that all TUs have been processed we can fill in the dependencies. */
- if (per_bfd->type_unit_groups != NULL)
- {
- htab_traverse_noresize (per_bfd->type_unit_groups.get (),
- build_type_psymtab_dependencies, per_objfile);
- }
+ process_skeletonless_type_units (per_objfile, &index_storage);
if (dwarf_read_debug > 0)
print_tu_stats (per_objfile);
- set_partial_user (per_objfile);
-
- per_bfd->partial_symtabs->psymtabs_addrmap
- = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
- per_bfd->partial_symtabs->obstack ());
- /* At this point we want to keep the address map. */
- save_psymtabs_addrmap.release ();
+ indexes.push_back (index_storage.release ());
+ /* Remove any NULL entries. This might happen if parallel-for
+ decides to throttle the number of threads that were used. */
+ indexes.erase
+ (std::remove_if (indexes.begin (),
+ indexes.end (),
+ [] (const std::unique_ptr<cooked_index> &entry)
+ {
+ return entry == nullptr;
+ }),
+ indexes.end ());
+ indexes.shrink_to_fit ();
+
+ cooked_index_vector *vec = new cooked_index_vector (std::move (indexes));
+ per_bfd->index_table.reset (vec);
+
+ const cooked_index_entry *main_entry = vec->get_main ();
+ if (main_entry != nullptr)
+ set_objfile_main_name (objfile, main_entry->name,
+ main_entry->per_cu->lang);
dwarf_read_debug_printf ("Done building psymtabs of %s",
objfile_name (objfile));
}
-/* Load the partial DIEs for a secondary CU into memory.
- This is also used when rereading a primary CU with load_all_dies. */
-
-static void
-load_partial_comp_unit (dwarf2_per_cu_data *this_cu,
- dwarf2_per_objfile *per_objfile,
- dwarf2_cu *existing_cu)
-{
- cutu_reader reader (this_cu, per_objfile, nullptr, existing_cu, false);
-
- if (!reader.dummy_p)
- {
- prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
- language_minimal);
-
- /* Check if comp unit has_children.
- If so, read the rest of the partial symbols from this comp unit.
- If not, there's no more debug_info for this comp unit. */
- if (reader.comp_unit_die->has_children)
- load_partial_dies (&reader, reader.info_ptr, 0);
-
- reader.keep ();
- }
-}
-
static void
read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
struct dwarf2_section_info *section,
dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
if (dwz != NULL)
- read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
- types_htab, rcuh_kind::COMPILE);
+ {
+ /* Pre-read the sections we'll need to construct an index. */
+ struct objfile *objfile = per_objfile->objfile;
+ dwz->abbrev.read (objfile);
+ dwz->info.read (objfile);
+ dwz->str.read (objfile);
+ dwz->line.read (objfile);
+ read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+ types_htab, rcuh_kind::COMPILE);
+ }
per_objfile->per_bfd->signatured_types = std::move (types_htab);
}
-/* Process all loaded DIEs for compilation unit CU, starting at
- FIRST_DIE. The caller should pass SET_ADDRMAP == 1 if the compilation
- unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
- DW_AT_ranges). See the comments of add_partial_subprogram on how
- SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated. */
+/* Return the initial uleb128 in the die at INFO_PTR. */
-static void
-scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int set_addrmap,
- struct dwarf2_cu *cu)
+static unsigned int
+peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
{
- struct partial_die_info *pdi;
-
- /* Now, march along the PDI's, descending into ones which have
- interesting children but skipping the children of the other ones,
- until we reach the end of the compilation unit. */
-
- pdi = first_die;
-
- while (pdi != NULL)
- {
- pdi->fixup (cu);
-
- /* Anonymous namespaces or modules have no name but have interesting
- children, so we need to look at them. Ditto for anonymous
- enums. */
-
- if (pdi->raw_name != NULL || pdi->tag == DW_TAG_namespace
- || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
- || pdi->tag == DW_TAG_imported_unit
- || pdi->tag == DW_TAG_inlined_subroutine)
- {
- switch (pdi->tag)
- {
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine:
- add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
- if (cu->per_cu->lang == language_cplus)
- scan_partial_symbols (pdi->die_child, lowpc, highpc,
- set_addrmap, cu);
- break;
- case DW_TAG_constant:
- case DW_TAG_variable:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- if (!pdi->is_declaration
- || (pdi->tag == DW_TAG_variable && pdi->is_external))
- {
- add_partial_symbol (pdi, cu);
- }
- break;
- case DW_TAG_class_type:
- case DW_TAG_interface_type:
- case DW_TAG_structure_type:
- if (!pdi->is_declaration)
- {
- add_partial_symbol (pdi, cu);
- }
- if ((cu->per_cu->lang == language_rust
- || cu->per_cu->lang == language_cplus)
- && pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc,
- set_addrmap, cu);
- break;
- case DW_TAG_enumeration_type:
- if (!pdi->is_declaration)
- add_partial_enumeration (pdi, cu);
- break;
- case DW_TAG_base_type:
- case DW_TAG_subrange_type:
- /* File scope base type definitions are added to the partial
- symbol table. */
- add_partial_symbol (pdi, cu);
- break;
- case DW_TAG_namespace:
- add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
- break;
- case DW_TAG_module:
- if (!pdi->is_declaration)
- add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
- break;
- case DW_TAG_imported_unit:
- {
- struct dwarf2_per_cu_data *per_cu;
-
- /* For now we don't handle imported units in type units. */
- if (cu->per_cu->is_debug_types)
- {
- error (_("Dwarf Error: DW_TAG_imported_unit is not"
- " supported in type units [in module %s]"),
- objfile_name (cu->per_objfile->objfile));
- }
-
- per_cu = dwarf2_find_containing_comp_unit
- (pdi->d.sect_off, pdi->is_dwz, cu->per_objfile);
-
- /* Go read the partial unit, if needed. */
- if (per_cu->v.psymtab == NULL)
- process_psymtab_comp_unit (per_cu, cu->per_objfile, true,
- cu->per_cu->lang);
-
- if (pdi->die_parent == nullptr
- && per_cu->unit_type == DW_UT_compile
- && per_cu->lang == language_cplus)
- /* Regard import as hint. See corresponding code in
- process_imported_unit_die. */
- break;
-
- cu->per_cu->imported_symtabs_push (per_cu);
- }
- break;
- case DW_TAG_imported_declaration:
- add_partial_symbol (pdi, cu);
- break;
- default:
- break;
- }
- }
-
- /* If the die has a sibling, skip to the sibling. */
+ unsigned int bytes_read;
- pdi = pdi->die_sibling;
- }
+ return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
}
-/* Functions used to compute the fully scoped name of a partial DIE.
-
- Normally, this is simple. For C++, the parent DIE's fully scoped
- name is concatenated with "::" and the partial DIE's name.
- Enumerators are an exception; they use the scope of their parent
- enumeration type, i.e. the name of the enumeration type is not
- prepended to the enumerator.
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit
+ READER::CU. Use READER::ABBREV_TABLE to lookup any abbreviation.
- There are two complexities. One is DW_AT_specification; in this
- case "parent" means the parent of the target of the specification,
- instead of the direct parent of the DIE. The other is compilers
- which do not emit DW_TAG_namespace; in this case we try to guess
- the fully qualified name of structure types from their members'
- linkage names. This must be done using the DIE's children rather
- than the children of any DW_AT_specification target. We only need
- to do this for structures at the top level, i.e. if the target of
- any DW_AT_specification (if any; otherwise the DIE itself) does not
- have a parent. */
+ Return the corresponding abbrev, or NULL if the number is zero (indicating
+ an empty DIE). In either case *BYTES_READ will be set to the length of
+ the initial number. */
-/* Compute the scope prefix associated with PDI's parent, in
- compilation unit CU. The result will be allocated on CU's
- comp_unit_obstack, or a copy of the already allocated PDI->NAME
- field. NULL is returned if no prefix is necessary. */
-static const char *
-partial_die_parent_scope (struct partial_die_info *pdi,
- struct dwarf2_cu *cu)
+static const struct abbrev_info *
+peek_die_abbrev (const die_reader_specs &reader,
+ const gdb_byte *info_ptr, unsigned int *bytes_read)
{
- const char *grandparent_scope;
- struct partial_die_info *parent, *real_pdi;
+ dwarf2_cu *cu = reader.cu;
+ bfd *abfd = reader.abfd;
+ unsigned int abbrev_number
+ = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
- /* We need to look at our parent DIE; if we have a DW_AT_specification,
- then this means the parent of the specification DIE. */
+ if (abbrev_number == 0)
+ return NULL;
- real_pdi = pdi;
- while (real_pdi->has_specification)
+ const abbrev_info *abbrev
+ = reader.abbrev_table->lookup_abbrev (abbrev_number);
+ if (!abbrev)
{
- auto res = find_partial_die (real_pdi->spec_offset,
- real_pdi->spec_is_dwz, cu);
- real_pdi = res.pdi;
- cu = res.cu;
+ error (_("Dwarf Error: Could not find abbrev number %d in %s"
+ " at offset %s [in module %s]"),
+ abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
+ sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
}
- parent = real_pdi->die_parent;
- if (parent == NULL)
- return NULL;
-
- if (parent->scope_set)
- return parent->scope;
-
- parent->fixup (cu);
+ return abbrev;
+}
- grandparent_scope = partial_die_parent_scope (parent, cu);
+/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
+ Returns a pointer to the end of a series of DIEs, terminated by an empty
+ DIE. Any children of the skipped DIEs will also be skipped. */
- /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus
- DW_TAG_namespace DIEs with a name of "::" for the global namespace.
- Work around this problem here. */
- if (cu->per_cu->lang == language_cplus
- && parent->tag == DW_TAG_namespace
- && strcmp (parent->name (cu), "::") == 0
- && grandparent_scope == NULL)
+static const gdb_byte *
+skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
+{
+ while (1)
{
- parent->scope = NULL;
- parent->scope_set = 1;
- return NULL;
- }
+ unsigned int bytes_read;
+ const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+ &bytes_read);
- /* Nested subroutines in Fortran get a prefix. */
- if (pdi->tag == DW_TAG_enumerator)
- /* Enumerators should not get the name of the enumeration as a prefix. */
- parent->scope = grandparent_scope;
- else if (parent->tag == DW_TAG_namespace
- || parent->tag == DW_TAG_module
- || parent->tag == DW_TAG_structure_type
- || parent->tag == DW_TAG_class_type
- || parent->tag == DW_TAG_interface_type
- || parent->tag == DW_TAG_union_type
- || parent->tag == DW_TAG_enumeration_type
- || (cu->per_cu->lang == language_fortran
- && parent->tag == DW_TAG_subprogram
- && pdi->tag == DW_TAG_subprogram))
- {
- if (grandparent_scope == NULL)
- parent->scope = parent->name (cu);
+ if (abbrev == NULL)
+ return info_ptr + bytes_read;
else
- parent->scope = typename_concat (&cu->comp_unit_obstack,
- grandparent_scope,
- parent->name (cu), 0, cu);
- }
- else
- {
- /* FIXME drow/2004-04-01: What should we be doing with
- function-local names? For partial symbols, we should probably be
- ignoring them. */
- complaint (_("unhandled containing DIE tag %s for DIE at %s"),
- dwarf_tag_name (parent->tag),
- sect_offset_str (pdi->sect_off));
- parent->scope = grandparent_scope;
+ info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
}
-
- parent->scope_set = 1;
- return parent->scope;
}
-/* Return the fully scoped name associated with PDI, from compilation unit
- CU. The result will be allocated with malloc. */
+/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
+ INFO_PTR should point just after the initial uleb128 of a DIE, and the
+ abbrev corresponding to that skipped uleb128 should be passed in
+ ABBREV.
+
+ If DO_SKIP_CHILDREN is true, or if the DIE has no children, this
+ returns a pointer to this DIE's sibling, skipping any children.
+ Otherwise, returns a pointer to the DIE's first child. */
-static gdb::unique_xmalloc_ptr<char>
-partial_die_full_name (struct partial_die_info *pdi,
- struct dwarf2_cu *cu)
+static const gdb_byte *
+skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
+ const struct abbrev_info *abbrev, bool do_skip_children)
{
- const char *parent_scope;
+ unsigned int bytes_read;
+ struct attribute attr;
+ bfd *abfd = reader->abfd;
+ struct dwarf2_cu *cu = reader->cu;
+ const gdb_byte *buffer = reader->buffer;
+ const gdb_byte *buffer_end = reader->buffer_end;
+ unsigned int form, i;
- /* If this is a template instantiation, we can not work out the
- template arguments from partial DIEs. So, unfortunately, we have
- to go through the full DIEs. At least any work we do building
- types here will be reused if full symbols are loaded later. */
- if (pdi->has_template_arguments)
+ if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1)
{
- pdi->fixup (cu);
-
- if (pdi->name (cu) != NULL && strchr (pdi->name (cu), '<') == NULL)
- {
- struct die_info *die;
- struct attribute attr;
- struct dwarf2_cu *ref_cu = cu;
-
- /* DW_FORM_ref_addr is using section offset. */
- attr.name = (enum dwarf_attribute) 0;
- attr.form = DW_FORM_ref_addr;
- attr.u.unsnd = to_underlying (pdi->sect_off);
- die = follow_die_ref (NULL, &attr, &ref_cu);
-
- return make_unique_xstrdup (dwarf2_full_name (NULL, die, ref_cu));
- }
+ /* We only handle DW_FORM_ref4 here. */
+ const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
+ unsigned int offset = read_4_bytes (abfd, sibling_data);
+ const gdb_byte *sibling_ptr
+ = buffer + to_underlying (cu->header.sect_off) + offset;
+ if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
+ return sibling_ptr;
+ /* Fall through to the slow way. */
}
-
- parent_scope = partial_die_parent_scope (pdi, cu);
- if (parent_scope == NULL)
- return NULL;
- else
- return gdb::unique_xmalloc_ptr<char> (typename_concat (NULL, parent_scope,
- pdi->name (cu),
- 0, cu));
-}
-
-static void
-add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
-{
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- struct objfile *objfile = per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
- CORE_ADDR addr = 0;
- const char *actual_name = NULL;
- CORE_ADDR baseaddr;
-
- baseaddr = objfile->text_section_offset ();
-
- gdb::unique_xmalloc_ptr<char> built_actual_name
- = partial_die_full_name (pdi, cu);
- if (built_actual_name != NULL)
- actual_name = built_actual_name.get ();
-
- if (actual_name == NULL)
- actual_name = pdi->name (cu);
-
- partial_symbol psymbol;
- memset (&psymbol, 0, sizeof (psymbol));
- psymbol.ginfo.set_language (cu->per_cu->lang,
- &objfile->objfile_obstack);
- psymbol.ginfo.set_section_index (-1);
-
- /* The code below indicates that the psymbol should be installed by
- setting this. */
- gdb::optional<psymbol_placement> where;
-
- switch (pdi->tag)
+ else if (abbrev->size_if_constant != 0)
{
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- addr = (gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr)
- - baseaddr);
- if (pdi->is_external
- || cu->per_cu->lang == language_ada
- || (cu->per_cu->lang == language_fortran
- && pdi->die_parent != NULL
- && pdi->die_parent->tag == DW_TAG_subprogram))
- {
- /* Normally, only "external" DIEs are part of the global scope.
- But in Ada and Fortran, we want to be able to access nested
- procedures globally. So all Ada and Fortran subprograms are
- stored in the global scope. */
- where = psymbol_placement::GLOBAL;
- }
- else
- where = psymbol_placement::STATIC;
-
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_BLOCK;
- psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
- psymbol.ginfo.value.address = addr;
-
- if (pdi->main_subprogram && actual_name != NULL)
- set_objfile_main_name (objfile, actual_name, cu->per_cu->lang);
- break;
- case DW_TAG_constant:
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_STATIC;
- where = (pdi->is_external
- ? psymbol_placement::GLOBAL
- : psymbol_placement::STATIC);
- break;
- case DW_TAG_variable:
- if (pdi->d.locdesc)
- addr = decode_locdesc (pdi->d.locdesc, cu);
+ info_ptr += abbrev->size_if_constant;
+ if (do_skip_children && abbrev->has_children)
+ return skip_children (reader, info_ptr);
+ return info_ptr;
+ }
- if (pdi->d.locdesc
- && addr == 0
- && !per_objfile->per_bfd->has_section_at_zero)
+ for (i = 0; i < abbrev->num_attrs; i++)
+ {
+ /* The only abbrev we care about is DW_AT_sibling. */
+ if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
{
- /* A global or static variable may also have been stripped
- out by the linker if unused, in which case its address
- will be nullified; do not add such variables into partial
- symbol table then. */
- }
- else if (pdi->is_external)
- {
- /* Global Variable.
- Don't enter into the minimal symbol tables as there is
- a minimal symbol table entry from the ELF symbols already.
- Enter into partial symbol table if it has a location
- descriptor or a type.
- If the location descriptor is missing, new_symbol will create
- a LOC_UNRESOLVED symbol, the address of the variable will then
- be determined from the minimal symbol table whenever the variable
- is referenced.
- The address for the partial symbol table entry is not
- used by GDB, but it comes in handy for debugging partial symbol
- table building. */
-
- if (pdi->d.locdesc || pdi->has_type)
+ read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+ if (attr.form == DW_FORM_ref_addr)
+ complaint (_("ignoring absolute DW_AT_sibling"));
+ else
{
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_STATIC;
- psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
- psymbol.ginfo.value.address = addr;
- where = psymbol_placement::GLOBAL;
- }
- }
- else
- {
- int has_loc = pdi->d.locdesc != NULL;
-
- /* Static Variable. Skip symbols whose value we cannot know (those
- without location descriptors or constant values). */
- if (!has_loc && !pdi->has_const_value)
- return;
+ sect_offset off = attr.get_ref_die_offset ();
+ const gdb_byte *sibling_ptr = buffer + to_underlying (off);
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_STATIC;
- psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
- if (has_loc)
- psymbol.ginfo.value.address = addr;
- where = psymbol_placement::STATIC;
- }
- break;
- case DW_TAG_array_type:
- case DW_TAG_typedef:
- case DW_TAG_base_type:
- case DW_TAG_subrange_type:
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_TYPEDEF;
- where = psymbol_placement::STATIC;
- break;
- case DW_TAG_imported_declaration:
- case DW_TAG_namespace:
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_TYPEDEF;
- where = psymbol_placement::GLOBAL;
- break;
- case DW_TAG_module:
- /* With Fortran 77 there might be a "BLOCK DATA" module
- available without any name. If so, we skip the module as it
- doesn't bring any value. */
- if (actual_name != nullptr)
- {
- psymbol.domain = MODULE_DOMAIN;
- psymbol.aclass = LOC_TYPEDEF;
- where = psymbol_placement::GLOBAL;
+ if (sibling_ptr < info_ptr)
+ complaint (_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ reader->die_section->overflow_complaint ();
+ else
+ return sibling_ptr;
+ }
}
- break;
- case DW_TAG_class_type:
- case DW_TAG_interface_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_enumeration_type:
- /* Skip external references. The DWARF standard says in the section
- about "Structure, Union, and Class Type Entries": "An incomplete
- structure, union or class type is represented by a structure,
- union or class entry that does not have a byte size attribute
- and that has a DW_AT_declaration attribute." */
- if (!pdi->has_byte_size && pdi->is_declaration)
- return;
-
- /* NOTE: carlton/2003-10-07: See comment in new_symbol about
- static vs. global. */
- psymbol.domain = STRUCT_DOMAIN;
- psymbol.aclass = LOC_TYPEDEF;
- where = (cu->per_cu->lang == language_cplus
- ? psymbol_placement::GLOBAL
- : psymbol_placement::STATIC);
- break;
- case DW_TAG_enumerator:
- psymbol.domain = VAR_DOMAIN;
- psymbol.aclass = LOC_CONST;
- where = (cu->per_cu->lang == language_cplus
- ? psymbol_placement::GLOBAL
- : psymbol_placement::STATIC);
- break;
- default:
- break;
- }
- if (where.has_value ())
- {
- if (built_actual_name != nullptr)
- actual_name = objfile->intern (actual_name);
- if (pdi->linkage_name == nullptr
- || cu->per_cu->lang == language_ada)
- psymbol.ginfo.set_linkage_name (actual_name);
- else
- {
- psymbol.ginfo.set_demangled_name (actual_name,
- &objfile->objfile_obstack);
- psymbol.ginfo.set_linkage_name (pdi->linkage_name);
- }
- cu->per_cu->v.psymtab->add_psymbol
- (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (),
- objfile);
- }
-}
-
-/* Read a partial die corresponding to a namespace; also, add a symbol
- corresponding to that namespace to the symbol table. NAMESPACE is
- the name of the enclosing namespace. */
-
-static void
-add_partial_namespace (struct partial_die_info *pdi,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int set_addrmap, struct dwarf2_cu *cu)
-{
- /* Add a symbol for the namespace. */
-
- add_partial_symbol (pdi, cu);
-
- /* Now scan partial symbols in that namespace. */
-
- if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-/* Read a partial die corresponding to a Fortran module. */
-
-static void
-add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
-{
- /* Add a symbol for the namespace. */
-
- add_partial_symbol (pdi, cu);
-
- /* Now scan partial symbols in that module. */
-
- if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-static int
-dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *,
- dwarf2_psymtab *, dwarf_tag);
-
-/* Read a partial die corresponding to a subprogram or an inlined
- subprogram and create a partial symbol for that subprogram.
- When the CU language allows it, this routine also defines a partial
- symbol for each nested subprogram that this subprogram contains.
- If SET_ADDRMAP is true, record the covered ranges in the addrmap.
- Set *LOWPC and *HIGHPC to the lowest and highest PC values found in PDI.
-
- PDI may also be a lexical block, in which case we simply search
- recursively for subprograms defined inside that lexical block.
- Again, this is only performed when the CU language allows this
- type of definitions. */
-
-static void
-add_partial_subprogram (struct partial_die_info *pdi,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int set_addrmap, struct dwarf2_cu *cu)
-{
- if (pdi->tag == DW_TAG_subprogram || pdi->tag == DW_TAG_inlined_subroutine)
- {
- if (pdi->has_pc_info)
- {
- if (pdi->lowpc < *lowpc)
- *lowpc = pdi->lowpc;
- if (pdi->highpc > *highpc)
- *highpc = pdi->highpc;
- if (set_addrmap)
- {
- struct objfile *objfile = cu->per_objfile->objfile;
- dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
- struct gdbarch *gdbarch = objfile->arch ();
- CORE_ADDR baseaddr;
- CORE_ADDR this_highpc;
- CORE_ADDR this_lowpc;
-
- baseaddr = objfile->text_section_offset ();
- this_lowpc
- = (gdbarch_adjust_dwarf2_addr (gdbarch,
- pdi->lowpc + baseaddr)
- - baseaddr);
- this_highpc
- = (gdbarch_adjust_dwarf2_addr (gdbarch,
- pdi->highpc + baseaddr)
- - baseaddr);
- addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
- this_lowpc, this_highpc - 1,
- cu->per_cu->v.psymtab);
- }
- }
-
- if (pdi->has_range_info
- && dwarf2_ranges_read (pdi->ranges_offset, &pdi->lowpc, &pdi->highpc,
- cu,
- set_addrmap ? cu->per_cu->v.psymtab : nullptr,
- pdi->tag))
- {
- if (pdi->lowpc < *lowpc)
- *lowpc = pdi->lowpc;
- if (pdi->highpc > *highpc)
- *highpc = pdi->highpc;
- }
-
- if (pdi->has_pc_info || pdi->has_range_info
- || (!pdi->is_external && pdi->may_be_inlined))
- {
- if (!pdi->is_declaration)
- /* Ignore subprogram DIEs that do not have a name, they are
- illegal. Do not emit a complaint at this point, we will
- do so when we convert this psymtab into a symtab. */
- if (pdi->name (cu))
- add_partial_symbol (pdi, cu);
- }
- }
-
- if (! pdi->has_children)
- return;
-
- if (cu->per_cu->lang == language_ada
- || cu->per_cu->lang == language_fortran)
- {
- pdi = pdi->die_child;
- while (pdi != NULL)
- {
- pdi->fixup (cu);
- if (pdi->tag == DW_TAG_subprogram
- || pdi->tag == DW_TAG_inlined_subroutine
- || pdi->tag == DW_TAG_lexical_block)
- add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
- pdi = pdi->die_sibling;
- }
- }
-}
-
-/* Read a partial die corresponding to an enumeration type. */
-
-static void
-add_partial_enumeration (struct partial_die_info *enum_pdi,
- struct dwarf2_cu *cu)
-{
- struct partial_die_info *pdi;
-
- if (enum_pdi->name (cu) != NULL)
- add_partial_symbol (enum_pdi, cu);
-
- pdi = enum_pdi->die_child;
- while (pdi)
- {
- if (pdi->tag != DW_TAG_enumerator || pdi->raw_name == NULL)
- complaint (_("malformed enumerator DIE ignored"));
- else
- add_partial_symbol (pdi, cu);
- pdi = pdi->die_sibling;
- }
-}
-
-/* Return the initial uleb128 in the die at INFO_PTR. */
-
-static unsigned int
-peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
-{
- unsigned int bytes_read;
-
- return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-}
-
-/* Read the initial uleb128 in the die at INFO_PTR in compilation unit
- READER::CU. Use READER::ABBREV_TABLE to lookup any abbreviation.
-
- Return the corresponding abbrev, or NULL if the number is zero (indicating
- an empty DIE). In either case *BYTES_READ will be set to the length of
- the initial number. */
-
-static const struct abbrev_info *
-peek_die_abbrev (const die_reader_specs &reader,
- const gdb_byte *info_ptr, unsigned int *bytes_read)
-{
- dwarf2_cu *cu = reader.cu;
- bfd *abfd = reader.abfd;
- unsigned int abbrev_number
- = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
-
- if (abbrev_number == 0)
- return NULL;
-
- const abbrev_info *abbrev
- = reader.abbrev_table->lookup_abbrev (abbrev_number);
- if (!abbrev)
- {
- error (_("Dwarf Error: Could not find abbrev number %d in %s"
- " at offset %s [in module %s]"),
- abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
- sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
- }
-
- return abbrev;
-}
-
-/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
- Returns a pointer to the end of a series of DIEs, terminated by an empty
- DIE. Any children of the skipped DIEs will also be skipped. */
-
-static const gdb_byte *
-skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
-{
- while (1)
- {
- unsigned int bytes_read;
- const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
- &bytes_read);
-
- if (abbrev == NULL)
- return info_ptr + bytes_read;
- else
- info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
- }
-}
-
-/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
- INFO_PTR should point just after the initial uleb128 of a DIE, and the
- abbrev corresponding to that skipped uleb128 should be passed in
- ABBREV. Returns a pointer to this DIE's sibling, skipping any
- children. */
-
-static const gdb_byte *
-skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
- const struct abbrev_info *abbrev)
-{
- unsigned int bytes_read;
- struct attribute attr;
- bfd *abfd = reader->abfd;
- struct dwarf2_cu *cu = reader->cu;
- const gdb_byte *buffer = reader->buffer;
- const gdb_byte *buffer_end = reader->buffer_end;
- unsigned int form, i;
-
- for (i = 0; i < abbrev->num_attrs; i++)
- {
- /* The only abbrev we care about is DW_AT_sibling. */
- if (abbrev->attrs[i].name == DW_AT_sibling)
- {
- read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
- if (attr.form == DW_FORM_ref_addr)
- complaint (_("ignoring absolute DW_AT_sibling"));
- else
- {
- sect_offset off = attr.get_ref_die_offset ();
- const gdb_byte *sibling_ptr = buffer + to_underlying (off);
-
- if (sibling_ptr < info_ptr)
- complaint (_("DW_AT_sibling points backwards"));
- else if (sibling_ptr > reader->buffer_end)
- reader->die_section->overflow_complaint ();
- else
- return sibling_ptr;
- }
- }
-
- /* If it isn't DW_AT_sibling, skip this attribute. */
- form = abbrev->attrs[i].form;
- skip_attribute:
- switch (form)
+ /* If it isn't DW_AT_sibling, skip this attribute. */
+ form = abbrev->attrs[i].form;
+ skip_attribute:
+ switch (form)
{
case DW_FORM_ref_addr:
/* In DWARF 2, DW_FORM_ref_addr is address sized; in DWARF 3
}
}
- if (abbrev->has_children)
+ if (do_skip_children && abbrev->has_children)
return skip_children (reader, info_ptr);
else
return info_ptr;
}
-
-/* Locate ORIG_PDI's sibling.
- INFO_PTR should point to the start of the next DIE after ORIG_PDI. */
-
-static const gdb_byte *
-locate_pdi_sibling (const struct die_reader_specs *reader,
- struct partial_die_info *orig_pdi,
- const gdb_byte *info_ptr)
-{
- /* Do we know the sibling already? */
-
- if (orig_pdi->sibling)
- return orig_pdi->sibling;
-
- /* Are there any children to deal with? */
-
- if (!orig_pdi->has_children)
- return info_ptr;
-
- /* Skip the children the long way. */
-
- return skip_children (reader, info_ptr);
-}
-
-/* Expand this partial symbol table into a full symbol table. SELF is
- not NULL. */
-
-void
-dwarf2_psymtab::read_symtab (struct objfile *objfile)
-{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
- gdb_assert (!per_objfile->symtab_set_p (per_cu_data));
-
- /* If this psymtab is constructed from a debug-only objfile, the
- has_section_at_zero flag will not necessarily be correct. We
- can get the correct value for this flag by looking at the data
- associated with the (presumably stripped) associated objfile. */
- if (objfile->separate_debug_objfile_backlink)
- {
- dwarf2_per_objfile *per_objfile_backlink
- = get_dwarf2_per_objfile (objfile->separate_debug_objfile_backlink);
-
- per_objfile->per_bfd->has_section_at_zero
- = per_objfile_backlink->per_bfd->has_section_at_zero;
- }
-
- expand_psymtab (objfile);
-
- process_cu_includes (per_objfile);
-}
\f
/* Reading in full CUs. */
dwarf2_per_objfile *per_objfile,
enum language pretend_language)
{
- /* We may arrive here during partial symbol reading, if we need full
- DIEs to process an unusual case (e.g. template arguments). Do
- not queue PER_CU, just tell our caller to load its DIEs. */
- if (per_cu->per_bfd->reading_partial_symbols)
- {
- dwarf2_cu *cu = per_objfile->get_cu (per_cu);
-
- if (cu == NULL || cu->dies == NULL)
- return 1;
- return 0;
- }
-
/* Mark the dependence relation so that we don't flush PER_CU
too early. */
if (dependent_cu != NULL)
objfile_name (per_objfile->objfile));
}
-/* Read in full symbols for PST, and anything it depends on. */
-
-void
-dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
-{
- gdb_assert (!readin_p (objfile));
-
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- free_cached_comp_units freer (per_objfile);
- expand_dependencies (objfile);
-
- dw2_do_instantiate_symtab (per_cu_data, per_objfile, false);
- gdb_assert (get_compunit_symtab (objfile) != nullptr);
-}
-
-/* See psympriv.h. */
-
-bool
-dwarf2_psymtab::readin_p (struct objfile *objfile) const
-{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- return per_objfile->symtab_set_p (per_cu_data);
-}
-
-/* See psympriv.h. */
-
-compunit_symtab *
-dwarf2_psymtab::get_compunit_symtab (struct objfile *objfile) const
-{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- return per_objfile->get_symtab (per_cu_data);
-}
-
/* Trivial hash function for die_info: the hash value of a DIE
is its offset in .debug_info for this objfile. */
struct symbol *sym = list->symbol[i];
if (sym->language () == language_go
- && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ && sym->aclass () == LOC_BLOCK)
{
gdb::unique_xmalloc_ptr<char> this_package_name
(go_symbol_package_name (sym));
struct objfile *objfile = cu->per_objfile->objfile;
if (strcmp (package_name.get (), this_package_name.get ()) != 0)
complaint (_("Symtab %s has objects from two different Go packages: %s and %s"),
- (symbol_symtab (sym) != NULL
+ (sym->symtab () != NULL
? symtab_to_filename_for_display
- (symbol_symtab (sym))
+ (sym->symtab ())
: objfile_name (objfile)),
this_package_name.get (), package_name.get ());
}
sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
/* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
e.g., "main" finds the "main" module and not C's main(). */
- SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_TYPE (sym) = type;
+ sym->set_domain (STRUCT_DOMAIN);
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_type (type);
add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
}
name = tail;
if (*name != '$'
|| index >= field_type->num_fields ()
- || (TYPE_FIELD_LOC_KIND (field_type, index)
+ || (field_type->field (index).loc_kind ()
!= FIELD_LOC_KIND_BITPOS))
{
complaint (_("Could not parse Rust enum encoding string \"%s\""
}
++name;
- bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+ bit_offset += field_type->field (index).loc_bitpos ();
field_type = field_type->field (index).type ();
}
type->field (0).set_type (field_type);
TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
type->field (0).set_name ("<<discriminant>>");
- SET_FIELD_BITPOS (type->field (0), bit_offset);
+ type->field (0).set_loc_bitpos (bit_offset);
/* The order of fields doesn't really matter, so put the real
field at index 1 and the data-less field at index 2. */
/* NAME points into the original discriminant name, which
already has the correct lifetime. */
type->field (2).set_name (name);
- SET_FIELD_BITPOS (type->field (2), 0);
+ type->field (2).set_loc_bitpos (0);
/* Indicate that this is a variant type. */
static discriminant_range ranges[1] = { { 0, 0 } };
std::unordered_map<std::string, ULONGEST> discriminant_map;
for (int i = 0; i < enum_type->num_fields (); ++i)
{
- if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+ if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
{
const char *name
= rust_last_path_segment (enum_type->field (i).name ());
- discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+ discriminant_map[name] = enum_type->field (i).loc_enumval ();
}
}
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
- static_block = cu->get_builder ()->end_symtab_get_static_block (addr, 0, 1);
+ static_block
+ = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1);
/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
this comp unit. */
dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu);
- cust = cu->get_builder ()->end_symtab_from_static_block (static_block,
- SECT_OFF_TEXT (objfile),
- 0);
+ cust = cu->get_builder ()->end_compunit_symtab_from_static_block
+ (static_block, SECT_OFF_TEXT (objfile), 0);
if (cust != NULL)
{
compilation is from a C file generated by language preprocessors, do
not set the language if it was already deduced by start_subfile. */
if (!(cu->per_cu->lang == language_c
- && COMPUNIT_FILETABS (cust)->language != language_unknown))
- COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+ && cust->primary_filetab ()->language () != language_unknown))
+ cust->primary_filetab ()->set_language (cu->per_cu->lang);
/* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can
produce DW_AT_location with location lists but it can be possibly
options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
*/
if (cu->has_loclist && gcc_4_minor >= 5)
- cust->locations_valid = 1;
+ cust->set_locations_valid (true);
if (gcc_4_minor >= 5)
- cust->epilogue_unwind_valid = 1;
+ cust->set_epilogue_unwind_valid (true);
- cust->call_site_htab = cu->call_site_htab;
+ cust->set_call_site_htab (cu->call_site_htab);
}
per_objfile->set_symtab (cu->per_cu, cust);
do not set the language if it was already deduced by
start_subfile. */
if (!(cu->per_cu->lang == language_c
- && COMPUNIT_FILETABS (cust)->language != language_c))
- COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+ && cust->primary_filetab ()->language () != language_c))
+ cust->primary_filetab ()->set_language (cu->per_cu->lang);
}
}
else
bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu_data *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz, per_objfile);
+ = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+ per_objfile->per_bfd);
/* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
into another compilation unit, at root level. Regard this as a hint,
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ case DW_TAG_namelist:
process_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
/* FALLTHROUGH */
case DW_TAG_base_type:
case DW_TAG_subrange_type:
+ case DW_TAG_generic_subrange:
case DW_TAG_typedef:
/* Add a typedef symbol for the type definition, if it has a
DW_AT_name. */
else if (bytes != NULL)
{
v = allocate_value (type);
- memcpy (value_contents_writeable (v), bytes,
+ memcpy (value_contents_writeable (v).data (), bytes,
TYPE_LENGTH (type));
}
else
to look up their definition from their declaration so
the only disadvantage remains the minimal symbol variant
`long name(params)' does not have the proper inferior type. */
- demangled.reset (gdb_demangle (mangled,
- (DMGL_PARAMS | DMGL_ANSI
- | DMGL_RET_DROP)));
+ demangled = gdb_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
+ | DMGL_RET_DROP));
}
if (demangled)
canon = demangled.get ();
return cu->producer_is_gcc_lt_4_3;
}
-static file_and_directory
+static file_and_directory &
find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
{
- file_and_directory res;
+ if (cu->per_cu->fnd != nullptr)
+ return *cu->per_cu->fnd;
/* Find the filename. Do not use dwarf2_name here, since the filename
is not a source language identifier. */
- res.name = dwarf2_string_attr (die, DW_AT_name, cu);
- res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
-
- if (res.comp_dir == NULL
- && producer_is_gcc_lt_4_3 (cu) && res.name != NULL
- && IS_ABSOLUTE_PATH (res.name))
- {
- std::string comp_dir_storage = ldirname (res.name);
- if (!comp_dir_storage.empty ())
- res.comp_dir
- = cu->per_objfile->objfile->intern (comp_dir_storage.c_str ());
- }
- if (res.comp_dir != NULL)
- {
- /* Irix 6.2 native cc prepends <machine>.: to the compilation
- directory, get rid of it. */
- const char *cp = strchr (res.comp_dir, ':');
-
- if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/')
- res.comp_dir = cp + 1;
- }
+ file_and_directory res (dwarf2_string_attr (die, DW_AT_name, cu),
+ dwarf2_string_attr (die, DW_AT_comp_dir, cu));
- if (res.name == NULL)
- res.name = "<unknown>";
+ if (res.get_comp_dir () == nullptr
+ && producer_is_gcc_lt_4_3 (cu)
+ && res.get_name () != nullptr
+ && IS_ABSOLUTE_PATH (res.get_name ()))
+ res.set_comp_dir (ldirname (res.get_name ()));
- return res;
+ cu->per_cu->fnd.reset (new file_and_directory (std::move (res)));
+ return *cu->per_cu->fnd;
}
/* Handle DW_AT_stmt_list for a compilation unit.
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const file_and_directory &fnd, CORE_ADDR lowpc) /* ARI: editCase function */
+ CORE_ADDR lowpc) /* ARI: editCase function */
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct attribute *attr;
gdb_assert (die->tag != DW_TAG_partial_unit);
}
decode_mapping = (die->tag != DW_TAG_partial_unit);
- dwarf_decode_lines (cu->line_header, fnd, cu, nullptr, lowpc,
- decode_mapping);
-
+ dwarf_decode_lines (cu->line_header, cu, lowpc, decode_mapping);
}
/* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */
lowpc = highpc;
lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
- file_and_directory fnd = find_file_and_directory (die, cu);
+ file_and_directory &fnd = find_file_and_directory (die, cu);
- cu->start_symtab (fnd.name, fnd.comp_dir, lowpc);
+ cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
+ lowpc);
gdb_assert (per_objfile->sym_cu == nullptr);
scoped_restore restore_sym_cu
/* Decode line number information if present. We do this before
processing child DIEs, so that the line header table is available
- for DW_AT_decl_file. */
- handle_DW_AT_stmt_list (die, cu, fnd, lowpc);
+ for DW_AT_decl_file. The PC check is here because, if LOWPC and
+ HIGHPC are both 0x0, then there won't be any interesting code in
+ the CU, but a check later on (in
+ lnp_state_machine::check_line_address) will fail to properly
+ exclude an entry that was removed via --gc-sections. */
+ if (lowpc != highpc)
+ handle_DW_AT_stmt_list (die, cu, lowpc);
/* Process all dies in compilation unit. */
if (die->child != NULL)
if (lh == NULL)
{
if (first_time)
- start_symtab ("", NULL, 0);
+ start_compunit_symtab ("", NULL, 0);
else
{
gdb_assert (tug_unshare->symtabs == NULL);
gdb_assert (m_builder == nullptr);
struct compunit_symtab *cust = tug_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
- (COMPUNIT_OBJFILE (cust), "",
- COMPUNIT_DIRNAME (cust),
+ (cust->objfile (), "",
+ cust->dirname (),
compunit_language (cust),
0, cust));
list_in_scope = get_builder ()->get_file_symbols ();
if (first_time)
{
- struct compunit_symtab *cust = start_symtab ("", NULL, 0);
+ struct compunit_symtab *cust = start_compunit_symtab ("", NULL, 0);
/* Note: We don't assign tu_group->compunit_symtab yet because we're
still initializing it, and our caller (a few levels up)
time. */
tug_unshare->symtabs
- = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+ = XOBNEWVEC (&cust->objfile ()->objfile_obstack,
struct symtab *, line_header->file_names_size ());
auto &file_names = line_header->file_names ();
assume there's a simple mapping from
cu->line_header->file_names to subfiles, plus
cu->line_header->file_names may contain dups. */
- b->get_current_subfile ()->symtab
- = allocate_symtab (cust, b->get_current_subfile ()->name);
+ const char *name = b->get_current_subfile ()->name.c_str ();
+ b->get_current_subfile ()->symtab = allocate_symtab (cust, name);
}
fe.symtab = b->get_current_subfile ()->symtab;
gdb_assert (m_builder == nullptr);
struct compunit_symtab *cust = tug_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
- (COMPUNIT_OBJFILE (cust), "",
- COMPUNIT_DIRNAME (cust),
+ (cust->objfile (), "",
+ cust->dirname (),
compunit_language (cust),
0, cust));
list_in_scope = get_builder ()->get_file_symbols ();
gdb::unique_xmalloc_ptr<char> search_path_holder;
if (search_cwd)
{
- if (*debug_file_directory != '\0')
+ if (!debug_file_directory.empty ())
{
search_path_holder.reset (concat (".", dirname_separator_string,
- debug_file_directory,
+ debug_file_directory.c_str (),
(char *) NULL));
search_path = search_path_holder.get ();
}
search_path = ".";
}
else
- search_path = debug_file_directory;
+ search_path = debug_file_directory.c_str ();
/* Add the path for the executable binary to the list of search paths. */
std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile));
if (comp_dir != NULL)
{
- gdb::unique_xmalloc_ptr<char> path_to_try
- (concat (comp_dir, SLASH_STRING, file_name, (char *) NULL));
+ std::string path_to_try = path_join (comp_dir, file_name);
/* NOTE: If comp_dir is a relative path, this will also try the
search path, which seems useful. */
- gdb_bfd_ref_ptr abfd (try_open_dwop_file (per_objfile, path_to_try.get (),
- 0 /*is_dwp*/,
- 1 /*search_cwd*/));
+ gdb_bfd_ref_ptr abfd (try_open_dwop_file
+ (per_objfile, path_to_try.c_str (), 0 /*is_dwp*/, 1 /*search_cwd*/));
+
if (abfd != NULL)
return abfd;
}
/* That didn't work, try debug-file-directory, which, despite its name,
is a list of paths. */
- if (*debug_file_directory == '\0')
+ if (debug_file_directory.empty ())
return NULL;
return try_open_dwop_file (per_objfile, file_name,
size of each of the DWO debugging sections we are interested in. */
static void
-dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp,
- dwo_sections *dwo_sections)
+dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, dwo_sections *dwo_sections)
{
const struct dwop_section_names *names = &dwop_section_names;
+ struct dwarf2_section_info *dw_sect = nullptr;
+
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwo_sections->abbrev.s.section = sectp;
- dwo_sections->abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwo_sections->info.s.section = sectp;
- dwo_sections->info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwo_sections->line.s.section = sectp;
- dwo_sections->line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->line;
else if (names->loc_dwo.matches (sectp->name))
- {
- dwo_sections->loc.s.section = sectp;
- dwo_sections->loc.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->loc;
else if (names->loclists_dwo.matches (sectp->name))
- {
- dwo_sections->loclists.s.section = sectp;
- dwo_sections->loclists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->loclists;
else if (names->macinfo_dwo.matches (sectp->name))
- {
- dwo_sections->macinfo.s.section = sectp;
- dwo_sections->macinfo.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->macinfo;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwo_sections->macro.s.section = sectp;
- dwo_sections->macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->macro;
else if (names->rnglists_dwo.matches (sectp->name))
- {
- dwo_sections->rnglists.s.section = sectp;
- dwo_sections->rnglists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->rnglists;
else if (names->str_dwo.matches (sectp->name))
- {
- dwo_sections->str.s.section = sectp;
- dwo_sections->str.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->str;
else if (names->str_offsets_dwo.matches (sectp->name))
- {
- dwo_sections->str_offsets.s.section = sectp;
- dwo_sections->str_offsets.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->str_offsets;
else if (names->types_dwo.matches (sectp->name))
{
struct dwarf2_section_info type_section;
memset (&type_section, 0, sizeof (type_section));
- type_section.s.section = sectp;
- type_section.size = bfd_section_size (sectp);
dwo_sections->types.push_back (type_section);
+ dw_sect = &dwo_sections->types.back ();
+ }
+
+ if (dw_sect != nullptr)
+ {
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
dwo_file->dbfd = std::move (dbfd);
for (asection *sec : gdb_bfd_sections (dwo_file->dbfd))
- dwarf2_locate_dwo_sections (dwo_file->dbfd.get (), sec,
- &dwo_file->sections);
+ dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (),
+ sec, &dwo_file->sections);
create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info,
dwo_file->cus);
we are interested in. */
static void
-dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
- dwp_file *dwp_file)
+dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, dwp_file *dwp_file)
{
const struct dwop_section_names *names = &dwop_section_names;
unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->str_dwo.matches (sectp->name))
- {
- dwp_file->sections.str.s.section = sectp;
- dwp_file->sections.str.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.str;
else if (names->cu_index.matches (sectp->name))
- {
- dwp_file->sections.cu_index.s.section = sectp;
- dwp_file->sections.cu_index.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.cu_index;
else if (names->tu_index.matches (sectp->name))
+ dw_sect = &dwp_file->sections.tu_index;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.tu_index.s.section = sectp;
- dwp_file->sections.tu_index.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */
static void
-dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, void *dwp_file_ptr)
{
struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
const struct dwop_section_names *names = &dwop_section_names;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwp_file->sections.abbrev.s.section = sectp;
- dwp_file->sections.abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwp_file->sections.info.s.section = sectp;
- dwp_file->sections.info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwp_file->sections.line.s.section = sectp;
- dwp_file->sections.line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.line;
else if (names->loc_dwo.matches (sectp->name))
- {
- dwp_file->sections.loc.s.section = sectp;
- dwp_file->sections.loc.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.loc;
else if (names->macinfo_dwo.matches (sectp->name))
- {
- dwp_file->sections.macinfo.s.section = sectp;
- dwp_file->sections.macinfo.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macinfo;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwp_file->sections.macro.s.section = sectp;
- dwp_file->sections.macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macro;
else if (names->str_offsets_dwo.matches (sectp->name))
- {
- dwp_file->sections.str_offsets.s.section = sectp;
- dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.str_offsets;
else if (names->types_dwo.matches (sectp->name))
+ dw_sect = &dwp_file->sections.types;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.types.s.section = sectp;
- dwp_file->sections.types.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */
static void
-dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, void *dwp_file_ptr)
{
struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
const struct dwop_section_names *names = &dwop_section_names;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwp_file->sections.abbrev.s.section = sectp;
- dwp_file->sections.abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwp_file->sections.info.s.section = sectp;
- dwp_file->sections.info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwp_file->sections.line.s.section = sectp;
- dwp_file->sections.line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.line;
else if (names->loclists_dwo.matches (sectp->name))
- {
- dwp_file->sections.loclists.s.section = sectp;
- dwp_file->sections.loclists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.loclists;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwp_file->sections.macro.s.section = sectp;
- dwp_file->sections.macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macro;
else if (names->rnglists_dwo.matches (sectp->name))
- {
- dwp_file->sections.rnglists.s.section = sectp;
- dwp_file->sections.rnglists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.rnglists;
else if (names->str_offsets_dwo.matches (sectp->name))
+ dw_sect = &dwp_file->sections.str_offsets;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.str_offsets.s.section = sectp;
- dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
[IWBN if the dwp file name was recorded in the executable, akin to
.gnu_debuglink, but that doesn't exist yet.]
Strip the directory from FILE_NAME and search again. */
- if (*debug_file_directory != '\0')
+ if (!debug_file_directory.empty ())
{
/* Don't implicitly search the current directory here.
If the user wants to search "." to handle this case,
dwp_file->num_sections, asection *);
for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
- dwarf2_locate_common_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_common_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0);
for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
{
if (dwp_file->version == 2)
- dwarf2_locate_v2_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_v2_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
else
- dwarf2_locate_v5_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_v5_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
}
}
/* Ignore functions with missing or invalid low and high pc attributes. */
- if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)
+ if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr)
<= PC_BOUNDS_INVALID)
{
attr = dwarf2_attr (die, DW_AT_external, cu);
of gdb assume that symbols do, and this is reasonably
true. */
for (symbol *sym : template_args)
- symbol_set_symtab (sym, symbol_symtab (templ_func));
+ sym->set_symtab (templ_func->symtab ());
}
/* In C++, we can have functions nested inside functions (e.g., when
as multiple lexical blocks? Handling children in a sane way would
be nasty. Might be easier to properly extend generic blocks to
describe ranges. */
- switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
+ switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr))
{
case PC_BOUNDS_NOT_PRESENT:
/* DW_TAG_lexical_block has no attributes, process its children as if
cu->get_builder ()->set_local_using_directives (cstk.local_using_directives);
}
+static void dwarf2_ranges_read_low_addrs (unsigned offset,
+ struct dwarf2_cu *cu,
+ dwarf_tag tag,
+ std::vector<CORE_ADDR> &result);
+
/* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */
static void
struct gdbarch *gdbarch = objfile->arch ();
CORE_ADDR pc, baseaddr;
struct attribute *attr;
- struct call_site *call_site, call_site_local;
void **slot;
int nparams;
struct die_info *child_die;
}
pc = attr->as_address () + baseaddr;
pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc);
+ pc -= baseaddr;
if (cu->call_site_htab == NULL)
- cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
- NULL, &objfile->objfile_obstack,
+ cu->call_site_htab = htab_create_alloc_ex (16, call_site::hash,
+ call_site::eq, NULL,
+ &objfile->objfile_obstack,
hashtab_obstack_allocate, NULL);
- call_site_local.pc = pc;
+ struct call_site call_site_local (pc, nullptr, nullptr);
slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT);
if (*slot != NULL)
{
nparams++;
}
- call_site
- = ((struct call_site *)
- obstack_alloc (&objfile->objfile_obstack,
- sizeof (*call_site)
- + (sizeof (*call_site->parameter) * (nparams - 1))));
+ struct call_site *call_site
+ = new (XOBNEWVAR (&objfile->objfile_obstack,
+ struct call_site,
+ sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams))
+ struct call_site (pc, cu->per_cu, per_objfile);
*slot = call_site;
- memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
- call_site->pc = pc;
+
+ /* We never call the destructor of call_site, so we must ensure it is
+ trivially destructible. */
+ gdb_static_assert(std::is_trivially_destructible<struct call_site>::value);
if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
|| dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
/* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin. */
attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
}
- SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
+
+ call_site->target.set_loc_dwarf_block (nullptr);
if (!attr || (attr->form_is_block () && attr->as_block ()->size == 0))
/* Keep NULL DWARF_BLOCK. */;
else if (attr->form_is_block ())
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
+ call_site->target.set_loc_dwarf_block (dlbaton);
}
else if (attr->form_is_ref ())
{
target_die = follow_die_ref (die, attr, &target_cu);
gdb_assert (target_cu->per_objfile->objfile == objfile);
+
+ struct attribute *ranges_attr
+ = dwarf2_attr (target_die, DW_AT_ranges, target_cu);
+
if (die_is_declaration (target_die, target_cu))
{
const char *target_physname;
"physname, for referencing DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
else
- SET_FIELD_PHYSNAME (call_site->target, target_physname);
+ call_site->target.set_loc_physname (target_physname);
+ }
+ else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ())
+ {
+ ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+ + target_cu->gnu_ranges_base);
+ std::vector<CORE_ADDR> addresses;
+ dwarf2_ranges_read_low_addrs (ranges_offset, target_cu,
+ target_die->tag, addresses);
+ CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR,
+ addresses.size ());
+ std::copy (addresses.begin (), addresses.end (), saved);
+ call_site->target.set_loc_array (addresses.size (), saved);
}
else
{
CORE_ADDR lowpc;
/* DW_AT_entry_pc should be preferred. */
- if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
+ if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+ nullptr, nullptr)
<= PC_BOUNDS_INVALID)
complaint (_("DW_AT_call_target target DIE has invalid "
"low pc, for referencing DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
else
{
- lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
- SET_FIELD_PHYSADDR (call_site->target, lowpc);
+ lowpc = (gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr)
+ - baseaddr);
+ call_site->target.set_loc_physaddr (lowpc);
}
}
}
"block nor reference, for DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
- call_site->per_cu = cu->per_cu;
- call_site->per_objfile = per_objfile;
-
for (child_die = die->child;
child_die && child_die->tag;
child_die = child_die->sibling)
/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
Return 1 if the attributes are present and valid, otherwise, return 0.
- If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'. */
+ TAG is passed to dwarf2_ranges_process. If MAP is not NULL, then
+ ranges in MAP are set, using DATUM as the value. */
static int
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR *high_return, struct dwarf2_cu *cu,
- dwarf2_psymtab *ranges_pst, dwarf_tag tag)
+ addrmap *map, void *datum, dwarf_tag tag)
{
struct objfile *objfile = cu->per_objfile->objfile;
- dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
struct gdbarch *gdbarch = objfile->arch ();
const CORE_ADDR baseaddr = objfile->text_section_offset ();
int low_set = 0;
retval = dwarf2_ranges_process (offset, cu, tag,
[&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
{
- if (ranges_pst != NULL)
+ if (map != nullptr)
{
CORE_ADDR lowpc;
CORE_ADDR highpc;
highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
range_end + baseaddr)
- baseaddr);
- addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
- lowpc, highpc - 1, ranges_pst);
+ addrmap_set_empty (map, lowpc, highpc - 1, datum);
}
/* FIXME: This is recording everything as a low-high
return 1;
}
+/* Process ranges and fill in a vector of the low PC values only. */
+
+static void
+dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu,
+ dwarf_tag tag,
+ std::vector<CORE_ADDR> &result)
+{
+ dwarf2_ranges_process (offset, cu, tag,
+ [&] (CORE_ADDR start, CORE_ADDR end)
+ {
+ result.push_back (start);
+ });
+}
+
/* Get low and high pc attributes from a die. See enum pc_bounds_kind
definition for the return value. *LOWPC and *HIGHPC are set iff
neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */
static enum pc_bounds_kind
dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
CORE_ADDR *highpc, struct dwarf2_cu *cu,
- dwarf2_psymtab *pst)
+ addrmap *map, void *datum)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct attribute *attr;
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
- if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
- die->tag))
+ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu,
+ map, datum, die->tag))
return PC_BOUNDS_INVALID;
/* Found discontinuous range of addresses. */
ret = PC_BOUNDS_RANGES;
CORE_ADDR low, high;
struct die_info *child = die->child;
- if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES)
+ if (dwarf2_get_pc_bounds (die, &low, &high, cu, nullptr, nullptr)
+ >= PC_BOUNDS_RANGES)
{
*lowpc = std::min (*lowpc, low);
*highpc = std::max (*highpc, high);
CORE_ADDR best_high = (CORE_ADDR) 0;
CORE_ADDR current_low, current_high;
- if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)
+ if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu,
+ nullptr, nullptr)
>= PC_BOUNDS_RANGES)
{
best_low = current_low;
{
cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
+ cu->producer_is_gcc_11 = major == 11;
}
else if (producer_is_icc (cu->producer, &major, &minor))
{
if (attr->form_is_constant ())
{
LONGEST offset = attr->constant_value (0);
- SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+
+ /* Work around this GCC 11 bug, where it would erroneously use -1
+ data member locations, instead of 0:
+
+ Negative DW_AT_data_member_location
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378
+ */
+ if (offset == -1 && cu->producer_is_gcc_11)
+ {
+ complaint (_("DW_AT_data_member_location value of -1, assuming 0"));
+ offset = 0;
+ }
+
+ field->set_loc_bitpos (offset * bits_per_byte);
}
else if (attr->form_is_section_offset ())
dwarf2_complex_location_expr_complaint ();
bool handled;
CORE_ADDR offset = decode_locdesc (attr->as_block (), cu, &handled);
if (handled)
- SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+ field->set_loc_bitpos (offset * bits_per_byte);
else
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- SET_FIELD_DWARF_BLOCK (*field, dlbaton);
+ field->set_loc_dwarf_block (dlbaton);
}
}
else
{
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
if (attr != nullptr)
- SET_FIELD_BITPOS (*field, attr->constant_value (0));
+ field->set_loc_bitpos (attr->constant_value (0));
}
}
fp = &new_field->field;
- if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
- {
+ if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item)
+ && !die_is_declaration (die, cu))
+ {
+ if (die->tag == DW_TAG_namelist_item)
+ {
+ /* Typically, DW_TAG_namelist_item are references to namelist items.
+ If so, follow that reference. */
+ struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
+ struct die_info *item_die = nullptr;
+ struct dwarf2_cu *item_cu = cu;
+ if (attr1->form_is_ref ())
+ item_die = follow_die_ref (die, attr1, &item_cu);
+ if (item_die != nullptr)
+ die = item_die;
+ }
/* Data member other than a C++ static data member. */
/* Get type of field. */
fp->set_type (die_type (die, cu));
- SET_FIELD_BITPOS (*fp, 0);
+ fp->set_loc_bitpos (0);
/* Get bit size of field (zero if none). */
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
anonymous object to the MSB of the field. We don't
have to do anything special since we don't need to
know the size of the anonymous object. */
- SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
- + attr->constant_value (0)));
+ fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0));
}
else
{
bit field. */
anonymous_size = TYPE_LENGTH (fp->type ());
}
- SET_FIELD_BITPOS (*fp,
- (FIELD_BITPOS (*fp)
- + anonymous_size * bits_per_byte
- - bit_offset - FIELD_BITSIZE (*fp)));
+ fp->set_loc_bitpos (fp->loc_bitpos ()
+ + anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp));
}
}
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
- SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
+ fp->set_loc_physname (physname ? physname : "");
fp->set_type (die_type (die, cu));
fp->set_name (fieldname);
}
offset_map[fip->fields[i].offset] = i;
struct objfile *objfile = cu->per_objfile->objfile;
- gdb::array_view<variant_part> parts
+ gdb::array_view<const variant_part> parts
= create_variant_parts (&objfile->objfile_obstack, offset_map, fip,
fip->variant_parts);
{
type->set_code (TYPE_CODE_UNION);
}
+ else if (die->tag == DW_TAG_namelist)
+ {
+ type->set_code (TYPE_CODE_NAMELIST);
+ }
else
{
type->set_code (TYPE_CODE_STRUCT);
struct dwarf2_cu *cu)
{
if (child_die->tag == DW_TAG_member
- || child_die->tag == DW_TAG_variable)
+ || child_die->tag == DW_TAG_variable
+ || child_die->tag == DW_TAG_namelist_item)
{
/* NOTE: carlton/2002-11-05: A C++ static data member
should be a DW_TAG_member that is a declaration, but
handle_variant (child_die, type, fi, template_args, cu);
}
-/* Finish creating a structure or union type, including filling in
- its members and creating a symbol for it. */
+/* Finish creating a structure or union type, including filling in its
+ members and creating a symbol for it. This function also handles Fortran
+ namelist variables, their items or members and creating a symbol for
+ them. */
static void
process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct symtab *symtab;
if (sym != nullptr)
- symtab = symbol_symtab (sym);
+ symtab = sym->symtab ();
else if (cu->line_header != nullptr)
{
/* Any related symtab will do. */
other parts of gdb assume that symbols do, and this is
reasonably true. */
for (int i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (type); ++i)
- symbol_set_symtab (TYPE_TEMPLATE_ARGUMENT (type, i), symtab);
+ TYPE_TEMPLATE_ARGUMENT (type, i)->set_symtab (symtab);
}
}
}
fields.emplace_back ();
struct field &field = fields.back ();
field.set_name (dwarf2_physname (name, child_die, cu));
- SET_FIELD_ENUMVAL (field, value);
+ field.set_loc_enumval (value);
}
if (!fields.empty ())
else
return false;
- SET_FIELD_BITPOS (*field, 8 * offset);
+ field->set_loc_bitpos (8 * offset);
if (size != TYPE_LENGTH (field->type ()))
FIELD_BITSIZE (*field) = 8 * size;
bounds->num_fields () * sizeof (struct field));
int last_fieldno = range_fields.size () - 1;
- int bounds_size = (TYPE_FIELD_BITPOS (bounds, last_fieldno) / 8
+ int bounds_size = (bounds->field (last_fieldno).loc_bitpos () / 8
+ TYPE_LENGTH (bounds->field (last_fieldno).type ()));
TYPE_LENGTH (bounds) = align_up (bounds_size, max_align);
result->field (1).set_name ("P_BOUNDS");
result->field (1).set_type (lookup_pointer_type (bounds));
- SET_FIELD_BITPOS (result->field (1), 8 * bounds_offset);
+ result->field (1).set_loc_bitpos (8 * bounds_offset);
result->set_name (type->name ());
TYPE_LENGTH (result) = (TYPE_LENGTH (result->field (0).type ())
child_die = die->child;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_subrange_type)
+ if (child_die->tag == DW_TAG_subrange_type
+ || child_die->tag == DW_TAG_generic_subrange)
{
struct type *child_type = read_type_die (child_die, cu);
gdb_assert (ptr - baton->data == baton->size);
SYMBOL_LOCATION_BATON (sym) = baton;
- SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+ sym->set_aclass_index (dwarf2_locexpr_index);
}
/* Create appropriate locally-scoped variables for all the
}
sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
- SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
+ sym->set_value_common_block (common_block);
}
}
/* Pass 0 as the default as we know this attribute is constant
and the default value will not be returned. */
LONGEST sz = len->constant_value (0);
- prop_type = cu->per_objfile->int_type (sz, true);
+ prop_type = objfile_int_type (objfile, sz, true);
}
else
{
break;
case DW_ATE_UTF:
{
- if (bits == 16)
- type = builtin_type (arch)->builtin_char16;
- else if (bits == 32)
- type = builtin_type (arch)->builtin_char32;
- else
- {
- complaint (_("unsupported DW_ATE_UTF bit size: '%d'"),
- bits);
- type = dwarf2_init_integer_type (cu, objfile, bits, 1, name);
- }
+ type = init_character_type (objfile, bits, 1, name);
return set_die_type (die, type, cu);
}
break;
break;
}
- if (name && strcmp (name, "char") == 0)
+ if (type->code () == TYPE_CODE_INT
+ && name != nullptr
+ && strcmp (name, "char") == 0)
type->set_has_no_signedness (true);
maybe_set_alignment (cu, die, type);
}
else if (attr->form_is_constant ())
prop->set_const_val (attr->constant_value (0));
- else
+ else if (attr->form_is_section_offset ())
{
- dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
- dwarf2_name (die, cu));
- return 0;
+ switch (attr->name)
+ {
+ case DW_AT_string_length:
+ baton = XOBNEW (obstack, struct dwarf2_property_baton);
+ baton->property_type = default_type;
+ fill_in_loclist_baton (cu, &baton->loclist, attr);
+ prop->set_loclist (baton);
+ gdb_assert (prop->baton () != NULL);
+ break;
+ default:
+ goto invalid;
+ }
}
+ else
+ goto invalid;
return 1;
+
+ invalid:
+ dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+ dwarf2_name (die, cu));
+ return 0;
}
/* See read.h. */
-struct type *
-dwarf2_per_objfile::int_type (int size_in_bytes, bool unsigned_p) const
-{
- struct type *int_type;
-
- /* Helper macro to examine the various builtin types. */
-#define TRY_TYPE(F) \
- int_type = (unsigned_p \
- ? objfile_type (objfile)->builtin_unsigned_ ## F \
- : objfile_type (objfile)->builtin_ ## F); \
- if (int_type != NULL && TYPE_LENGTH (int_type) == size_in_bytes) \
- return int_type
-
- TRY_TYPE (char);
- TRY_TYPE (short);
- TRY_TYPE (int);
- TRY_TYPE (long);
- TRY_TYPE (long_long);
-
-#undef TRY_TYPE
-
- gdb_assert_not_reached ("unable to find suitable integer type");
-}
-
/* Read the DW_AT_type attribute for a sub-range. If this attribute is not
present (which is valid) then compute the default type based on the
compilation units address size. */
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- reader->die_section->get_name (),
- (unsigned) (info_ptr - reader->die_section->buffer),
- bfd_get_filename (reader->abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ reader->die_section->get_name (),
+ (unsigned) (info_ptr - reader->die_section->buffer),
+ bfd_get_filename (reader->abfd));
dump_die (die, dwarf_die_debug);
}
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- reader->die_section->get_name (),
- (unsigned) (info_ptr - reader->die_section->buffer),
- bfd_get_filename (reader->abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ reader->die_section->get_name (),
+ (unsigned) (info_ptr - reader->die_section->buffer),
+ bfd_get_filename (reader->abfd));
dump_die (*diep, dwarf_die_debug);
}
}
\f
-/* Returns nonzero if TAG represents a type that we might generate a partial
- symbol for. */
-
-static int
-is_type_tag_for_partial (int tag, enum language lang)
+void
+cooked_indexer::check_bounds (cutu_reader *reader)
{
- switch (tag)
+ if (reader->cu->per_cu->addresses_seen)
+ return;
+
+ dwarf2_cu *cu = reader->cu;
+
+ CORE_ADDR best_lowpc = 0, best_highpc = 0;
+ /* Possibly set the default values of LOWPC and HIGHPC from
+ `DW_AT_ranges'. */
+ dwarf2_find_base_address (reader->comp_unit_die, cu);
+ enum pc_bounds_kind cu_bounds_kind
+ = dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc,
+ cu, m_index_storage->get_addrmap (), cu->per_cu);
+ if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
{
-#if 0
- /* Some types that would be reasonable to generate partial symbols for,
- that we don't at present. Note that normally this does not
- matter, mainly because C compilers don't give names to these
- types, but instead emit DW_TAG_typedef. */
- case DW_TAG_file_type:
- case DW_TAG_ptr_to_member_type:
- case DW_TAG_set_type:
- case DW_TAG_string_type:
- case DW_TAG_subroutine_type:
-#endif
+ struct objfile *objfile = cu->per_objfile->objfile;
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ struct gdbarch *gdbarch = objfile->arch ();
+ CORE_ADDR low
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
+ - baseaddr);
+ CORE_ADDR high
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
+ - baseaddr - 1);
+ /* Store the contiguous range if it is not empty; it can be
+ empty for CUs with no code. */
+ addrmap_set_empty (m_index_storage->get_addrmap (), low, high,
+ cu->per_cu);
- /* GNAT may emit an array with a name, but no typedef, so we
- need to make a symbol in this case. */
- case DW_TAG_array_type:
- return lang == language_ada;
+ cu->per_cu->addresses_seen = true;
+ }
+}
- case DW_TAG_base_type:
+/* Helper function that returns true if TAG can have a linkage
+ name. */
+
+static bool
+tag_can_have_linkage_name (enum dwarf_tag tag)
+{
+ switch (tag)
+ {
+ /* We include types here because an anonymous C++ type might
+ have a name for linkage purposes. */
case DW_TAG_class_type:
- case DW_TAG_interface_type:
- case DW_TAG_enumeration_type:
case DW_TAG_structure_type:
- case DW_TAG_subrange_type:
- case DW_TAG_typedef:
case DW_TAG_union_type:
- return 1;
+ case DW_TAG_variable:
+ case DW_TAG_subprogram:
+ return true;
+
default:
- return 0;
+ return false;
}
}
-/* Load all DIEs that are interesting for partial symbols into memory. */
-
-static struct partial_die_info *
-load_partial_dies (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr, int building_psymtab)
+cutu_reader *
+cooked_indexer::ensure_cu_exists (cutu_reader *reader,
+ dwarf2_per_objfile *per_objfile,
+ sect_offset sect_off, bool is_dwz,
+ bool for_scanning)
{
- struct dwarf2_cu *cu = reader->cu;
- struct objfile *objfile = cu->per_objfile->objfile;
- struct partial_die_info *parent_die, *last_die, *first_die = NULL;
- unsigned int bytes_read;
- unsigned int load_all = 0;
- int nesting_level = 1;
-
- parent_die = NULL;
- last_die = NULL;
-
- gdb_assert (cu->per_cu != NULL);
- if (cu->load_all_dies)
- load_all = 1;
+ /* Lookups for type unit references are always in the CU, and
+ cross-CU references will crash. */
+ if (reader->cu->per_cu->is_dwz == is_dwz
+ && reader->cu->header.offset_in_cu_p (sect_off))
+ return reader;
- cu->partial_dies
- = htab_create_alloc_ex (cu->header.length / 12,
- partial_die_hash,
- partial_die_eq,
- NULL,
- &cu->comp_unit_obstack,
- hashtab_obstack_allocate,
- dummy_obstack_deallocate);
+ dwarf2_per_cu_data *per_cu
+ = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+ per_objfile->per_bfd);
- while (1)
+ /* When scanning, we only want to visit a given CU a single time.
+ Doing this check here avoids self-imports as well. */
+ if (for_scanning)
{
- const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
- &bytes_read);
-
- /* A NULL abbrev means the end of a series of children. */
- if (abbrev == NULL)
- {
- if (--nesting_level == 0)
- return first_die;
-
- info_ptr += bytes_read;
- last_die = parent_die;
- parent_die = parent_die->die_parent;
- continue;
- }
-
- /* Check for template arguments. We never save these; if
- they're seen, we just mark the parent, and go on our way. */
- if (parent_die != NULL
- && cu->per_cu->lang == language_cplus
- && (abbrev->tag == DW_TAG_template_type_param
- || abbrev->tag == DW_TAG_template_value_param))
- {
- parent_die->has_template_arguments = 1;
-
- if (!load_all)
- {
- /* We don't need a partial DIE for the template argument. */
- info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
- continue;
- }
- }
-
- /* We only recurse into c++ subprograms looking for template arguments.
- Skip their other children. */
- if (!load_all
- && cu->per_cu->lang == language_cplus
- && parent_die != NULL
- && parent_die->tag == DW_TAG_subprogram
- && abbrev->tag != DW_TAG_inlined_subroutine)
- {
- info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
- continue;
- }
-
- /* Check whether this DIE is interesting enough to save. Normally
- we would not be interested in members here, but there may be
- later variables referencing them via DW_AT_specification (for
- static members). */
- if (!load_all
- && !is_type_tag_for_partial (abbrev->tag, cu->per_cu->lang)
- && abbrev->tag != DW_TAG_constant
- && abbrev->tag != DW_TAG_enumerator
- && abbrev->tag != DW_TAG_subprogram
- && abbrev->tag != DW_TAG_inlined_subroutine
- && abbrev->tag != DW_TAG_lexical_block
- && abbrev->tag != DW_TAG_variable
- && abbrev->tag != DW_TAG_namespace
- && abbrev->tag != DW_TAG_module
- && abbrev->tag != DW_TAG_member
- && abbrev->tag != DW_TAG_imported_unit
- && abbrev->tag != DW_TAG_imported_declaration)
- {
- /* Otherwise we skip to the next sibling, if any. */
- info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
- continue;
- }
-
- struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
- abbrev);
-
- info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read);
-
- /* This two-pass algorithm for processing partial symbols has a
- high cost in cache pressure. Thus, handle some simple cases
- here which cover the majority of C partial symbols. DIEs
- which neither have specification tags in them, nor could have
- specification tags elsewhere pointing at them, can simply be
- processed and discarded.
-
- This segment is also optional; scan_partial_symbols and
- add_partial_symbol will handle these DIEs if we chain
- them in normally. When compilers which do not emit large
- quantities of duplicate debug information are more common,
- this code can probably be removed. */
-
- /* Any complete simple types at the top level (pretty much all
- of them, for a language without namespaces), can be processed
- directly. */
- if (parent_die == NULL
- && pdi.has_specification == 0
- && pdi.is_declaration == 0
- && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
- || pdi.tag == DW_TAG_base_type
- || pdi.tag == DW_TAG_array_type
- || pdi.tag == DW_TAG_subrange_type))
- {
- if (building_psymtab && pdi.raw_name != NULL)
- add_partial_symbol (&pdi, cu);
-
- info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
- continue;
- }
-
- /* The exception for DW_TAG_typedef with has_children above is
- a workaround of GCC PR debug/47510. In the case of this complaint
- type_name_or_error will error on such types later.
-
- GDB skipped children of DW_TAG_typedef by the shortcut above and then
- it could not find the child DIEs referenced later, this is checked
- above. In correct DWARF DW_TAG_typedef should have no children. */
-
- if (pdi.tag == DW_TAG_typedef && pdi.has_children)
- complaint (_("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
- "- DIE at %s [in module %s]"),
- sect_offset_str (pdi.sect_off), objfile_name (objfile));
-
- /* If we're at the second level, and we're an enumerator, and
- our parent has no specification (meaning possibly lives in a
- namespace elsewhere), then we can add the partial symbol now
- instead of queueing it. */
- if (pdi.tag == DW_TAG_enumerator
- && parent_die != NULL
- && parent_die->die_parent == NULL
- && parent_die->tag == DW_TAG_enumeration_type
- && parent_die->has_specification == 0)
- {
- if (pdi.raw_name == NULL)
- complaint (_("malformed enumerator DIE ignored"));
- else if (building_psymtab)
- add_partial_symbol (&pdi, cu);
-
- info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
- continue;
- }
-
- struct partial_die_info *part_die
- = new (&cu->comp_unit_obstack) partial_die_info (pdi);
-
- /* We'll save this DIE so link it in. */
- part_die->die_parent = parent_die;
- part_die->die_sibling = NULL;
- part_die->die_child = NULL;
-
- if (last_die && last_die == parent_die)
- last_die->die_child = part_die;
- else if (last_die)
- last_die->die_sibling = part_die;
-
- last_die = part_die;
-
- if (first_die == NULL)
- first_die = part_die;
-
- /* Maybe add the DIE to the hash table. Not all DIEs that we
- find interesting need to be in the hash table, because we
- also have the parent/sibling/child chains; only those that we
- might refer to by offset later during partial symbol reading.
-
- For now this means things that might have be the target of a
- DW_AT_specification, DW_AT_abstract_origin, or
- DW_AT_extension. DW_AT_extension will refer only to
- namespaces; DW_AT_abstract_origin refers to functions (and
- many things under the function DIE, but we do not recurse
- into function DIEs during partial symbol reading) and
- possibly variables as well; DW_AT_specification refers to
- declarations. Declarations ought to have the DW_AT_declaration
- flag. It happens that GCC forgets to put it in sometimes, but
- only for functions, not for types.
-
- Adding more things than necessary to the hash table is harmless
- except for the performance cost. Adding too few will result in
- wasted time in find_partial_die, when we reread the compilation
- unit with load_all_dies set. */
-
- if (load_all
- || abbrev->tag == DW_TAG_constant
- || abbrev->tag == DW_TAG_subprogram
- || abbrev->tag == DW_TAG_variable
- || abbrev->tag == DW_TAG_namespace
- || part_die->is_declaration)
- {
- void **slot;
-
- slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
- to_underlying (part_die->sect_off),
- INSERT);
- *slot = part_die;
- }
-
- /* For some DIEs we want to follow their children (if any). For C
- we have no reason to follow the children of structures; for other
- languages we have to, so that we can get at method physnames
- to infer fully qualified class names, for DW_AT_specification,
- and for C++ template arguments. For C++, we also look one level
- inside functions to find template arguments (if the name of the
- function does not already contain the template arguments).
-
- For Ada and Fortran, we need to scan the children of subprograms
- and lexical blocks as well because these languages allow the
- definition of nested entities that could be interesting for the
- debugger, such as nested subprograms for instance. */
- if (last_die->has_children
- && (load_all
- || last_die->tag == DW_TAG_namespace
- || last_die->tag == DW_TAG_module
- || last_die->tag == DW_TAG_enumeration_type
- || (cu->per_cu->lang == language_cplus
- && last_die->tag == DW_TAG_subprogram
- && (last_die->raw_name == NULL
- || strchr (last_die->raw_name, '<') == NULL))
- || (cu->per_cu->lang != language_c
- && (last_die->tag == DW_TAG_class_type
- || last_die->tag == DW_TAG_interface_type
- || last_die->tag == DW_TAG_structure_type
- || last_die->tag == DW_TAG_union_type))
- || ((cu->per_cu->lang == language_ada
- || cu->per_cu->lang == language_fortran)
- && (last_die->tag == DW_TAG_subprogram
- || last_die->tag == DW_TAG_lexical_block))))
- {
- nesting_level++;
- parent_die = last_die;
- continue;
- }
+ bool nope = false;
+ if (!per_cu->scanned.compare_exchange_strong (nope, true))
+ return nullptr;
+ }
+ if (per_cu == m_per_cu)
+ return reader;
- /* Otherwise we skip to the next sibling, if any. */
- info_ptr = locate_pdi_sibling (reader, last_die, info_ptr);
+ cutu_reader *result = m_index_storage->get_reader (per_cu);
+ if (result == nullptr)
+ {
+ cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false,
+ m_index_storage->get_abbrev_cache ());
- /* Back to the top, do it again. */
+ prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die,
+ language_minimal);
+ std::unique_ptr<cutu_reader> copy
+ (new cutu_reader (std::move (new_reader)));
+ result = m_index_storage->preserve (std::move (copy));
}
-}
-partial_die_info::partial_die_info (sect_offset sect_off_,
- const struct abbrev_info *abbrev)
- : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
-{
-}
-
-/* See class definition. */
+ if (result->dummy_p || !result->comp_unit_die->has_children)
+ return nullptr;
-const char *
-partial_die_info::name (dwarf2_cu *cu)
-{
- if (!canonical_name && raw_name != nullptr)
- {
- struct objfile *objfile = cu->per_objfile->objfile;
- raw_name = dwarf2_canonicalize_name (raw_name, cu, objfile);
- canonical_name = 1;
- }
+ if (for_scanning)
+ check_bounds (result);
- return raw_name;
+ return result;
}
-/* Read a minimal amount of information into the minimal die structure.
- INFO_PTR should point just after the initial uleb128 of a DIE. */
-
const gdb_byte *
-partial_die_info::read (const struct die_reader_specs *reader,
- const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
-{
- struct dwarf2_cu *cu = reader->cu;
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- unsigned int i;
- int has_low_pc_attr = 0;
- int has_high_pc_attr = 0;
- int high_pc_relative = 0;
-
- for (i = 0; i < abbrev.num_attrs; ++i)
+cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+ cutu_reader *reader,
+ const gdb_byte *watermark_ptr,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev,
+ const char **name,
+ const char **linkage_name,
+ cooked_index_flag *flags,
+ sect_offset *sibling_offset,
+ const cooked_index_entry **parent_entry,
+ CORE_ADDR *maybe_defer,
+ bool for_specification)
+{
+ bool origin_is_dwz = false;
+ bool is_declaration = false;
+ sect_offset origin_offset {};
+
+ gdb::optional<CORE_ADDR> low_pc;
+ gdb::optional<CORE_ADDR> high_pc;
+ bool high_pc_relative = false;
+
+ for (int i = 0; i < abbrev->num_attrs; ++i)
{
attribute attr;
- info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
- /* String and address offsets that need to do the reprocessing have
- already been read at this point, so there is no need to wait until
- the loop terminates to do the reprocessing. */
+ info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
if (attr.requires_reprocessing_p ())
- read_attribute_reprocess (reader, &attr, tag);
+ read_attribute_reprocess (reader, &attr, abbrev->tag);
+
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
{
case DW_AT_name:
- switch (tag)
+ switch (abbrev->tag)
{
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
case DW_TAG_type_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
- case DW_TAG_enumeration_type:
- case DW_TAG_enumerator:
- /* These tags always have simple identifiers already; no need
- to canonicalize them. */
- canonical_name = 1;
- raw_name = attr.as_string ();
break;
+
default:
- canonical_name = 0;
- raw_name = attr.as_string ();
+ if (*name == nullptr)
+ *name = attr.as_string ();
break;
}
break;
+
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
/* Note that both forms of linkage name might appear. We
assume they will be the same, and we only store the last
one we see. */
- linkage_name = attr.as_string ();
- break;
- case DW_AT_low_pc:
- has_low_pc_attr = 1;
- lowpc = attr.as_address ();
- break;
- case DW_AT_high_pc:
- has_high_pc_attr = 1;
- highpc = attr.as_address ();
- if (cu->header.version >= 4 && attr.form_is_constant ())
- high_pc_relative = 1;
+ if (*linkage_name == nullptr)
+ *linkage_name = attr.as_string ();
break;
- case DW_AT_location:
- /* Support the .debug_loc offsets. */
- if (attr.form_is_block ())
- {
- d.locdesc = attr.as_block ();
- }
- else if (attr.form_is_section_offset ())
- {
- dwarf2_complex_location_expr_complaint ();
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
- "partial symbol information");
- }
- break;
- case DW_AT_external:
- is_external = attr.as_boolean ();
+
+ case DW_AT_main_subprogram:
+ if (attr.as_boolean ())
+ *flags |= IS_MAIN;
break;
+
case DW_AT_declaration:
is_declaration = attr.as_boolean ();
break;
- case DW_AT_type:
- has_type = 1;
+
+ case DW_AT_sibling:
+ if (sibling_offset != nullptr)
+ *sibling_offset = attr.get_ref_die_offset ();
break;
- case DW_AT_abstract_origin:
+
case DW_AT_specification:
+ case DW_AT_abstract_origin:
case DW_AT_extension:
- has_specification = 1;
- spec_offset = attr.get_ref_die_offset ();
- spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz);
+ origin_offset = attr.get_ref_die_offset ();
+ origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
break;
- case DW_AT_sibling:
- /* Ignore absolute siblings, they might point outside of
- the current compile unit. */
- if (attr.form == DW_FORM_ref_addr)
- complaint (_("ignoring absolute DW_AT_sibling"));
- else
- {
- const gdb_byte *buffer = reader->buffer;
- sect_offset off = attr.get_ref_die_offset ();
- const gdb_byte *sibling_ptr = buffer + to_underlying (off);
- if (sibling_ptr < info_ptr)
- complaint (_("DW_AT_sibling points backwards"));
- else if (sibling_ptr > reader->buffer_end)
- reader->die_section->overflow_complaint ();
- else
- sibling = sibling_ptr;
- }
- break;
- case DW_AT_byte_size:
- has_byte_size = 1;
+ case DW_AT_external:
+ if (attr.as_boolean ())
+ *flags &= ~IS_STATIC;
break;
- case DW_AT_const_value:
- has_const_value = 1;
+
+ case DW_AT_enum_class:
+ if (attr.as_boolean ())
+ *flags |= IS_ENUM_CLASS;
break;
- case DW_AT_calling_convention:
- /* DWARF doesn't provide a way to identify a program's source-level
- entry point. DW_AT_calling_convention attributes are only meant
- to describe functions' calling conventions.
-
- However, because it's a necessary piece of information in
- Fortran, and before DWARF 4 DW_CC_program was the only
- piece of debugging information whose definition refers to
- a 'main program' at all, several compilers marked Fortran
- main programs with DW_CC_program --- even when those
- functions use the standard calling conventions.
-
- Although DWARF now specifies a way to provide this
- information, we support this practice for backward
- compatibility. */
- if (attr.constant_value (0) == DW_CC_program
- && cu->per_cu->lang == language_fortran)
- main_subprogram = 1;
+
+ case DW_AT_low_pc:
+ low_pc = attr.as_address ();
break;
- case DW_AT_inline:
- {
- LONGEST value = attr.constant_value (-1);
- if (value == DW_INL_inlined
- || value == DW_INL_declared_inlined)
- may_be_inlined = 1;
- }
+
+ case DW_AT_high_pc:
+ high_pc = attr.as_address ();
+ if (reader->cu->header.version >= 4 && attr.form_is_constant ())
+ high_pc_relative = true;
break;
- case DW_AT_import:
- if (tag == DW_TAG_imported_unit)
+ case DW_AT_location:
+ if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
{
- d.sect_off = attr.get_ref_die_offset ();
- is_dwz = (attr.form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz);
+ struct dwarf_block *locdesc = attr.as_block ();
+ CORE_ADDR addr = decode_locdesc (locdesc, reader->cu);
+ if (addr != 0
+ || reader->cu->per_objfile->per_bfd->has_section_at_zero)
+ {
+ low_pc = addr;
+ /* For variables, we don't want to try decoding the
+ type just to find the size -- for gdb's purposes
+ we only need the address of a variable. */
+ high_pc = addr + 1;
+ high_pc_relative = false;
+ }
}
break;
- case DW_AT_main_subprogram:
- main_subprogram = attr.as_boolean ();
+ case DW_AT_ranges:
+ if (!scanning_per_cu->addresses_seen)
+ {
+ /* Offset in the .debug_ranges or .debug_rnglist section
+ (depending on DWARF version). */
+ ULONGEST ranges_offset = attr.as_unsigned ();
+
+ /* See dwarf2_cu::gnu_ranges_base's doc for why we might
+ want to add this value. */
+ ranges_offset += reader->cu->gnu_ranges_base;
+
+ CORE_ADDR lowpc, highpc;
+ dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu,
+ m_index_storage->get_addrmap (),
+ scanning_per_cu, abbrev->tag);
+ }
break;
+ }
+ }
- case DW_AT_ranges:
- {
- /* Offset in the .debug_ranges or .debug_rnglist section (depending
- on DWARF version). */
- ranges_offset = attr.as_unsigned ();
+ /* We don't want to examine declarations, but if we found a
+ declaration when handling DW_AT_specification or the like, then
+ that is ok. Similarly, we allow an external variable without a
+ location; those are resolved via minimal symbols. */
+ if (is_declaration && !for_specification
+ && (abbrev->tag != DW_TAG_variable
+ || (*flags & IS_STATIC) != 0))
+ {
+ *linkage_name = nullptr;
+ *name = nullptr;
+ }
+ else if ((*name == nullptr
+ || (*linkage_name == nullptr
+ && tag_can_have_linkage_name (abbrev->tag))
+ || (*parent_entry == nullptr && m_language != language_c))
+ && origin_offset != sect_offset (0))
+ {
+ cutu_reader *new_reader
+ = ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
+ origin_is_dwz, false);
+ if (new_reader != nullptr)
+ {
+ const gdb_byte *new_info_ptr = (new_reader->buffer
+ + to_underlying (origin_offset));
- /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
- this value. */
- if (tag != DW_TAG_compile_unit)
- ranges_offset += cu->gnu_ranges_base;
+ if (new_reader->cu == reader->cu
+ && new_info_ptr > watermark_ptr
+ && maybe_defer != nullptr
+ && *parent_entry == nullptr)
+ *maybe_defer = form_addr (origin_offset, origin_is_dwz);
+ else if (*parent_entry == nullptr)
+ {
+ CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
+ *parent_entry
+ = (cooked_index_entry *) addrmap_find (m_die_range_map,
+ lookup);
+ }
- has_range_info = 1;
- }
- break;
+ unsigned int bytes_read;
+ const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
+ new_info_ptr,
+ &bytes_read);
+ new_info_ptr += bytes_read;
+ scan_attributes (scanning_per_cu, new_reader, new_info_ptr, new_info_ptr,
+ new_abbrev, name, linkage_name, flags, nullptr,
+ parent_entry, maybe_defer, true);
+ }
+ }
- default:
- break;
+ if (!for_specification)
+ {
+ if (m_language == language_ada
+ && *linkage_name == nullptr)
+ *linkage_name = *name;
+
+ if (!scanning_per_cu->addresses_seen
+ && low_pc.has_value ()
+ && (reader->cu->per_objfile->per_bfd->has_section_at_zero
+ || *low_pc != 0)
+ && high_pc.has_value ())
+ {
+ if (high_pc_relative)
+ high_pc = *high_pc + *low_pc;
+
+ if (*high_pc > *low_pc)
+ {
+ struct objfile *objfile = reader->cu->per_objfile->objfile;
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ struct gdbarch *gdbarch = objfile->arch ();
+ CORE_ADDR lo
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, *low_pc + baseaddr)
+ - baseaddr);
+ CORE_ADDR hi
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, *high_pc + baseaddr)
+ - baseaddr);
+ addrmap_set_empty (m_index_storage->get_addrmap (), lo, hi - 1,
+ scanning_per_cu);
+ }
+ }
+
+ if (abbrev->tag == DW_TAG_module || abbrev->tag == DW_TAG_namespace)
+ *flags &= ~IS_STATIC;
+
+ if (abbrev->tag == DW_TAG_namespace && *name == nullptr)
+ *name = "(anonymous namespace)";
+
+ if (m_language == language_cplus
+ && (abbrev->tag == DW_TAG_class_type
+ || abbrev->tag == DW_TAG_interface_type
+ || abbrev->tag == DW_TAG_structure_type
+ || abbrev->tag == DW_TAG_union_type
+ || abbrev->tag == DW_TAG_enumeration_type
+ || abbrev->tag == DW_TAG_enumerator))
+ *flags &= ~IS_STATIC;
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_imported_unit (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev)
+{
+ sect_offset sect_off {};
+ bool is_dwz = false;
+
+ for (int i = 0; i < abbrev->num_attrs; ++i)
+ {
+ /* Note that we never need to reprocess attributes here. */
+ attribute attr;
+ info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+
+ if (attr.name == DW_AT_import)
+ {
+ sect_off = attr.get_ref_die_offset ();
+ is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ || reader->cu->per_cu->is_dwz);
}
}
- /* For Ada, if both the name and the linkage name appear, we prefer
- the latter. This lets "catch exception" work better, regardless
- of the order in which the name and linkage name were emitted.
- Really, though, this is just a workaround for the fact that gdb
- doesn't store both the name and the linkage name. */
- if (cu->per_cu->lang == language_ada && linkage_name != nullptr)
- raw_name = linkage_name;
+ /* Did not find DW_AT_import. */
+ if (sect_off == sect_offset (0))
+ return info_ptr;
+
+ dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
+ cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off,
+ is_dwz, true);
+ if (new_reader != nullptr)
+ {
+ index_dies (new_reader, new_reader->info_ptr, nullptr, false);
+
+ reader->cu->add_dependence (new_reader->cu->per_cu);
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::recurse (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully)
+{
+ info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+
+ if (parent_entry != nullptr)
+ {
+ CORE_ADDR start = form_addr (parent_entry->die_offset,
+ reader->cu->per_cu->is_dwz);
+ CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
+ reader->cu->per_cu->is_dwz);
+ addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry);
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_dies (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully)
+{
+ const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length ();
+
+ while (info_ptr < end_ptr)
+ {
+ sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
+ unsigned int bytes_read;
+ const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+ &bytes_read);
+ info_ptr += bytes_read;
+ if (abbrev == nullptr)
+ break;
+
+ if (abbrev->tag == DW_TAG_imported_unit)
+ {
+ info_ptr = index_imported_unit (reader, info_ptr, abbrev);
+ continue;
+ }
+
+ if (!abbrev->interesting)
+ {
+ info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
+ if (fully && abbrev->has_children)
+ info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+ continue;
+ }
+
+ const char *name = nullptr;
+ const char *linkage_name = nullptr;
+ CORE_ADDR defer = 0;
+ cooked_index_flag flags = IS_STATIC;
+ sect_offset sibling {};
+ const cooked_index_entry *this_parent_entry = parent_entry;
+ info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr,
+ info_ptr, abbrev, &name, &linkage_name,
+ &flags, &sibling, &this_parent_entry,
+ &defer, false);
+
+ if (abbrev->tag == DW_TAG_namespace
+ && m_language == language_cplus
+ && strcmp (name, "::") == 0)
+ {
+ /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they
+ generated bogus DW_TAG_namespace DIEs with a name of "::"
+ for the global namespace. Work around this problem
+ here. */
+ name = nullptr;
+ }
+
+ const cooked_index_entry *this_entry = nullptr;
+ if (name != nullptr)
+ {
+ if (defer != 0)
+ m_deferred_entries.push_back ({
+ this_die, name, defer, abbrev->tag, flags
+ });
+ else
+ this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
+ name, this_parent_entry,
+ m_per_cu);
+ }
- if (high_pc_relative)
- highpc += lowpc;
+ if (linkage_name != nullptr)
+ {
+ /* We only want this to be "main" if it has a linkage name
+ but not an ordinary name. */
+ if (name != nullptr)
+ flags = flags & ~IS_MAIN;
+ m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE,
+ linkage_name, nullptr, m_per_cu);
+ }
+
+ if (abbrev->has_children)
+ {
+ switch (abbrev->tag)
+ {
+ case DW_TAG_class_type:
+ case DW_TAG_interface_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if (m_language != language_c && this_entry != nullptr)
+ {
+ info_ptr = recurse (reader, info_ptr, this_entry, fully);
+ continue;
+ }
+ break;
+
+ case DW_TAG_enumeration_type:
+ /* We need to recurse even for an anonymous enumeration.
+ Which scope we record as the parent scope depends on
+ whether we're reading an "enum class". If so, we use
+ the enum itself as the parent, yielding names like
+ "enum_class::enumerator"; otherwise we inject the
+ names into our own parent scope. */
+ info_ptr = recurse (reader, info_ptr,
+ ((flags & IS_ENUM_CLASS) == 0)
+ ? parent_entry
+ : this_entry,
+ fully);
+ continue;
+
+ case DW_TAG_module:
+ if (this_entry == nullptr)
+ break;
+ /* FALLTHROUGH */
+ case DW_TAG_namespace:
+ /* We don't check THIS_ENTRY for a namespace, to handle
+ the ancient G++ workaround pointed out above. */
+ info_ptr = recurse (reader, info_ptr, this_entry, fully);
+ continue;
- if (has_low_pc_attr && has_high_pc_attr)
- {
- /* When using the GNU linker, .gnu.linkonce. sections are used to
- eliminate duplicate copies of functions and vtables and such.
- The linker will arbitrarily choose one and discard the others.
- The AT_*_pc values for such functions refer to local labels in
- these sections. If the section from that file was discarded, the
- labels are not in the output, so the relocs get a value of 0.
- If this is a discarded function, mark the pc bounds as invalid,
- so that GDB will ignore it. */
- if (lowpc == 0 && !per_objfile->per_bfd->has_section_at_zero)
- {
- struct objfile *objfile = per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
+ case DW_TAG_subprogram:
+ if ((m_language == language_fortran
+ || m_language == language_ada)
+ && this_entry != nullptr)
+ {
+ info_ptr = recurse (reader, info_ptr, this_entry, true);
+ continue;
+ }
+ break;
+ }
- complaint (_("DW_AT_low_pc %s is zero "
- "for DIE at %s [in module %s]"),
- paddress (gdbarch, lowpc),
- sect_offset_str (sect_off),
- objfile_name (objfile));
- }
- /* dwarf2_get_pc_bounds has also the strict low < high requirement. */
- else if (lowpc >= highpc)
- {
- struct objfile *objfile = per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
+ if (sibling != sect_offset (0))
+ {
+ const gdb_byte *sibling_ptr
+ = reader->buffer + to_underlying (sibling);
- complaint (_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
- "for DIE at %s [in module %s]"),
- paddress (gdbarch, lowpc),
- paddress (gdbarch, highpc),
- sect_offset_str (sect_off),
- objfile_name (objfile));
+ if (sibling_ptr < info_ptr)
+ complaint (_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ reader->die_section->overflow_complaint ();
+ else
+ info_ptr = sibling_ptr;
+ }
+ else
+ info_ptr = skip_children (reader, info_ptr);
}
- else
- has_pc_info = 1;
}
return info_ptr;
}
-/* Find a cached partial DIE at OFFSET in CU. */
-
-struct partial_die_info *
-dwarf2_cu::find_partial_die (sect_offset sect_off)
+void
+cooked_indexer::make_index (cutu_reader *reader)
{
- struct partial_die_info *lookup_die = NULL;
- struct partial_die_info part_die (sect_off);
-
- lookup_die = ((struct partial_die_info *)
- htab_find_with_hash (partial_dies, &part_die,
- to_underlying (sect_off)));
+ check_bounds (reader);
+ find_file_and_directory (reader->comp_unit_die, reader->cu);
+ if (!reader->comp_unit_die->has_children)
+ return;
+ index_dies (reader, reader->info_ptr, nullptr, false);
- return lookup_die;
+ for (const auto &entry : m_deferred_entries)
+ {
+ CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
+ cooked_index_entry *parent
+ = (cooked_index_entry *) addrmap_find (m_die_range_map, key);
+ m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
+ entry.name, parent, m_per_cu);
+ }
}
-/* Find a partial DIE at OFFSET, which may or may not be in CU,
- except in the case of .debug_types DIEs which do not reference
- outside their CU (they do however referencing other types via
- DW_FORM_ref_sig8). */
+/* An implementation of quick_symbol_functions for the cooked DWARF
+ index. */
-static const struct cu_partial_die_info
-find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
+struct cooked_index_functions : public dwarf2_base_index_functions
{
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- struct objfile *objfile = per_objfile->objfile;
- struct partial_die_info *pd = NULL;
+ struct compunit_symtab *find_pc_sect_compunit_symtab
+ (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+ CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
- if (offset_in_dwz == cu->per_cu->is_dwz
- && cu->header.offset_in_cu_p (sect_off))
- {
- pd = cu->find_partial_die (sect_off);
- if (pd != NULL)
- return { cu, pd };
- /* We missed recording what we needed.
- Load all dies and try again. */
- }
- else
- {
- /* TUs don't reference other CUs/TUs (except via type signatures). */
- if (cu->per_cu->is_debug_types)
- {
- error (_("Dwarf Error: Type Unit at offset %s contains"
- " external reference to offset %s [in module %s].\n"),
- sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
- bfd_get_filename (objfile->obfd));
- }
- dwarf2_per_cu_data *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile);
+ struct compunit_symtab *find_compunit_symtab_by_address
+ (struct objfile *objfile, CORE_ADDR address) override;
- cu = per_objfile->get_cu (per_cu);
- if (cu == NULL || cu->partial_dies == NULL)
- load_partial_comp_unit (per_cu, per_objfile, nullptr);
+ void dump (struct objfile *objfile) override
+ {
+ gdb_printf ("Cooked index in use\n");
+ }
- cu = per_objfile->get_cu (per_cu);
+ void expand_matching_symbols
+ (struct objfile *,
+ const lookup_name_info &lookup_name,
+ domain_enum domain,
+ int global,
+ symbol_compare_ftype *ordered_compare) override;
- cu->last_used = 0;
- pd = cu->find_partial_die (sect_off);
- }
+ 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;
- /* If we didn't find it, and not all dies have been loaded,
- load them all and try again. */
+ bool can_lazily_read_symbols () override
+ {
+ return true;
+ }
- if (pd == NULL && cu->load_all_dies == 0)
- {
- cu->load_all_dies = 1;
+ void read_partial_symbols (struct objfile *objfile) override
+ {
+ if (dwarf2_has_info (objfile, nullptr))
+ dwarf2_build_psymtabs (objfile, true);
+ }
+};
- /* This is nasty. When we reread the DIEs, somewhere up the call chain
- THIS_CU->cu may already be in use. So we can't just free it and
- replace its DIEs with the ones we read in. Instead, we leave those
- DIEs alone (which can still be in use, e.g. in scan_partial_symbols),
- and clobber THIS_CU->cu->partial_dies with the hash table for the new
- set. */
- load_partial_comp_unit (cu->per_cu, per_objfile, cu);
+struct compunit_symtab *
+cooked_index_functions::find_pc_sect_compunit_symtab
+ (struct objfile *objfile,
+ struct bound_minimal_symbol msymbol,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->index_table == nullptr)
+ return nullptr;
- pd = cu->find_partial_die (sect_off);
- }
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ cooked_index_vector *table
+ = (static_cast<cooked_index_vector *>
+ (per_objfile->per_bfd->index_table.get ()));
+ dwarf2_per_cu_data *per_cu = table->lookup (pc - baseaddr);
+ if (per_cu == nullptr)
+ return nullptr;
- if (pd == NULL)
- error (_("Dwarf Error: Cannot find DIE at %s [from module %s]\n"),
- sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
- return { cu, pd };
-}
+ if (warn_if_readin && per_objfile->symtab_set_p (per_cu))
+ warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
+ paddress (objfile->arch (), pc));
-/* See if we can figure out if the class lives in a namespace. We do
- this by looking for a member function; its demangled name will
- contain namespace info, if there is any. */
+ compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab
+ (dw2_instantiate_symtab (per_cu, per_objfile,
+ false),
+ pc));
+ gdb_assert (result != nullptr);
+ return result;
+}
-static void
-guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
- struct dwarf2_cu *cu)
+struct compunit_symtab *
+cooked_index_functions::find_compunit_symtab_by_address
+ (struct objfile *objfile, CORE_ADDR address)
{
- /* NOTE: carlton/2003-10-07: Getting the info this way changes
- what template types look like, because the demangler
- frequently doesn't give the same name as the debug info. We
- could fix this by only using the demangled name to get the
- prefix (but see comment in read_structure_type). */
+ if (objfile->sect_index_data == -1)
+ return nullptr;
- struct partial_die_info *real_pdi;
- struct partial_die_info *child_pdi;
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->index_table == nullptr)
+ return nullptr;
- /* If this DIE (this DIE's specification, if any) has a parent, then
- we should not do this. We'll prepend the parent's fully qualified
- name when we create the partial symbol. */
+ CORE_ADDR baseaddr = objfile->data_section_offset ();
+ cooked_index_vector *table
+ = (static_cast<cooked_index_vector *>
+ (per_objfile->per_bfd->index_table.get ()));
+ dwarf2_per_cu_data *per_cu = table->lookup (address - baseaddr);
+ if (per_cu == nullptr)
+ return nullptr;
- real_pdi = struct_pdi;
- while (real_pdi->has_specification)
- {
- auto res = find_partial_die (real_pdi->spec_offset,
- real_pdi->spec_is_dwz, cu);
- real_pdi = res.pdi;
- cu = res.cu;
- }
+ return dw2_instantiate_symtab (per_cu, per_objfile, false);
+}
- if (real_pdi->die_parent != NULL)
+void
+cooked_index_functions::expand_matching_symbols
+ (struct objfile *objfile,
+ const lookup_name_info &lookup_name,
+ domain_enum domain,
+ int global,
+ symbol_compare_ftype *ordered_compare)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->index_table == nullptr)
return;
+ const block_search_flags search_flags = (global
+ ? SEARCH_GLOBAL_BLOCK
+ : SEARCH_STATIC_BLOCK);
+ const language_defn *lang = language_def (language_ada);
+ symbol_name_matcher_ftype *name_match
+ = lang->get_symbol_name_matcher (lookup_name);
+
+ cooked_index_vector *table
+ = (static_cast<cooked_index_vector *>
+ (per_objfile->per_bfd->index_table.get ()));
+ for (const cooked_index_entry *entry : table->all_entries ())
+ {
+ if (entry->parent_entry != nullptr)
+ continue;
- for (child_pdi = struct_pdi->die_child;
- child_pdi != NULL;
- child_pdi = child_pdi->die_sibling)
- {
- if (child_pdi->tag == DW_TAG_subprogram
- && child_pdi->linkage_name != NULL)
- {
- gdb::unique_xmalloc_ptr<char> actual_class_name
- (cu->language_defn->class_name_from_physname
- (child_pdi->linkage_name));
- if (actual_class_name != NULL)
- {
- struct objfile *objfile = cu->per_objfile->objfile;
- struct_pdi->raw_name = objfile->intern (actual_class_name.get ());
- struct_pdi->canonical_name = 1;
- }
- break;
- }
- }
-}
-
-/* Return true if a DIE with TAG may have the DW_AT_const_value
- attribute. */
+ if (!entry->matches (search_flags)
+ || !entry->matches (domain))
+ continue;
-static bool
-can_have_DW_AT_const_value_p (enum dwarf_tag tag)
-{
- switch (tag)
- {
- case DW_TAG_constant:
- case DW_TAG_enumerator:
- case DW_TAG_formal_parameter:
- case DW_TAG_template_value_param:
- case DW_TAG_variable:
- return true;
+ if (name_match (entry->canonical, lookup_name, nullptr))
+ dw2_instantiate_symtab (entry->per_cu, per_objfile, false);
}
-
- return false;
}
-void
-partial_die_info::fixup (struct dwarf2_cu *cu)
+bool
+cooked_index_functions::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)
{
- /* Once we've fixed up a die, there's no point in doing so again.
- This also avoids a memory leak if we were to call
- guess_partial_die_structure_name multiple times. */
- if (fixup_called)
- return;
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->index_table == nullptr)
+ return true;
- /* If we found a reference attribute and the DIE has no name, try
- to find a name in the referred to DIE. */
+ dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
- if (raw_name == NULL && has_specification)
+ /* This invariant is documented in quick-functions.h. */
+ gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+ if (lookup_name == nullptr)
{
- struct partial_die_info *spec_die;
-
- auto res = find_partial_die (spec_offset, spec_is_dwz, cu);
- spec_die = res.pdi;
- cu = res.cu;
-
- spec_die->fixup (cu);
-
- if (spec_die->raw_name)
+ for (dwarf2_per_cu_data *per_cu
+ : all_comp_units_range (per_objfile->per_bfd))
{
- raw_name = spec_die->raw_name;
- canonical_name = spec_die->canonical_name;
+ QUIT;
- /* Copy DW_AT_external attribute if it is set. */
- if (spec_die->is_external)
- is_external = spec_die->is_external;
+ if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+ file_matcher,
+ expansion_notify))
+ return false;
}
+ return true;
}
- if (!has_const_value && has_specification
- && can_have_DW_AT_const_value_p (tag))
- {
- struct partial_die_info *spec_die;
+ lookup_name_info lookup_name_without_params
+ = lookup_name->make_ignore_params ();
+ bool completing = lookup_name->completion_mode ();
- auto res = find_partial_die (spec_offset, spec_is_dwz, cu);
- spec_die = res.pdi;
- cu = res.cu;
+ /* Unique styles of language splitting. */
+ static const enum language unique_styles[] =
+ {
+ /* No splitting is also a style. */
+ language_c,
+ /* This includes Rust. */
+ language_cplus,
+ /* This includes Go. */
+ language_d,
+ language_ada
+ };
- spec_die->fixup (cu);
+ cooked_index_vector *table
+ = (static_cast<cooked_index_vector *>
+ (per_objfile->per_bfd->index_table.get ()));
+ for (enum language lang : unique_styles)
+ {
+ std::vector<gdb::string_view> name_vec
+ = lookup_name_without_params.split_name (lang);
- if (spec_die->has_const_value)
+ for (const cooked_index_entry *entry : table->find (name_vec.back (),
+ completing))
{
- /* Copy DW_AT_const_value attribute if it is set. */
- has_const_value = spec_die->has_const_value;
- }
- }
+ /* No need to consider symbols from expanded CUs. */
+ if (per_objfile->symtab_set_p (entry->per_cu))
+ continue;
- /* Set default names for some unnamed DIEs. */
+ /* If file-matching was done, we don't need to consider
+ symbols from unmarked CUs. */
+ if (file_matcher != nullptr && !entry->per_cu->mark)
+ continue;
- if (raw_name == NULL && tag == DW_TAG_namespace)
- {
- raw_name = CP_ANONYMOUS_NAMESPACE_STR;
- canonical_name = 1;
- }
+ /* See if the symbol matches the type filter. */
+ if (!entry->matches (search_flags)
+ || !entry->matches (domain)
+ || !entry->matches (kind))
+ continue;
- /* If there is no parent die to provide a namespace, and there are
- children, see if we can determine the namespace from their linkage
- name. */
- if (cu->per_cu->lang == language_cplus
- && !cu->per_objfile->per_bfd->types.empty ()
- && die_parent == NULL
- && has_children
- && (tag == DW_TAG_class_type
- || tag == DW_TAG_structure_type
- || tag == DW_TAG_union_type))
- guess_partial_die_structure_name (this, cu);
-
- /* GCC might emit a nameless struct or union that has a linkage
- name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
- if (raw_name == NULL
- && (tag == DW_TAG_class_type
- || tag == DW_TAG_interface_type
- || tag == DW_TAG_structure_type
- || tag == DW_TAG_union_type)
- && linkage_name != NULL)
- {
- gdb::unique_xmalloc_ptr<char> demangled
- (gdb_demangle (linkage_name, DMGL_TYPES));
- if (demangled != nullptr)
- {
- const char *base;
-
- /* Strip any leading namespaces/classes, keep only the base name.
- DW_AT_name for named DIEs does not contain the prefixes. */
- base = strrchr (demangled.get (), ':');
- if (base && base > demangled.get () && base[-1] == ':')
- base++;
+ /* We've found the base name of the symbol; now walk its
+ parentage chain, ensuring that each component
+ matches. */
+ bool found = true;
+
+ const cooked_index_entry *parent = entry->parent_entry;
+ for (int i = name_vec.size () - 1; i > 0; --i)
+ {
+ /* If we ran out of entries, or if this segment doesn't
+ match, this did not match. */
+ if (parent == nullptr
+ || strncmp (parent->name, name_vec[i - 1].data (),
+ name_vec[i - 1].length ()) != 0)
+ {
+ found = false;
+ break;
+ }
+
+ parent = parent->parent_entry;
+ }
+
+ if (!found)
+ continue;
+
+ /* Might have been looking for "a::b" and found
+ "x::a::b". */
+ if (symbol_matcher == nullptr)
+ {
+ symbol_name_match_type match_type
+ = lookup_name_without_params.match_type ();
+ if ((match_type == symbol_name_match_type::FULL
+ || (lang != language_ada
+ && match_type == symbol_name_match_type::EXPRESSION))
+ && parent != nullptr)
+ continue;
+ }
else
- base = demangled.get ();
+ {
+ auto_obstack temp_storage;
+ const char *full_name = entry->full_name (&temp_storage);
+ if (!symbol_matcher (full_name))
+ continue;
+ }
- struct objfile *objfile = cu->per_objfile->objfile;
- raw_name = objfile->intern (base);
- canonical_name = 1;
+ if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
+ file_matcher,
+ expansion_notify))
+ return false;
}
}
- fixup_called = 1;
+ return true;
+}
+
+/* Return a new cooked_index_functions object. */
+
+static quick_symbol_functions_up
+make_cooked_index_funcs ()
+{
+ return quick_symbol_functions_up (new cooked_index_functions);
+}
+
+quick_symbol_functions_up
+cooked_index_vector::make_quick_functions () const
+{
+ return make_cooked_index_funcs ();
}
+\f
+
/* Read the .debug_loclists or .debug_rnglists header (they are the same format)
contents from the given SECTION in the HEADER.
break;
}
default:
- gdb_assert_not_reached (_("Unexpected DWARF form."));
+ gdb_assert_not_reached ("Unexpected DWARF form.");
}
}
/* See read.h. */
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
+ unsigned int offset_size)
+{
+ bfd *abfd = objfile->obfd;
+ ULONGEST str_offset = read_offset (abfd, buf, offset_size);
+
+ return per_bfd->line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
+}
+
+/* See read.h. */
+
const char *
dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
const struct comp_unit_head *cu_header,
static const char *
compute_include_file_name (const struct line_header *lh, const file_entry &fe,
const file_and_directory &cu_info,
- gdb::unique_xmalloc_ptr<char> *name_holder)
+ std::string &name_holder)
{
const char *include_name = fe.name;
const char *include_name_to_compare = include_name;
const char *dir_name = fe.include_dir (lh);
- gdb::unique_xmalloc_ptr<char> hold_compare;
+ std::string hold_compare;
if (!IS_ABSOLUTE_PATH (include_name)
- && (dir_name != NULL || cu_info.comp_dir != NULL))
+ && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
{
/* Avoid creating a duplicate name for CU_INFO.
We do this by comparing INCLUDE_NAME and CU_INFO.
if (dir_name != NULL)
{
- name_holder->reset (concat (dir_name, SLASH_STRING,
- include_name, (char *) NULL));
- include_name = name_holder->get ();
+ name_holder = path_join (dir_name, include_name);
+ include_name = name_holder.c_str ();
include_name_to_compare = include_name;
}
- if (!IS_ABSOLUTE_PATH (include_name) && cu_info.comp_dir != nullptr)
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && cu_info.get_comp_dir () != nullptr)
{
- hold_compare.reset (concat (cu_info.comp_dir, SLASH_STRING,
- include_name, (char *) NULL));
- include_name_to_compare = hold_compare.get ();
+ hold_compare = path_join (cu_info.get_comp_dir (), include_name);
+ include_name_to_compare = hold_compare.c_str ();
}
}
- gdb::unique_xmalloc_ptr<char> copied_name;
- const char *cu_filename = cu_info.name;
- if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.comp_dir != nullptr)
+ std::string copied_name;
+ const char *cu_filename = cu_info.get_name ();
+ if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
{
- copied_name.reset (concat (cu_info.comp_dir, SLASH_STRING,
- cu_filename, (char *) NULL));
- cu_filename = copied_name.get ();
+ copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
+ cu_filename = copied_name.c_str ();
}
if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
public:
/* Initialize a machine state for the start of a line number
program. */
- lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh,
- bool record_lines_p);
+ lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
file_entry *current_file ()
{
/* Handle DW_LNS_negate_stmt. */
void handle_negate_stmt ()
{
- m_is_stmt = !m_is_stmt;
+ m_flags ^= LEF_IS_STMT;
}
/* Handle DW_LNS_const_add_pc. */
{
record_line (false);
m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
}
/* Handle DW_LNE_end_sequence. */
m_currently_recording_lines = true;
}
+ /* Handle DW_LNS_set_prologue_end. */
+ void handle_set_prologue_end ()
+ {
+ m_flags |= LEF_PROLOGUE_END;
+ }
+
private:
/* Advance the line by LINE_DELTA. */
void advance_line (int line_delta)
gdbarch *m_gdbarch;
- /* True if we're recording lines.
- Otherwise we're building partial symtabs and are just interested in
- finding include files mentioned by the line number program. */
- bool m_record_lines_p;
-
/* The line number header. */
line_header *m_line_header;
/* These are initialized in the constructor. */
CORE_ADDR m_address;
- bool m_is_stmt;
+ linetable_entry_flags m_flags;
unsigned int m_discriminator;
/* Additional bits of state we need to track. */
CORE_ADDR m_last_address;
/* Set to true when a previous line at the same address (using
- m_last_address) had m_is_stmt true. This is reset to false when a
- line entry at a new address (m_address different to m_last_address) is
- processed. */
+ m_last_address) had LEF_IS_STMT set in m_flags. This is reset to false
+ when a line entry at a new address (m_address different to
+ m_last_address) is processed. */
bool m_stmt_at_address = false;
/* When true, record the lines we decode. */
advance_line (line_delta);
record_line (false);
m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
}
void
const file_entry *fe = current_file ();
if (fe == NULL)
dwarf2_debug_line_missing_file_complaint ();
- else if (m_record_lines_p)
+ else
{
const char *dir = fe->include_dir (m_line_header);
static void
dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, CORE_ADDR address, bool is_stmt,
+ unsigned int line, CORE_ADDR address,
+ linetable_entry_flags flags,
struct dwarf2_cu *cu)
{
CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Recording line %u, file %s, address %s\n",
- line, lbasename (subfile->name),
- paddress (gdbarch, address));
+ gdb_printf (gdb_stdlog,
+ "Recording line %u, file %s, address %s\n",
+ line, lbasename (subfile->name.c_str ()),
+ paddress (gdbarch, address));
}
if (cu != nullptr)
- cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
+ cu->get_builder ()->record_line (subfile, line, addr, flags);
}
/* Subroutine of dwarf_decode_lines_1 to simplify it.
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Finishing current line, file %s, address %s\n",
- lbasename (subfile->name),
- paddress (gdbarch, address));
+ gdb_printf (gdb_stdlog,
+ "Finishing current line, file %s, address %s\n",
+ lbasename (subfile->name.c_str ()),
+ paddress (gdbarch, address));
}
- dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu);
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
}
void
{
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Processing actual line %u: file %u,"
- " address %s, is_stmt %u, discrim %u%s\n",
- m_line, m_file,
- paddress (m_gdbarch, m_address),
- m_is_stmt, m_discriminator,
- (end_sequence ? "\t(end sequence)" : ""));
+ gdb_printf (gdb_stdlog,
+ "Processing actual line %u: file %u,"
+ " address %s, is_stmt %u, prologue_end %u, discrim %u%s\n",
+ m_line, m_file,
+ paddress (m_gdbarch, m_address),
+ (m_flags & LEF_IS_STMT) != 0,
+ (m_flags & LEF_PROLOGUE_END) != 0,
+ m_discriminator,
+ (end_sequence ? "\t(end sequence)" : ""));
}
file_entry *fe = current_file ();
previous version of the code. */
else if (m_op_index == 0 || end_sequence)
{
- fe->included_p = true;
- if (m_record_lines_p)
- {
- /* When we switch files we insert an end maker in the first file,
- switch to the second file and add a new line entry. The
- problem is that the end marker inserted in the first file will
- discard any previous line entries at the same address. If the
- line entries in the first file are marked as is-stmt, while
- the new line in the second file is non-stmt, then this means
- the end marker will discard is-stmt lines so we can have a
- non-stmt line. This means that there are less addresses at
- which the user can insert a breakpoint.
-
- To improve this we track the last address in m_last_address,
- and whether we have seen an is-stmt at this address. Then
- when switching files, if we have seen a stmt at the current
- address, and we are switching to create a non-stmt line, then
- discard the new line. */
- bool file_changed
- = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
- bool ignore_this_line
- = ((file_changed && !end_sequence && m_last_address == m_address
- && !m_is_stmt && m_stmt_at_address)
- || (!end_sequence && m_line == 0));
-
- if ((file_changed && !ignore_this_line) || end_sequence)
+ /* When we switch files we insert an end maker in the first file,
+ switch to the second file and add a new line entry. The
+ problem is that the end marker inserted in the first file will
+ discard any previous line entries at the same address. If the
+ line entries in the first file are marked as is-stmt, while
+ the new line in the second file is non-stmt, then this means
+ the end marker will discard is-stmt lines so we can have a
+ non-stmt line. This means that there are less addresses at
+ which the user can insert a breakpoint.
+
+ To improve this we track the last address in m_last_address,
+ and whether we have seen an is-stmt at this address. Then
+ when switching files, if we have seen a stmt at the current
+ address, and we are switching to create a non-stmt line, then
+ discard the new line. */
+ bool file_changed
+ = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+ bool ignore_this_line
+ = ((file_changed && !end_sequence && m_last_address == m_address
+ && ((m_flags & LEF_IS_STMT) == 0)
+ && m_stmt_at_address)
+ || (!end_sequence && m_line == 0));
+
+ if ((file_changed && !ignore_this_line) || end_sequence)
+ {
+ dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
+ m_currently_recording_lines ? m_cu : nullptr);
+ }
+
+ if (!end_sequence && !ignore_this_line)
+ {
+ linetable_entry_flags lte_flags = m_flags;
+ if (producer_is_codewarrior (m_cu))
+ lte_flags |= LEF_IS_STMT;
+
+ if (dwarf_record_line_p (m_cu, m_line, m_last_line,
+ m_line_has_non_zero_discriminator,
+ m_last_subfile))
{
- dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
- m_currently_recording_lines ? m_cu : nullptr);
- }
-
- if (!end_sequence && !ignore_this_line)
- {
- bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
-
- if (dwarf_record_line_p (m_cu, m_line, m_last_line,
- m_line_has_non_zero_discriminator,
- m_last_subfile))
- {
- buildsym_compunit *builder = m_cu->get_builder ();
- dwarf_record_line_1 (m_gdbarch,
- builder->get_current_subfile (),
- m_line, m_address, is_stmt,
- m_currently_recording_lines ? m_cu : nullptr);
- }
- m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
- m_last_line = m_line;
+ buildsym_compunit *builder = m_cu->get_builder ();
+ dwarf_record_line_1 (m_gdbarch,
+ builder->get_current_subfile (),
+ m_line, m_address, lte_flags,
+ m_currently_recording_lines ? m_cu : nullptr);
}
+ m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
+ m_last_line = m_line;
}
}
- /* Track whether we have seen any m_is_stmt true at m_address in case we
+ /* Track whether we have seen any IS_STMT true at m_address in case we
have multiple line table entries all at m_address. */
if (m_last_address != m_address)
{
m_stmt_at_address = false;
m_last_address = m_address;
}
- m_stmt_at_address |= m_is_stmt;
+ m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
}
lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
- line_header *lh, bool record_lines_p)
+ line_header *lh)
{
m_cu = cu;
m_gdbarch = arch;
- m_record_lines_p = record_lines_p;
m_line_header = lh;
m_currently_recording_lines = true;
and also record it in case it needs it. This is currently used by MIPS
code, cf. `mips_adjust_dwarf2_line'. */
m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
- m_is_stmt = lh->default_is_stmt;
+ m_flags = 0;
+ if (lh->default_is_stmt)
+ m_flags |= LEF_IS_STMT;
m_discriminator = 0;
m_last_address = m_address;
}
/* Subroutine of dwarf_decode_lines to simplify it.
- Process the line number information in LH.
- If DECODE_FOR_PST_P is non-zero, all we do is process the line number
- program in order to set included_p for every referenced header. */
+ Process the line number information in LH. */
static void
dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
- const int decode_for_pst_p, CORE_ADDR lowpc)
+ CORE_ADDR lowpc)
{
const gdb_byte *line_ptr, *extended_end;
const gdb_byte *line_end;
struct objfile *objfile = cu->per_objfile->objfile;
bfd *abfd = objfile->obfd;
struct gdbarch *gdbarch = objfile->arch ();
- /* True if we're recording line info (as opposed to building partial
- symtabs and just interested in finding include files mentioned by
- the line number program). */
- bool record_lines_p = !decode_for_pst_p;
baseaddr = objfile->text_section_offset ();
{
/* The DWARF line number program state machine. Reset the state
machine at the start of each sequence. */
- lnp_state_machine state_machine (cu, gdbarch, lh, record_lines_p);
+ lnp_state_machine state_machine (cu, gdbarch, lh);
bool end_sequence = false;
- if (record_lines_p)
- {
- /* Start a subfile for the current file of the state
- machine. */
- const file_entry *fe = state_machine.current_file ();
+ /* Start a subfile for the current file of the state
+ machine. */
+ const file_entry *fe = state_machine.current_file ();
- if (fe != NULL)
- dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
- }
+ if (fe != NULL)
+ dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
/* Decode the table. */
while (line_ptr < line_end && !end_sequence)
state_machine.handle_fixed_advance_pc (addr_adj);
}
break;
+ case DW_LNS_set_prologue_end:
+ state_machine.handle_set_prologue_end ();
+ break;
default:
{
/* Unknown standard opcode, ignore it. */
structure and CU. The actual information extracted and the type
of structures created from the LNP depends on the value of PST.
- 1. If PST is NULL, then this procedure uses the data from the program
- to create all necessary symbol tables, and their linetables.
-
- 2. If PST is not NULL, this procedure reads the program to determine
- the list of files included by the unit represented by PST, and
- builds all the associated partial symbol tables.
-
FND holds the CU file name and directory, if known.
It is used for relative paths in the line table.
table is read in. */
static void
-dwarf_decode_lines (struct line_header *lh, const file_and_directory &fnd,
- struct dwarf2_cu *cu, dwarf2_psymtab *pst,
+dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
CORE_ADDR lowpc, int decode_mapping)
{
- struct objfile *objfile = cu->per_objfile->objfile;
- const int decode_for_pst_p = (pst != NULL);
-
if (decode_mapping)
- dwarf_decode_lines_1 (lh, cu, decode_for_pst_p, lowpc);
+ dwarf_decode_lines_1 (lh, cu, lowpc);
- if (decode_for_pst_p)
- {
- /* Now that we're done scanning the Line Header Program, we can
- create the psymtab of each included file. */
- for (auto &file_entry : lh->file_names ())
- if (file_entry.included_p)
- {
- gdb::unique_xmalloc_ptr<char> name_holder;
- const char *include_name =
- compute_include_file_name (lh, file_entry, fnd, &name_holder);
- if (include_name != NULL)
- dwarf2_create_include_psymtab
- (cu->per_objfile->per_bfd, include_name, pst,
- cu->per_objfile->per_bfd->partial_symtabs.get (),
- objfile->per_bfd);
- }
- }
- else
- {
- /* Make sure a symtab is created for every file, even files
- which contain only variables (i.e. no code with associated
- line numbers). */
- buildsym_compunit *builder = cu->get_builder ();
- struct compunit_symtab *cust = builder->get_compunit_symtab ();
+ /* Make sure a symtab is created for every file, even files
+ which contain only variables (i.e. no code with associated
+ line numbers). */
+ buildsym_compunit *builder = cu->get_builder ();
+ struct compunit_symtab *cust = builder->get_compunit_symtab ();
- for (auto &fe : lh->file_names ())
+ for (auto &fe : lh->file_names ())
+ {
+ dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
+ if (builder->get_current_subfile ()->symtab == NULL)
{
- dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
- if (builder->get_current_subfile ()->symtab == NULL)
- {
- builder->get_current_subfile ()->symtab
- = allocate_symtab (cust,
- builder->get_current_subfile ()->name);
- }
- fe.symtab = builder->get_current_subfile ()->symtab;
+ builder->get_current_subfile ()->symtab
+ = allocate_symtab (cust,
+ builder->get_current_subfile ()->name.c_str ());
}
+ fe.symtab = builder->get_current_subfile ()->symtab;
}
}
dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
const char *dirname)
{
- gdb::unique_xmalloc_ptr<char> copy;
+ std::string copy;
/* In order not to lose the line information directory,
we concatenate it to the filename when it makes sense.
if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
- copy.reset (concat (dirname, SLASH_STRING, filename, (char *) NULL));
- filename = copy.get ();
+ copy = path_join (dirname, filename);
+ filename = copy.c_str ();
}
cu->get_builder ()->start_subfile (filename);
variable has been optimized away. */
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
return;
}
unsigned int dummy;
if (block->data[0] == DW_OP_addr)
- SET_SYMBOL_VALUE_ADDRESS
- (sym, cu->header.read_address (objfile->obfd,
- block->data + 1,
- &dummy));
+ sym->set_value_address
+ (cu->header.read_address (objfile->obfd, block->data + 1,
+ &dummy));
else
- SET_SYMBOL_VALUE_ADDRESS
- (sym, read_addr_index_from_leb128 (cu, block->data + 1,
- &dummy));
- SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+ sym->set_value_address
+ (read_addr_index_from_leb128 (cu, block->data + 1, &dummy));
+ sym->set_aclass_index (LOC_STATIC);
fixup_symbol_section (sym, objfile);
- SET_SYMBOL_VALUE_ADDRESS
- (sym,
- SYMBOL_VALUE_ADDRESS (sym)
+ sym->set_value_address
+ (sym->value_address ()
+ objfile->section_offsets[sym->section_index ()]);
return;
}
/* Handle DW_AT_artificial. */
attr = dwarf2_attr (die, DW_AT_artificial, cu);
if (attr != nullptr)
- sym->artificial = attr->as_boolean ();
+ sym->set_is_artificial (attr->as_boolean ());
/* Default assumptions.
Use the passed type or decode it from the die. */
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+ sym->set_domain (VAR_DOMAIN);
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
if (type != NULL)
- SYMBOL_TYPE (sym) = type;
+ sym->set_type (type);
else
- SYMBOL_TYPE (sym) = die_type (die, cu);
+ sym->set_type (die_type (die, cu));
attr = dwarf2_attr (die,
inlined_func ? DW_AT_call_line : DW_AT_decl_line,
cu);
if (attr != nullptr)
- SYMBOL_LINE (sym) = attr->constant_value (0);
+ sym->set_line (attr->constant_value (0));
attr = dwarf2_attr (die,
inlined_func ? DW_AT_call_file : DW_AT_decl_file,
if (fe == NULL)
complaint (_("file index out of range"));
else
- symbol_set_symtab (sym, fe->symtab);
+ sym->set_symtab (fe->symtab);
}
switch (die->tag)
addr = attr->as_address ();
addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr);
- SET_SYMBOL_VALUE_ADDRESS (sym, addr);
- SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
+ sym->set_value_address (addr);
+ sym->set_aclass_index (LOC_LABEL);
}
else
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
- SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
- SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_type (objfile_type (objfile)->builtin_core_addr);
+ sym->set_domain (LABEL_DOMAIN);
add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_subprogram:
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
- SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
+ sym->set_aclass_index (LOC_BLOCK);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if ((attr2 != nullptr && attr2->as_boolean ())
|| cu->per_cu->lang == language_ada
case DW_TAG_inlined_subroutine:
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
- SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
- SYMBOL_INLINED (sym) = 1;
+ sym->set_aclass_index (LOC_BLOCK);
+ sym->set_is_inlined (1);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_template_value_param:
/* Compilation with minimal debug info may result in
variables with missing type entries. Change the
misleading `void' type to something sensible. */
- if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
- SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
+ if (sym->type ()->code () == TYPE_CODE_VOID)
+ sym->set_type (objfile_type (objfile)->builtin_int);
attr = dwarf2_attr (die, DW_AT_const_value, cu);
/* In the case of DW_TAG_member, we should only be called for
&& die->parent->tag == DW_TAG_common_block)
attr2 = NULL;
- if (SYMBOL_CLASS (sym) == LOC_STATIC
- && SYMBOL_VALUE_ADDRESS (sym) == 0
+ if (sym->aclass () == LOC_STATIC
+ && sym->value_address () == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
/* When a static variable is eliminated by the linker,
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
- if (SYMBOL_CLASS (sym) == LOC_STATIC
+ if (sym->aclass () == LOC_STATIC
&& (objfile->flags & OBJF_MAINLINE) == 0
&& per_objfile->per_bfd->can_copy)
{
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
- SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
+ sym->set_aclass_index (LOC_UNRESOLVED);
}
else if (!die_is_declaration (die, cu))
{
/* Use the default LOC_OPTIMIZED_OUT class. */
- gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT);
+ gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
if (!suppress_add)
list_to_add = cu->list_in_scope;
}
struct context_stack *curr
= cu->get_builder ()->get_current_context_stack ();
if (curr != nullptr && curr->name != nullptr)
- SYMBOL_IS_ARGUMENT (sym) = 1;
+ sym->set_is_argument (1);
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr != nullptr)
{
case DW_TAG_union_type:
case DW_TAG_set_type:
case DW_TAG_enumeration_type:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
-
+ case DW_TAG_namelist:
+ if (die->tag == DW_TAG_namelist)
+ {
+ sym->set_aclass_index (LOC_STATIC);
+ sym->set_domain (VAR_DOMAIN);
+ }
+ else
+ {
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (STRUCT_DOMAIN);
+ }
{
/* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
really ever be static objects: otherwise, if you try
/* The symbol's name is already allocated along
with this objfile, so we don't need to
duplicate it for the type. */
- if (SYMBOL_TYPE (sym)->name () == 0)
- SYMBOL_TYPE (sym)->set_name (sym->search_name ());
+ if (sym->type ()->name () == 0)
+ sym->type ()->set_name (sym->search_name ());
}
}
}
break;
case DW_TAG_typedef:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ case DW_TAG_generic_subrange:
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_enumerator:
break;
case DW_TAG_imported_declaration:
case DW_TAG_namespace:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+ sym->set_aclass_index (LOC_TYPEDEF);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_module:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (MODULE_DOMAIN);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_common_block:
- SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
- SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
+ sym->set_aclass_index (LOC_COMMON_BLOCK);
+ sym->set_domain (COMMON_BLOCK_DOMAIN);
add_symbol_to_list (sym, cu->list_in_scope);
break;
default:
const gdb_byte *bytes;
struct dwarf2_locexpr_baton *baton;
- dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
+ dwarf2_const_value_attr (attr, sym->type (),
sym->print_name (),
&objfile->objfile_obstack, cu,
&value, &bytes, &baton);
if (baton != NULL)
{
SYMBOL_LOCATION_BATON (sym) = baton;
- SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+ sym->set_aclass_index (dwarf2_locexpr_index);
}
else if (bytes != NULL)
- {
- SYMBOL_VALUE_BYTES (sym) = bytes;
- SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES;
+ {
+ sym->set_value_bytes (bytes);
+ sym->set_aclass_index (LOC_CONST_BYTES);
}
else
{
- SYMBOL_VALUE (sym) = value;
- SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
+ sym->set_value_longest (value);
+ sym->set_aclass_index (LOC_CONST);
}
}
struct dwarf2_per_cu_data *per_cu;
sect_offset sect_off = attr->get_ref_die_offset ();
- per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile);
+ per_cu = dwarf2_find_containing_comp_unit (sect_off, 1,
+ per_objfile->per_bfd);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
else if (attr->form_is_ref ())
case DW_TAG_typedef:
this_type = read_typedef (die, cu);
break;
+ case DW_TAG_generic_subrange:
case DW_TAG_subrange_type:
this_type = read_subrange_type (die, cu);
break;
&& die->tag != DW_TAG_class_type
&& die->tag != DW_TAG_interface_type
&& die->tag != DW_TAG_structure_type
+ && die->tag != DW_TAG_namelist
&& die->tag != DW_TAG_union_type)
return NULL;
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ case DW_TAG_namelist:
/* Some GCC versions emit spurious DW_AT_name attributes for unnamed
structures or unions. These were of the form "._%d" in GCC 4.1,
or simply "<anonymous struct>" or "<anonymous union>" in GCC 4.3
{
unsigned int i;
- print_spaces (indent, f);
- fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
- dwarf_tag_name (die->tag), die->abbrev,
- sect_offset_str (die->sect_off));
+ gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n",
+ indent, "",
+ dwarf_tag_name (die->tag), die->abbrev,
+ sect_offset_str (die->sect_off));
if (die->parent != NULL)
- {
- print_spaces (indent, f);
- fprintf_unfiltered (f, " parent at offset: %s\n",
- sect_offset_str (die->parent->sect_off));
- }
+ gdb_printf (f, "%*s parent at offset: %s\n",
+ indent, "",
+ sect_offset_str (die->parent->sect_off));
- print_spaces (indent, f);
- fprintf_unfiltered (f, " has children: %s\n",
- dwarf_bool_name (die->child != NULL));
+ gdb_printf (f, "%*s has children: %s\n",
+ indent, "",
+ dwarf_bool_name (die->child != NULL));
- print_spaces (indent, f);
- fprintf_unfiltered (f, " attributes:\n");
+ gdb_printf (f, "%*s attributes:\n", indent, "");
for (i = 0; i < die->num_attrs; ++i)
{
- print_spaces (indent, f);
- fprintf_unfiltered (f, " %s (%s) ",
- dwarf_attr_name (die->attrs[i].name),
- dwarf_form_name (die->attrs[i].form));
+ gdb_printf (f, "%*s %s (%s) ",
+ indent, "",
+ dwarf_attr_name (die->attrs[i].name),
+ dwarf_form_name (die->attrs[i].form));
switch (die->attrs[i].form)
{
case DW_FORM_addr:
case DW_FORM_addrx:
case DW_FORM_GNU_addr_index:
- fprintf_unfiltered (f, "address: ");
- fputs_filtered (hex_string (die->attrs[i].as_address ()), f);
+ gdb_printf (f, "address: ");
+ gdb_puts (hex_string (die->attrs[i].as_address ()), f);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf_unfiltered (f, "block: size %s",
- pulongest (die->attrs[i].as_block ()->size));
+ gdb_printf (f, "block: size %s",
+ pulongest (die->attrs[i].as_block ()->size));
break;
case DW_FORM_exprloc:
- fprintf_unfiltered (f, "expression: size %s",
- pulongest (die->attrs[i].as_block ()->size));
+ gdb_printf (f, "expression: size %s",
+ pulongest (die->attrs[i].as_block ()->size));
break;
case DW_FORM_data16:
- fprintf_unfiltered (f, "constant of 16 bytes");
+ gdb_printf (f, "constant of 16 bytes");
break;
case DW_FORM_ref_addr:
- fprintf_unfiltered (f, "ref address: ");
- fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+ gdb_printf (f, "ref address: ");
+ gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
break;
case DW_FORM_GNU_ref_alt:
- fprintf_unfiltered (f, "alt ref address: ");
- fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+ gdb_printf (f, "alt ref address: ");
+ gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
- (long) (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "constant ref: 0x%lx (adjusted)",
+ (long) (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_udata:
- fprintf_unfiltered (f, "constant: %s",
- pulongest (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "constant: %s",
+ pulongest (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_sec_offset:
- fprintf_unfiltered (f, "section offset: %s",
- pulongest (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "section offset: %s",
+ pulongest (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_ref_sig8:
- fprintf_unfiltered (f, "signature: %s",
- hex_string (die->attrs[i].as_signature ()));
+ gdb_printf (f, "signature: %s",
+ hex_string (die->attrs[i].as_signature ()));
break;
case DW_FORM_string:
case DW_FORM_strp:
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
- fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
- die->attrs[i].as_string ()
- ? die->attrs[i].as_string () : "",
- die->attrs[i].canonical_string_p () ? "is" : "not");
+ gdb_printf (f, "string: \"%s\" (%s canonicalized)",
+ die->attrs[i].as_string ()
+ ? die->attrs[i].as_string () : "",
+ die->attrs[i].canonical_string_p () ? "is" : "not");
break;
case DW_FORM_flag:
if (die->attrs[i].as_boolean ())
- fprintf_unfiltered (f, "flag: TRUE");
+ gdb_printf (f, "flag: TRUE");
else
- fprintf_unfiltered (f, "flag: FALSE");
+ gdb_printf (f, "flag: FALSE");
break;
case DW_FORM_flag_present:
- fprintf_unfiltered (f, "flag: TRUE");
+ gdb_printf (f, "flag: TRUE");
break;
case DW_FORM_indirect:
/* The reader will have reduced the indirect form to
the "base form" so this form should not occur. */
- fprintf_unfiltered (f,
- "unexpected attribute form: DW_FORM_indirect");
+ gdb_printf (f,
+ "unexpected attribute form: DW_FORM_indirect");
break;
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- fprintf_unfiltered (f, "constant: %s",
- plongest (die->attrs[i].as_signed ()));
+ gdb_printf (f, "constant: %s",
+ plongest (die->attrs[i].as_signed ()));
break;
default:
- fprintf_unfiltered (f, "unsupported attribute form: %d.",
- die->attrs[i].form);
+ gdb_printf (f, "unsupported attribute form: %d.",
+ die->attrs[i].form);
break;
}
- fprintf_unfiltered (f, "\n");
+ gdb_printf (f, "\n");
}
}
if (die->child != NULL)
{
- print_spaces (indent, f);
- fprintf_unfiltered (f, " Children:");
+ gdb_printf (f, "%*s Children:", indent, "");
if (level + 1 < max_level)
{
- fprintf_unfiltered (f, "\n");
+ gdb_printf (f, "\n");
dump_die_1 (f, level + 1, max_level, die->child);
}
else
{
- fprintf_unfiltered (f,
- " [not printed, max nesting level reached]\n");
+ gdb_printf (f,
+ " [not printed, max nesting level reached]\n");
}
}
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile);
+ per_objfile->per_bfd);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
else if (cu->dies == NULL)
{
/* We're loading full DIEs during partial symbol reading. */
- gdb_assert (per_objfile->per_bfd->reading_partial_symbols);
load_full_comp_unit (cu->per_cu, per_objfile, cu, false,
language_minimal);
}
/* For .gdb_index version 7 keep track of included TUs.
http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
if (per_objfile->per_bfd->index_table != NULL
- && per_objfile->per_bfd->index_table->version <= 7)
+ && !per_objfile->per_bfd->index_table->version_check ())
{
(*ref_cu)->per_cu->imported_symtabs_push (sig_cu->per_cu);
}
{
struct signatured_type *sig_type;
- /* Caller is responsible for ensuring type_unit_groups don't get here. */
- gdb_assert (! per_cu->type_unit_group_p ());
-
/* We have the per_cu, but we need the signatured_type.
Fortunately this is an easy translation. */
gdb_assert (per_cu->is_debug_types);
complaint (_("Location list used without "
"specifying the CU base address."));
- SYMBOL_ACLASS_INDEX (sym) = (is_block
- ? dwarf2_loclist_block_index
- : dwarf2_loclist_index);
+ sym->set_aclass_index ((is_block
+ ? dwarf2_loclist_block_index
+ : dwarf2_loclist_index));
SYMBOL_LOCATION_BATON (sym) = baton;
}
else
baton->size = 0;
}
- SYMBOL_ACLASS_INDEX (sym) = (is_block
- ? dwarf2_locexpr_block_index
- : dwarf2_locexpr_index);
+ sym->set_aclass_index ((is_block
+ ? dwarf2_locexpr_block_index
+ : dwarf2_locexpr_index));
SYMBOL_LOCATION_BATON (sym) = baton;
}
}
static struct dwarf2_per_cu_data *
dwarf2_find_containing_comp_unit (sect_offset sect_off,
unsigned int offset_in_dwz,
- dwarf2_per_objfile *per_objfile)
+ dwarf2_per_bfd *per_bfd)
{
int low = dwarf2_find_containing_comp_unit
- (sect_off, offset_in_dwz, per_objfile->per_bfd->all_comp_units);
- dwarf2_per_cu_data *this_cu
- = per_objfile->per_bfd->all_comp_units[low].get ();
+ (sect_off, offset_in_dwz, per_bfd->all_comp_units);
+ dwarf2_per_cu_data *this_cu = per_bfd->all_comp_units[low].get ();
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
error (_("Dwarf Error: could not find partial DIE containing "
"offset %s [in module %s]"),
sect_offset_str (sect_off),
- bfd_get_filename (per_objfile->objfile->obfd));
+ bfd_get_filename (per_bfd->obfd));
- gdb_assert (per_objfile->per_bfd->all_comp_units[low-1]->sect_off
+ gdb_assert (per_bfd->all_comp_units[low-1]->sect_off
<= sect_off);
- return per_objfile->per_bfd->all_comp_units[low - 1].get ();
+ return per_bfd->all_comp_units[low - 1].get ();
}
else
{
- if (low == per_objfile->per_bfd->all_comp_units.size () - 1
+ if (low == per_bfd->all_comp_units.size () - 1
&& sect_off >= this_cu->sect_off + this_cu->length)
error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
}
+ /* Read DW_AT_rank and set in type. */
+ attr = dwarf2_attr (die, DW_AT_rank, cu);
+ if (attr != NULL)
+ {
+ struct type *prop_type = cu->addr_sized_int_type (false);
+ if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
+ type->add_dyn_prop (DYN_PROP_RANK, prop);
+ }
+
/* Read DW_AT_data_location and set in type. */
if (!skip_data_location)
{
return get_die_type_at_offset (die->sect_off, cu->per_cu, cu->per_objfile);
}
-/* Trivial hash function for partial_die_info: the hash value of a DIE
- is its offset in .debug_info for this objfile. */
-
-static hashval_t
-partial_die_hash (const void *item)
-{
- const struct partial_die_info *part_die
- = (const struct partial_die_info *) item;
-
- return to_underlying (part_die->sect_off);
-}
-
-/* Trivial comparison function for partial_die_info structures: two DIEs
- are equal if they have the same offset. */
-
-static int
-partial_die_eq (const void *item_lhs, const void *item_rhs)
-{
- const struct partial_die_info *part_die_lhs
- = (const struct partial_die_info *) item_lhs;
- const struct partial_die_info *part_die_rhs
- = (const struct partial_die_info *) item_rhs;
-
- return part_die_lhs->sect_off == part_die_rhs->sect_off;
-}
-
struct cmd_list_element *set_dwarf_cmdlist;
struct cmd_list_element *show_dwarf_cmdlist;
show_check_physname (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Whether to check \"physname\" is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Whether to check \"physname\" is %s.\n"),
+ value);
}
void _initialize_dwarf2_read ();
void
_initialize_dwarf2_read ()
{
- add_basic_prefix_cmd ("dwarf", class_maintenance, _("\
+ add_setshow_prefix_cmd ("dwarf", class_maintenance,
+ _("\
Set DWARF specific variables.\n\
Configure DWARF variables such as the cache size."),
- &set_dwarf_cmdlist,
- 0/*allow-unknown*/, &maintenance_set_cmdlist);
-
- add_show_prefix_cmd ("dwarf", class_maintenance, _("\
+ _("\
Show DWARF specific variables.\n\
Show DWARF variables such as the cache size."),
- &show_dwarf_cmdlist,
- 0/*allow-unknown*/, &maintenance_show_cmdlist);
+ &set_dwarf_cmdlist, &show_dwarf_cmdlist,
+ &maintenance_set_cmdlist, &maintenance_show_cmdlist);
add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
&dwarf_max_cache_age, _("\