diff options
Diffstat (limited to 'gdb/dwarf2')
29 files changed, 1814 insertions, 1448 deletions
diff --git a/gdb/dwarf2/ada-imported.c b/gdb/dwarf2/ada-imported.c index 1e25966..48e6fcc 100644 --- a/gdb/dwarf2/ada-imported.c +++ b/gdb/dwarf2/ada-imported.c @@ -109,7 +109,7 @@ ada_alias_get_block_value (const struct symbol *sym) if (real_symbol.symbol == nullptr) error (_("could not find alias '%s' for function '%s'"), name, sym->print_name ()); - if (real_symbol.symbol->aclass () != LOC_BLOCK) + if (real_symbol.symbol->loc_class () != LOC_BLOCK) error (_("alias '%s' for function '%s' is not a function"), name, sym->print_name ()); diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c index 2d14ebd..d2b5364 100644 --- a/gdb/dwarf2/attribute.c +++ b/gdb/dwarf2/attribute.c @@ -186,6 +186,52 @@ attribute::unsigned_constant () const /* See attribute.h. */ +std::optional<LONGEST> +attribute::signed_constant () const +{ + if (form_is_strictly_signed ()) + return u.snd; + + switch (form) + { + case DW_FORM_data8: + case DW_FORM_udata: + /* Not sure if DW_FORM_udata should be handled or not. Anyway + for DW_FORM_data8, there's no need to sign-extend. */ + return u.snd; + + case DW_FORM_data1: + return sign_extend (u.unsnd, 8); + case DW_FORM_data2: + return sign_extend (u.unsnd, 16); + case DW_FORM_data4: + return sign_extend (u.unsnd, 32); + } + + /* For DW_FORM_data16 see attribute::form_is_constant. */ + complaint (_("Attribute value is not a constant (%s)"), + dwarf_form_name (form)); + return {}; +} + +/* See attribute.h. */ + +std::optional<LONGEST> +attribute::confused_constant () const +{ + if (form_is_strictly_signed ()) + return u.snd; + else if (form_is_constant ()) + return u.unsnd; + + /* For DW_FORM_data16 see attribute::form_is_constant. */ + complaint (_("Attribute value is not a constant (%s)"), + dwarf_form_name (form)); + return {}; +} + +/* See attribute.h. */ + bool attribute::form_is_unsigned () const { @@ -296,5 +342,8 @@ attribute::as_boolean () const return true; else if (form == DW_FORM_flag) return u.unsnd != 0; - return constant_value (0) != 0; + /* Using signed_constant here will work even for the weird case + where a negative value is provided. Probably doesn't matter but + also seems harmless. */ + return signed_constant ().value_or (0) != 0; } diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h index ec4f3d8..234de4e 100644 --- a/gdb/dwarf2/attribute.h +++ b/gdb/dwarf2/attribute.h @@ -114,6 +114,34 @@ struct attribute returned. */ std::optional<ULONGEST> unsigned_constant () const; + /* Return a signed constant value. This only handles constant forms + (i.e., form_is_constant -- and not the extended list of + "unsigned" forms) and assumes a signed value is desired. This + function will sign-extend DW_FORM_data* values. + + If non-constant form is used, then complaint is issued and an + empty value is returned. */ + std::optional<LONGEST> signed_constant () const; + + /* Return a signed constant value. However, for narrow forms like + DW_FORM_data1, sign extension is not done. + + DWARF advises compilers to generally use DW_FORM_[su]data to + avoid ambiguity. However, both GCC and LLVM ignore this for + certain attributes. Furthermore in DWARF, whether a narrower + form causes sign-extension depends on the attribute -- for + attributes that can only assume non-negative values, sign + extension is not done. + + Unfortunately, both compilers also emit certain attributes in a + "confused" way, using DW_FORM_sdata for signed values, and + possibly choosing a narrow form (e.g., DW_FORM_data1) otherwise + -- assuming that sign-extension will not be done. + + This method should only be called when this "confused" treatment + is necessary. */ + std::optional<LONGEST> confused_constant () const; + /* Return non-zero if ATTR's value falls in the 'constant' class, or zero otherwise. When this function returns true, you can apply the constant_value method to it. @@ -166,6 +194,15 @@ struct attribute false. */ bool form_is_strictly_signed () const; + /* Check if the attribute's form is an unsigned constant form. This + only returns true for forms that are strictly unsigned -- that + is, for a context-dependent form like DW_FORM_data1, this returns + false. */ + bool form_is_strictly_unsigned () const + { + return form == DW_FORM_udata; + } + /* Check if the attribute's form is a form that requires "reprocessing". */ bool form_requires_reprocessing () const; diff --git a/gdb/dwarf2/call-site.h b/gdb/dwarf2/call-site.h index e02cc5e..2cc4883 100644 --- a/gdb/dwarf2/call-site.h +++ b/gdb/dwarf2/call-site.h @@ -198,7 +198,7 @@ struct call_site struct call_site *tail_call_next = nullptr; /* * Describe DW_AT_call_target. Missing attribute uses - FIELD_LOC_KIND_DWARF_BLOCK with FIELD_DWARF_BLOCK == NULL. */ + m_loc_kind == DWARF_BLOCK with m_loc.dwarf_block == nullptr. */ struct call_site_target target {}; diff --git a/gdb/dwarf2/cooked-index-entry.c b/gdb/dwarf2/cooked-index-entry.c index 52db851..863ddd6 100644 --- a/gdb/dwarf2/cooked-index-entry.c +++ b/gdb/dwarf2/cooked-index-entry.c @@ -33,6 +33,7 @@ to_string (cooked_index_flag flags) MAP_ENUM_FLAG (IS_LINKAGE), MAP_ENUM_FLAG (IS_TYPE_DECLARATION), MAP_ENUM_FLAG (IS_PARENT_DEFERRED), + MAP_ENUM_FLAG (IS_SYNTHESIZED), }; return flags.to_string (mapping); @@ -233,8 +234,7 @@ cooked_index_entry::write_scope (struct obstack *storage, obstack_grow (storage, sep, strlen (sep)); } -void _initialize_dwarf2_entry (); -void _initialize_dwarf2_entry () +INIT_GDB_FILE (dwarf2_entry) { #if GDB_SELF_TEST selftests::register_test ("cooked_index_entry::compare", test_compare); diff --git a/gdb/dwarf2/cooked-index-worker.c b/gdb/dwarf2/cooked-index-worker.c index da51a8c..09d80ef 100644 --- a/gdb/dwarf2/cooked-index-worker.c +++ b/gdb/dwarf2/cooked-index-worker.c @@ -20,6 +20,7 @@ #include "dwarf2/cooked-index-worker.h" #include "dwarf2/cooked-index.h" #include "gdbsupport/thread-pool.h" +#include "maint.h" #include "run-on-main-thread.h" #include "event-top.h" #include "exceptions.h" @@ -244,8 +245,12 @@ cooked_index_worker::write_to_cache (const cooked_index *idx) void cooked_index_worker::done_reading () { - for (auto &one_result : m_results) - m_all_parents_map.add_map (*one_result.get_parent_map ()); + { + scoped_time_it time_it ("DWARF add parent map", m_per_command_time); + + for (auto &one_result : m_results) + m_all_parents_map.add_map (*one_result.get_parent_map ()); + } dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; cooked_index *table diff --git a/gdb/dwarf2/cooked-index-worker.h b/gdb/dwarf2/cooked-index-worker.h index df5c31d..8b9766c 100644 --- a/gdb/dwarf2/cooked-index-worker.h +++ b/gdb/dwarf2/cooked-index-worker.h @@ -25,6 +25,8 @@ #include "dwarf2/cooked-index-shard.h" #include "dwarf2/types.h" #include "dwarf2/read.h" +#include "maint.h" +#include "run-on-main-thread.h" #if CXX_STD_THREAD #include <mutex> @@ -107,11 +109,20 @@ public: return &m_parent_map; } - /* Add an exception to the list of exceptions caught while reading. - These are passed forward and printed by the main thread. */ - void note_error (gdb_exception &&except) + /* Catch exceptions from calling F (), and add them to the list of caught + exceptions. These are passed forward and printed by the main thread. */ + template <typename F> + void + catch_error (F &&f) { - m_exceptions.push_back (std::move (except)); + try + { + f (); + } + catch (gdb_exception &ex) + { + m_exceptions.push_back (std::move (ex)); + } } /* Called when the thread using this object is done with its work. @@ -207,8 +218,12 @@ public: explicit cooked_index_worker (dwarf2_per_objfile *per_objfile) : m_per_objfile (per_objfile), - m_cache_store (global_index_cache, per_objfile->per_bfd) - { } + m_cache_store (global_index_cache, per_objfile->per_bfd), + m_per_command_time (per_command_time) + { + /* Make sure we capture per_command_time from the main thread. */ + gdb_assert (is_main_thread ()); + } virtual ~cooked_index_worker () { } DISABLE_COPY_AND_ASSIGN (cooked_index_worker); @@ -298,6 +313,9 @@ protected: std::optional<gdb_exception> m_failed; /* An object used to write to the index cache. */ index_cache_store_context m_cache_store; + + /* Captured value of per_command_time. */ + bool m_per_command_time; }; using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>; diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index 7948ffa..6209590 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -21,6 +21,7 @@ #include "dwarf2/read.h" #include "dwarf2/stringify.h" #include "event-top.h" +#include "maint.h" #include "observable.h" #include "run-on-main-thread.h" #include "gdbsupport/task-group.h" @@ -101,7 +102,12 @@ cooked_index::set_contents () { auto this_shard = shard.get (); const parent_map_map *parent_maps = m_state->get_parent_map_map (); - finalizers.add_task ([=] () { this_shard->finalize (parent_maps); }); + finalizers.add_task ([=] () + { + scoped_time_it time_it ("DWARF finalize worker", + m_state->m_per_command_time); + this_shard->finalize (parent_maps); + }); } finalizers.start (); @@ -321,9 +327,7 @@ maintenance_wait_for_index_cache (const char *args, int from_tty) wait_for_index_cache (0); } -void _initialize_cooked_index (); -void -_initialize_cooked_index () +INIT_GDB_FILE (cooked_index) { add_cmd ("wait-for-index-cache", class_maintenance, maintenance_wait_for_index_cache, _("\ diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c index b8b66cf..d4557c45 100644 --- a/gdb/dwarf2/cooked-indexer.c +++ b/gdb/dwarf2/cooked-indexer.c @@ -83,19 +83,17 @@ tag_can_have_linkage_name (enum dwarf_tag tag) cutu_reader * cooked_indexer::ensure_cu_exists (cutu_reader *reader, - sect_offset sect_off, bool is_dwz, + const section_and_offset §_off, bool for_scanning) { /* 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)) + if (reader->section () == sect_off.section + && reader->cu ()->header.offset_in_unit_p (sect_off.offset)) return reader; dwarf2_per_objfile *per_objfile = reader->cu ()->per_objfile; - dwarf2_per_cu *per_cu - = dwarf2_find_containing_comp_unit (sect_off, is_dwz, - per_objfile->per_bfd); + dwarf2_per_cu *per_cu = dwarf2_find_containing_unit (sect_off, per_objfile); /* When scanning, we only want to visit a given CU a single time. Doing this check here avoids self-imports as well. */ @@ -109,20 +107,20 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader, cutu_reader *result = m_index_storage->get_reader (per_cu); if (result == nullptr) { - cutu_reader new_reader (*per_cu, *per_objfile, nullptr, nullptr, false, - language_minimal, - &m_index_storage->get_abbrev_table_cache ()); - - if (new_reader.is_dummy () || new_reader.top_level_die () == nullptr - || !new_reader.top_level_die ()->has_children) + const abbrev_table_cache &abbrev_table_cache + = m_index_storage->get_abbrev_table_cache (); + auto new_reader + = std::make_unique<cutu_reader> (*per_cu, *per_objfile, nullptr, + nullptr, false, language_minimal, + &abbrev_table_cache); + + if (new_reader->is_dummy ()) return nullptr; - auto copy = std::make_unique<cutu_reader> (std::move (new_reader)); - result = m_index_storage->preserve (std::move (copy)); + result = m_index_storage->preserve (std::move (new_reader)); } - if (result->is_dummy () || result->top_level_die () == nullptr - || !result->top_level_die ()->has_children) + if (result->is_dummy ()) return nullptr; if (for_scanning) @@ -148,10 +146,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, bool *is_enum_class, bool for_specification) { - bool origin_is_dwz = false; bool is_declaration = false; - sect_offset origin_offset {}; - + std::optional<section_and_offset> origin; std::optional<unrelocated_addr> low_pc; std::optional<unrelocated_addr> high_pc; bool high_pc_relative = false; @@ -221,8 +217,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, case DW_AT_specification: case DW_AT_abstract_origin: case DW_AT_extension: - origin_offset = attr.get_ref_die_offset (); - origin_is_dwz = attr.form_is_alt (); + origin = { &get_section_for_ref (attr, reader->cu ()), + attr.get_ref_die_offset () }; break; case DW_AT_external: @@ -311,19 +307,19 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, || (*linkage_name == nullptr && tag_can_have_linkage_name (abbrev->tag)) || (*parent_entry == nullptr && m_language != language_c)) - && origin_offset != sect_offset (0)) + && origin.has_value ()) { cutu_reader *new_reader - = ensure_cu_exists (reader, origin_offset, origin_is_dwz, false); + = ensure_cu_exists (reader, *origin, false); if (new_reader == nullptr) error (_(DWARF_ERROR_PREFIX "cannot follow reference to DIE at %s" " [in module %s]"), - sect_offset_str (origin_offset), + sect_offset_str (origin->offset), bfd_get_filename (reader->abfd ())); const gdb_byte *new_info_ptr - = (new_reader->buffer () + to_underlying (origin_offset)); + = (new_reader->buffer () + to_underlying (origin->offset)); if (*parent_entry == nullptr) { @@ -347,7 +343,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, if (new_abbrev == nullptr) error (_(DWARF_ERROR_PREFIX "Unexpected null DIE at offset %s [in module %s]"), - sect_offset_str (origin_offset), + sect_offset_str (origin->offset), bfd_get_filename (new_reader->abfd ())); new_info_ptr += bytes_read; @@ -411,8 +407,7 @@ 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; + std::optional<section_and_offset> target; for (int i = 0; i < abbrev->num_attrs; ++i) { @@ -421,19 +416,16 @@ cooked_indexer::index_imported_unit (cutu_reader *reader, info_ptr = reader->read_attribute (&attr, &abbrev->attrs[i], info_ptr); if (attr.name == DW_AT_import) - { - sect_off = attr.get_ref_die_offset (); - is_dwz = (attr.form_is_alt () - || reader->cu ()->per_cu->is_dwz); - } + target = { &get_section_for_ref (attr, reader->cu ()), + attr.get_ref_die_offset () }; } /* Did not find DW_AT_import. */ - if (sect_off == sect_offset (0)) + if (!target.has_value ()) return info_ptr; cutu_reader *new_reader - = ensure_cu_exists (reader, sect_off, is_dwz, true); + = ensure_cu_exists (reader, *target, true); if (new_reader != nullptr) { index_dies (new_reader, new_reader->info_ptr (), nullptr, false); diff --git a/gdb/dwarf2/cooked-indexer.h b/gdb/dwarf2/cooked-indexer.h index 904c55f..83cbf7f 100644 --- a/gdb/dwarf2/cooked-indexer.h +++ b/gdb/dwarf2/cooked-indexer.h @@ -30,6 +30,7 @@ struct cooked_index_worker_result; struct cutu_reader; struct dwarf2_per_cu; struct dwarf2_per_objfile; +struct section_and_offset; /* An instance of this is created to index a CU. */ @@ -55,8 +56,7 @@ private: 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, - sect_offset sect_off, - bool is_dwz, + const section_and_offset §_off, bool for_scanning); /* Index DIEs in the READER starting at INFO_PTR. PARENT is diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h index 5683291..68010a0 100644 --- a/gdb/dwarf2/cu.h +++ b/gdb/dwarf2/cu.h @@ -21,7 +21,7 @@ #define GDB_DWARF2_CU_H #include "buildsym.h" -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/unit-head.h" #include <optional> #include "language.h" #include "gdbsupport/unordered_set.h" @@ -54,6 +54,11 @@ struct dwarf2_cu DISABLE_COPY_AND_ASSIGN (dwarf2_cu); + /* The section the DIEs were effectively read from. This could be + .debug_info, .debug_types, or with split DWARF, their .dwo + variants. */ + const dwarf2_section_info §ion () const; + /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope. Create the set of symtabs used by this TU, or if this TU is sharing symtabs with another TU and the symtabs have already been created @@ -99,8 +104,17 @@ struct dwarf2_cu void add_dependence (dwarf2_per_cu *ref_per_cu) { m_dependencies.emplace (ref_per_cu); } + /* Find the DIE at section offset SECT_OFF. + + Return nullptr if not found. */ + die_info *find_die (sect_offset sect_off) const + { + auto it = die_hash.find (sect_off); + return it != die_hash.end () ? *it : nullptr; + } + /* The header of the compilation unit. */ - struct comp_unit_head header; + struct unit_head header; /* Base address of this compilation unit. */ std::optional<unrelocated_addr> base_address; @@ -360,7 +374,7 @@ public: right place. And since the DW_TAG_compile_unit DIE in the split-unit can't have a DW_AT_ranges attribute, we can use the - die->tag != DW_AT_compile_unit + die->tag != DW_TAG_compile_unit to determine whether the base should be added or not. */ ULONGEST gnu_ranges_base = 0; diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c index 583103b..1aa0d03 100644 --- a/gdb/dwarf2/dwz.c +++ b/gdb/dwarf2/dwz.c @@ -56,35 +56,37 @@ dwz_file::read_string (struct objfile *objfile, LONGEST str_offset) /* A helper function to find the sections for a .dwz file. */ static void -locate_dwz_sections (struct objfile *objfile, bfd *abfd, asection *sectp, - dwz_file *dwz_file) +locate_dwz_sections (objfile *objfile, dwz_file &dwz_file) { - dwarf2_section_info *sect = nullptr; + for (asection *sec : gdb_bfd_sections (dwz_file.dwz_bfd)) + { + dwarf2_section_info *sect = nullptr; - /* Note that we only support the standard ELF names, because .dwz + /* Note that we only support the standard ELF names, because .dwz is ELF-only (at the time of writing). */ - if (dwarf2_elf_names.abbrev.matches (sectp->name)) - sect = &dwz_file->abbrev; - else if (dwarf2_elf_names.info.matches (sectp->name)) - sect = &dwz_file->info; - else if (dwarf2_elf_names.str.matches (sectp->name)) - sect = &dwz_file->str; - else if (dwarf2_elf_names.line.matches (sectp->name)) - sect = &dwz_file->line; - else if (dwarf2_elf_names.macro.matches (sectp->name)) - sect = &dwz_file->macro; - else if (dwarf2_elf_names.gdb_index.matches (sectp->name)) - sect = &dwz_file->gdb_index; - else if (dwarf2_elf_names.debug_names.matches (sectp->name)) - sect = &dwz_file->debug_names; - else if (dwarf2_elf_names.types.matches (sectp->name)) - sect = &dwz_file->types; - - if (sect != nullptr) - { - sect->s.section = sectp; - sect->size = bfd_section_size (sectp); - sect->read (objfile); + if (dwarf2_elf_names.abbrev.matches (sec->name)) + sect = &dwz_file.abbrev; + else if (dwarf2_elf_names.info.matches (sec->name)) + sect = &dwz_file.info; + else if (dwarf2_elf_names.str.matches (sec->name)) + sect = &dwz_file.str; + else if (dwarf2_elf_names.line.matches (sec->name)) + sect = &dwz_file.line; + else if (dwarf2_elf_names.macro.matches (sec->name)) + sect = &dwz_file.macro; + else if (dwarf2_elf_names.gdb_index.matches (sec->name)) + sect = &dwz_file.gdb_index; + else if (dwarf2_elf_names.debug_names.matches (sec->name)) + sect = &dwz_file.debug_names; + else if (dwarf2_elf_names.types.matches (sec->name)) + sect = &dwz_file.types; + + if (sect != nullptr) + { + sect->s.section = sec; + sect->size = bfd_section_size (sec); + sect->read (objfile); + } } } @@ -341,7 +343,7 @@ dwz_file::read_dwz_file (dwarf2_per_objfile *per_objfile) { gdb::unique_xmalloc_ptr<char> abs = gdb_realpath (per_bfd->filename ()); - filename = ldirname (abs.get ()) + SLASH_STRING + filename; + filename = gdb_ldirname (abs.get ()) + SLASH_STRING + filename; } /* First try the file name given in the section. If that doesn't @@ -392,9 +394,7 @@ dwz_file::read_dwz_file (dwarf2_per_objfile *per_objfile) dwz_file_up result (new dwz_file (std::move (dwz_bfd))); - for (asection *sec : gdb_bfd_sections (result->dwz_bfd)) - locate_dwz_sections (per_objfile->objfile, result->dwz_bfd.get (), - sec, result.get ()); + locate_dwz_sections (per_objfile->objfile, *result); gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ()); bfd_cache_close (result->dwz_bfd.get ()); diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c index 6464ffb..e31ae10 100644 --- a/gdb/dwarf2/frame-tailcall.c +++ b/gdb/dwarf2/frame-tailcall.c @@ -478,9 +478,7 @@ const struct frame_unwind_legacy dwarf2_tailcall_frame_unwind ( tailcall_frame_prev_arch ); -void _initialize_tailcall_frame (); -void -_initialize_tailcall_frame () +INIT_GDB_FILE (tailcall_frame) { cache_htab = htab_create_alloc (50, cache_hash, cache_eq, NULL, xcalloc, xfree); diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 1b4de0d..7a37285 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -2247,9 +2247,7 @@ dwarf2_build_frame_info (struct objfile *objfile) set_comp_unit (objfile, unit.release ()); } -void _initialize_dwarf2_frame (); -void -_initialize_dwarf2_frame () +INIT_GDB_FILE (dwarf2_frame) { #if GDB_SELF_TEST selftests::register_test_foreach_arch ("execute_cfa_program", diff --git a/gdb/dwarf2/frame.h b/gdb/dwarf2/frame.h index f8fd8e8..9357cc1 100644 --- a/gdb/dwarf2/frame.h +++ b/gdb/dwarf2/frame.h @@ -198,6 +198,15 @@ struct dwarf2_frame_state bool armcc_cfa_offsets_reversed = false; }; +/* If DWARF supoprt was requested, create the real prototype for the + append_unwinders function. Otherwise, create a fake inline function. + + There is no need to emit a warning for some of these, because they aren't + actively reading DWARF when this is called, they're just initializing GDB. + + These should probably be moved to dwarf2/public.h. */ +#if defined(DWARF_FORMAT_AVAILABLE) + /* Set the architecture-specific register state initialization function for GDBARCH to INIT_REG. */ @@ -287,4 +296,56 @@ extern void *dwarf2_frame_get_fn_data (const frame_info_ptr &this_frame, void **this_cache, fn_prev_register cookie); +#else /* DWARF_FORMAT_AVAILABLE */ + +static inline void dwarf2_append_unwinders (struct gdbarch *gdbarch) { } + +static inline void dwarf2_frame_set_init_reg ( + gdbarch *gdbarch, void (*init_reg) (struct gdbarch *,int, + dwarf2_frame_state_reg *, + const frame_info_ptr &)) { } + +static inline const struct frame_base * + dwarf2_frame_base_sniffer (const frame_info_ptr &this_frame) +{ + warning (_("No dwarf support available.")); + return nullptr; +} + +static inline void dwarf2_frame_set_signal_frame_p + (gdbarch *gdbarch, int (*signal_frame_p) (struct gdbarch *, + const frame_info_ptr &)) { } + +static inline void *dwarf2_frame_get_fn_data (const frame_info_ptr &this_frame, + void **this_cache, + fn_prev_register cookie) +{ + return nullptr; +} + +static inline void *dwarf2_frame_allocate_fn_data + (const frame_info_ptr &this_frame, void **this_cache, + fn_prev_register cookie, unsigned long size) +{ + return nullptr; +} + +static inline int dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc, + struct dwarf2_per_cu_data *data, + int *regnum_out, LONGEST *offset_out, + CORE_ADDR *text_offset_out, + const gdb_byte **cfa_start_out, + const gdb_byte **cfa_end_out) +{ + return 0; +} + +static inline void + dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch, + int (*adjust_regnum) (struct gdbarch *, + int, int)) +{} + +#endif /* DWARF_FORMAT_AVAILABLE */ + #endif /* GDB_DWARF2_FRAME_H */ diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c index 1715beb..cfe8ce9 100644 --- a/gdb/dwarf2/index-cache.c +++ b/gdb/dwarf2/index-cache.c @@ -342,9 +342,7 @@ show_index_cache_stats_command (const char *arg, int from_tty) indent, global_index_cache.n_misses ()); } -void _initialize_index_cache (); -void -_initialize_index_cache () +INIT_GDB_FILE (index_cache) { /* Set the default index cache directory. */ std::string cache_dir = get_standard_cache_dir (); diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index 614bdcd..d5b198b 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -872,7 +872,7 @@ public: m_debugstrlookup.file_write (file_str); } - void add_cu (dwarf2_per_cu *per_cu, offset_type index) + void add_cu (const dwarf2_per_cu *per_cu, offset_type index) { m_cu_index_htab.emplace (per_cu, index); } @@ -1289,6 +1289,40 @@ write_shortcuts_table (cooked_index *table, data_buf &shortcuts, shortcuts.append_offset (main_name_offset); } +/* Get sorted (by section offset) lists of comp units and type units. */ + +static std::pair<std::vector<const dwarf2_per_cu *>, + std::vector<const signatured_type *>> +get_unit_lists (const dwarf2_per_bfd &per_bfd) +{ + std::vector<const dwarf2_per_cu *> comp_units; + std::vector<const signatured_type *> type_units; + + for (const auto &unit : per_bfd.all_units) + if (unit->is_debug_types) + type_units.emplace_back (static_cast<const signatured_type *> + (unit.get ())); + else + comp_units.emplace_back (unit.get ()); + + auto by_sect_off = [] (const dwarf2_per_cu *lhs, const dwarf2_per_cu *rhs) + { return lhs->sect_off < rhs->sect_off; }; + + /* Sort both lists, even though it is technically not always required: + + - while .gdb_index requires the CU list to be sorted, DWARF 5 doesn't + say anything about the order of CUs in .debug_names. + - .gdb_index doesn't require the TU list to be sorted, and DWARF 5 + doesn't say anything about the order of TUs in .debug_names. + + However, it helps make sure that GDB produce a stable and predictable + output, which is nice. */ + std::sort (comp_units.begin (), comp_units.end (), by_sect_off); + std::sort (type_units.begin (), type_units.end (), by_sect_off); + + return {std::move (comp_units), std::move (type_units)}; +} + /* Write contents of a .gdb_index section for OBJFILE into OUT_FILE. If OBJFILE has an associated dwz file, write contents of a .gdb_index section for that dwz file into DWZ_OUT_FILE. If OBJFILE does not have an @@ -1299,8 +1333,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, FILE *out_file, FILE *dwz_out_file) { mapped_symtab symtab; - data_buf objfile_cu_list; - data_buf dwz_cu_list; /* While we're scanning CU's create a table that maps a dwarf2_per_cu (which is what addrmap records) to its index (which is what is recorded in the @@ -1308,40 +1340,44 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, cu_index_map cu_index_htab; cu_index_htab.reserve (per_bfd->all_units.size ()); - /* Store out the .debug_type CUs, if any. */ - data_buf types_cu_list; + auto [comp_units, type_units] = get_unit_lists (*per_bfd); + int counter = 0; - /* The CU list is already sorted, so we don't need to do additional - work here. */ + /* Write comp units. */ + data_buf objfile_cu_list; + data_buf dwz_cu_list; - int counter = 0; - for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units) + for (const dwarf2_per_cu *per_cu : comp_units) { - const auto insertpair = cu_index_htab.emplace (per_cu.get (), counter); + const auto insertpair = cu_index_htab.emplace (per_cu, counter); gdb_assert (insertpair.second); - /* See enhancement PR symtab/30838. */ - gdb_assert (!(per_cu->is_dwz && per_cu->is_debug_types)); - /* The all_units list contains CUs read from the objfile as well as from the eventual dwz file. We need to place the entry in the corresponding index. */ - data_buf &cu_list = (per_cu->is_debug_types - ? types_cu_list - : per_cu->is_dwz ? dwz_cu_list : objfile_cu_list); + data_buf &cu_list = per_cu->is_dwz ? dwz_cu_list : objfile_cu_list; cu_list.append_uint (8, BFD_ENDIAN_LITTLE, to_underlying (per_cu->sect_off)); - if (per_cu->is_debug_types) - { - signatured_type *sig_type = (signatured_type *) per_cu.get (); - cu_list.append_uint (8, BFD_ENDIAN_LITTLE, - to_underlying (sig_type->type_offset_in_tu)); - cu_list.append_uint (8, BFD_ENDIAN_LITTLE, - sig_type->signature); - } - else - cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ()); + cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ()); + ++counter; + } + + /* Write type units. */ + data_buf types_cu_list; + + for (const signatured_type *sig_type : type_units) + { + const auto insertpair = cu_index_htab.emplace (sig_type, counter); + gdb_assert (insertpair.second); + + /* See enhancement PR symtab/30838. */ + gdb_assert (!sig_type->is_dwz); + types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE, + to_underlying (sig_type->sect_off)); + types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE, + to_underlying (sig_type->type_offset_in_tu)); + types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE, sig_type->signature); ++counter; } @@ -1388,29 +1424,35 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, const enum bfd_endian dwarf5_byte_order = bfd_big_endian (per_bfd->obfd) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; - /* The CU list is already sorted, so we don't need to do additional - work here. Also, the debug_types entries do not appear in - all_units, but only in their own hash table. */ - data_buf cu_list; - data_buf types_cu_list; + auto [comp_units, type_units] = get_unit_lists (*per_bfd); debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order); - int counter = 0; - int types_counter = 0; - for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units) + data_buf comp_unit_list; + int comp_unit_counter = 0; + + for (const auto per_cu : comp_units) + { + nametable.add_cu (per_cu, comp_unit_counter); + comp_unit_list.append_uint (nametable.dwarf5_offset_size (), + dwarf5_byte_order, + to_underlying (per_cu->sect_off)); + comp_unit_counter++; + } + + data_buf type_unit_list; + int type_unit_counter = 0; + + for (const auto per_cu : type_units) { - int &this_counter = per_cu->is_debug_types ? types_counter : counter; - data_buf &this_list = per_cu->is_debug_types ? types_cu_list : cu_list; - - nametable.add_cu (per_cu.get (), this_counter); - this_list.append_uint (nametable.dwarf5_offset_size (), - dwarf5_byte_order, - to_underlying (per_cu->sect_off)); - ++this_counter; + nametable.add_cu (per_cu, type_unit_counter); + type_unit_list.append_uint (nametable.dwarf5_offset_size (), + dwarf5_byte_order, + to_underlying (per_cu->sect_off)); + type_unit_counter++; } /* Verify that all units are represented. */ - gdb_assert (counter == per_bfd->all_comp_units.size ()); - gdb_assert (types_counter == per_bfd->all_type_units.size ()); + gdb_assert (comp_unit_counter == per_bfd->num_comp_units); + gdb_assert (type_unit_counter == per_bfd->num_type_units); for (const cooked_index_entry *entry : table->all_entries ()) nametable.insert (entry); @@ -1425,8 +1467,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, + sizeof (dwarf5_augmentation_3)); size_t expected_bytes = 0; expected_bytes += bytes_of_header; - expected_bytes += cu_list.size (); - expected_bytes += types_cu_list.size (); + expected_bytes += comp_unit_list.size (); + expected_bytes += type_unit_list.size (); expected_bytes += nametable.bytes (); data_buf header; @@ -1449,11 +1491,11 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, header.append_uint (2, dwarf5_byte_order, 0); /* comp_unit_count - The number of CUs in the CU list. */ - header.append_uint (4, dwarf5_byte_order, counter); + header.append_uint (4, dwarf5_byte_order, comp_unit_counter); /* local_type_unit_count - The number of TUs in the local TU list. */ - header.append_uint (4, dwarf5_byte_order, types_counter); + header.append_uint (4, dwarf5_byte_order, type_unit_counter); /* foreign_type_unit_count - The number of TUs in the foreign TU list. */ @@ -1481,8 +1523,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, gdb_assert (header.size () == bytes_of_header); header.file_write (out_file); - cu_list.file_write (out_file); - types_cu_list.file_write (out_file); + comp_unit_list.file_write (out_file); + type_unit_list.file_write (out_file); nametable.file_write (out_file, out_file_str); assert_file_size (out_file, expected_bytes); @@ -1768,9 +1810,7 @@ gdb_index () } /* selftests namespace. */ #endif -void _initialize_dwarf_index_write (); -void -_initialize_dwarf_index_write () +INIT_GDB_FILE (dwarf_index_write) { #if GDB_SELF_TEST selftests::register_test ("gdb_index", selftests::gdb_index); diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c index de162b7..4652306 100644 --- a/gdb/dwarf2/line-header.c +++ b/gdb/dwarf2/line-header.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/unit-head.h" #include "dwarf2/leb.h" #include "dwarf2/line-header.h" #include "dwarf2/read.h" @@ -95,7 +95,7 @@ dwarf2_statement_list_fits_in_line_number_section_complaint (void) static LONGEST read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf, - const struct comp_unit_head *cu_header, + const struct unit_head *cu_header, unsigned int *bytes_read, unsigned int *offset_size) { @@ -253,11 +253,10 @@ read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd, /* See line-header.h. */ line_header_up -dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, - dwarf2_per_objfile *per_objfile, - struct dwarf2_section_info *section, - const struct comp_unit_head *cu_header, - const char *comp_dir) +dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, + dwarf2_per_objfile *per_objfile, + struct dwarf2_section_info *section, + const unit_head *cu_header, const char *comp_dir) { const gdb_byte *line_ptr; unsigned int bytes_read, offset_size; diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h index 36385b6..e6f9ea9 100644 --- a/gdb/dwarf2/line-header.h +++ b/gdb/dwarf2/line-header.h @@ -218,7 +218,7 @@ file_entry::include_dir (const line_header *lh) const extern line_header_up dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile, - struct dwarf2_section_info *section, const struct comp_unit_head *cu_header, + struct dwarf2_section_info *section, const struct unit_head *cu_header, const char *comp_dir); #endif /* GDB_DWARF2_LINE_HEADER_H */ diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index e1a5fdd..37c85d8 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1732,11 +1732,10 @@ dwarf2_evaluate_property (const dynamic_prop *prop, *value = prop->const_val (); return true; - case PROP_ADDR_OFFSET: + case PROP_FIELD: { const dwarf2_property_baton *baton = prop->baton (); const struct property_addr_info *pinfo; - struct value *val; for (pinfo = addr_stack; pinfo != NULL; pinfo = pinfo->next) { @@ -1747,14 +1746,40 @@ dwarf2_evaluate_property (const dynamic_prop *prop, } if (pinfo == NULL) error (_("cannot find reference address for offset property")); - if (pinfo->valaddr.data () != NULL) - val = value_from_contents - (baton->offset_info.type, - pinfo->valaddr.data () + baton->offset_info.offset); - else - val = value_at (baton->offset_info.type, - pinfo->addr + baton->offset_info.offset); - *value = value_as_address (val); + + struct field resolved_field = baton->field; + resolve_dynamic_field (resolved_field, pinfo, initial_frame); + + /* Storage for memory if we need to read it. */ + gdb::byte_vector memory; + const gdb_byte *bytes = pinfo->valaddr.data (); + if (bytes == nullptr) + { + int bitpos = resolved_field.loc_bitpos (); + int bitsize = resolved_field.bitsize (); + if (bitsize == 0) + bitsize = check_typedef (resolved_field.type ())->length () * 8; + + /* Read just the minimum number of bytes needed to satisfy + unpack_field_as_long. So, update the resolved field's + starting offset to remove any unnecessary leading + bytes. */ + int byte_offset = bitpos / 8; + + bitpos %= 8; + resolved_field.set_loc_bitpos (bitpos); + + /* Make sure to include any remaining bit offset in the + size computation, in case the value straddles a + byte. */ + int byte_length = align_up (bitsize + bitpos, 8) / 8; + memory.resize (byte_length); + + read_memory (pinfo->addr + byte_offset, memory.data (), + byte_length); + bytes = memory.data (); + } + *value = unpack_field_as_long (bytes, &resolved_field); return true; } @@ -4129,9 +4154,7 @@ const struct symbol_computed_ops dwarf2_loclist_funcs = { loclist_generate_c_location }; -void _initialize_dwarf2loc (); -void -_initialize_dwarf2loc () +INIT_GDB_FILE (dwarf2loc) { add_setshow_zuinteger_cmd ("entry-values", class_maintenance, &entry_values_debug, diff --git a/gdb/dwarf2/loc.h b/gdb/dwarf2/loc.h index 30c528b..c672320 100644 --- a/gdb/dwarf2/loc.h +++ b/gdb/dwarf2/loc.h @@ -20,6 +20,7 @@ #ifndef GDB_DWARF2_LOC_H #define GDB_DWARF2_LOC_H +#include "gdbtypes.h" #include "dwarf2/expr.h" struct symbol_computed_ops; @@ -99,31 +100,9 @@ struct property_addr_info /* If not NULL, a pointer to the info for the object containing the object described by this node. */ - struct property_addr_info *next; + const property_addr_info *next; }; -/* Converts a dynamic property into a static one. FRAME is the frame in which - the property is evaluated; if NULL, the selected frame (if any) is used - instead. - - ADDR_STACK is the stack of addresses that might be needed to evaluate the - property. When evaluating a property that is not related to a type, it can - be NULL. - - Returns true if PROP could be converted and the static value is passed - back into VALUE, otherwise returns false. - - Any values in PUSH_VALUES will be pushed before evaluating the location - expression, PUSH_VALUES[0] will be pushed first, then PUSH_VALUES[1], - etc. This means the during evaluation PUSH_VALUES[0] will be at the - bottom of the stack. */ - -bool dwarf2_evaluate_property (const struct dynamic_prop *prop, - const frame_info_ptr &frame, - const property_addr_info *addr_stack, - CORE_ADDR *value, - gdb::array_view<CORE_ADDR> push_values = {}); - /* A helper for the compiler interface that compiles a single dynamic property to C code. @@ -167,6 +146,9 @@ struct dwarf2_locexpr_baton directly. */ bool is_reference; + /* True if this object is actually a dwarf2_field_location_baton. */ + bool is_field_location; + /* The objfile that was used when creating this. */ dwarf2_per_objfile *per_objfile; @@ -175,6 +157,23 @@ struct dwarf2_locexpr_baton dwarf2_per_cu *per_cu; }; +/* If the DWARF location for a field used DW_AT_bit_size, then an + object of this type is created to represent the field location. + This is then used to apply the bit offset after computing the + field's byte offset. Objects of this type always set the + 'is_field_location' member in dwarf2_locexpr_baton. See also + apply_bit_offset_to_field. */ + +struct dwarf2_field_location_baton : public dwarf2_locexpr_baton +{ + /* The bit offset, coming from DW_AT_bit_offset. */ + LONGEST bit_offset; + + /* The DW_AT_byte_size of the field. If no explicit byte size was + specified, this is 0. */ + LONGEST explicit_byte_size; +}; + struct dwarf2_loclist_baton { /* The initial base address for the location list, based on the compilation @@ -202,23 +201,6 @@ struct dwarf2_loclist_baton unsigned char dwarf_version; }; -/* The baton used when a dynamic property is an offset to a parent - type. This can be used, for instance, then the bound of an array - inside a record is determined by the value of another field inside - that record. */ - -struct dwarf2_offset_baton -{ - /* The offset from the parent type where the value of the property - is stored. In the example provided above, this would be the offset - of the field being used as the array bound. */ - LONGEST offset; - - /* The type of the object whose property is dynamic. In the example - provided above, this would the array's index type. */ - struct type *type; -}; - /* A dynamic property is either expressed as a single location expression or a location list. If the property is an indirection, pointing to another die, keep track of the targeted type in PROPERTY_TYPE. @@ -241,8 +223,8 @@ struct dwarf2_property_baton /* Location list to be evaluated in the context of PROPERTY_TYPE. */ struct dwarf2_loclist_baton loclist; - /* The location is an offset to PROPERTY_TYPE. */ - struct dwarf2_offset_baton offset_info; + /* The location is stored in a field of PROPERTY_TYPE. */ + struct field field; }; }; @@ -307,8 +289,53 @@ extern struct value *indirect_synthetic_pointer Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if it cannot resolve the parameter for any reason. */ +#if defined(DWARF_FORMAT_AVAILABLE) + +/* Converts a dynamic property into a static one. FRAME is the frame in which + the property is evaluated; if NULL, the selected frame (if any) is used + instead. + + ADDR_STACK is the stack of addresses that might be needed to evaluate the + property. When evaluating a property that is not related to a type, it can + be NULL. + + Returns true if PROP could be converted and the static value is passed + back into VALUE, otherwise returns false. + + Any values in PUSH_VALUES will be pushed before evaluating the location + expression, PUSH_VALUES[0] will be pushed first, then PUSH_VALUES[1], + etc. This means the during evaluation PUSH_VALUES[0] will be at the + bottom of the stack. */ + +bool dwarf2_evaluate_property (const struct dynamic_prop *prop, + const frame_info_ptr &frame, + const property_addr_info *addr_stack, + CORE_ADDR *value, + gdb::array_view<CORE_ADDR> push_values = {}); + extern struct value *value_of_dwarf_reg_entry (struct type *type, const frame_info_ptr &frame, enum call_site_parameter_kind kind, union call_site_parameter_u kind_u); + +#else /* DWARF_FORMAT_AVAILABLE */ + +static inline bool +dwarf2_evaluate_property (const struct dynamic_prop *, const frame_info_ptr &, + const property_addr_info *, CORE_ADDR *, + gdb::array_view<CORE_ADDR> = {}) +{ + return false; +} + +static inline struct value * +value_of_dwarf_reg_entry (struct type *type, const frame_info_ptr &frame, + enum call_site_parameter_kind kind, + union call_site_parameter_u kind_u) +{ + error (_("No dwarf support available.")); +} + +#endif /* DWARF_FORMAT_AVAILABLE */ + #endif /* GDB_DWARF2_LOC_H */ diff --git a/gdb/dwarf2/public.h b/gdb/dwarf2/public.h index ed504c6..f9e7488 100644 --- a/gdb/dwarf2/public.h +++ b/gdb/dwarf2/public.h @@ -30,6 +30,8 @@ enum class dw_index_kind DEBUG_NAMES, }; +#if defined(DWARF_FORMAT_AVAILABLE) + /* Try to locate the sections we need for DWARF 2 debugging information. If these are found, begin reading the DWARF and return true. Otherwise, return false. NAMES points to the dwarf2 @@ -44,4 +46,27 @@ extern bool dwarf2_initialize_objfile extern void dwarf2_build_frame_info (struct objfile *); +/* Append the DWARF-2 frame unwinders to GDBARCH's list. */ + +void dwarf2_append_unwinders (struct gdbarch *gdbarch); + +#else /* DWARF_FORMAT_AVAILABLE */ + +static inline bool +dwarf2_initialize_objfile (struct objfile *, + const struct dwarf2_debug_sections * = nullptr, + bool = false) +{ + warning (_("No dwarf support available.")); + return false; +} + +static inline void +dwarf2_build_frame_info (struct objfile *) +{ + warning (_("No dwarf support available.")); +} + +#endif /* DWARF_FORMAT_AVAILABLE */ + #endif /* GDB_DWARF2_PUBLIC_H */ diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c index 11de986..ddf4935 100644 --- a/gdb/dwarf2/read-debug-names.c +++ b/gdb/dwarf2/read-debug-names.c @@ -114,6 +114,14 @@ struct mapped_debug_names_reader gdb::unordered_map<ULONGEST, index_val> abbrev_map; + /* List of CUs in the same order as found in the index header (DWARF 5 section + 6.1.1.4.2). */ + std::vector<dwarf2_per_cu *> comp_units; + + /* List of local TUs in the same order as found in the index (DWARF 5 section + 6.1.1.4.3). */ + std::vector<dwarf2_per_cu *> type_units; + /* Even though the scanning of .debug_names and creation of the cooked index entries is done serially, we create multiple shards so that the finalization step can be parallelized. The shards @@ -232,7 +240,7 @@ mapped_debug_names_reader::scan_one_entry (const char *name, case DW_IDX_compile_unit: { /* Don't crash on bad data. */ - if (ull >= per_objfile->per_bfd->all_comp_units.size ()) + if (ull >= this->comp_units.size ()) { complaint (_(".debug_names entry has bad CU index %s" " [in module %s]"), @@ -240,30 +248,31 @@ mapped_debug_names_reader::scan_one_entry (const char *name, bfd_get_filename (abfd)); continue; } + + per_cu = this->comp_units[ull]; + break; } - per_cu = per_objfile->per_bfd->get_cu (ull); - break; case DW_IDX_type_unit: - /* Don't crash on bad data. */ - if (ull >= per_objfile->per_bfd->all_type_units.size ()) - { - complaint (_(".debug_names entry has bad TU index %s" - " [in module %s]"), - pulongest (ull), - bfd_get_filename (abfd)); - continue; - } { - int nr_cus = per_objfile->per_bfd->all_comp_units.size (); - per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull); + /* Don't crash on bad data. */ + if (ull >= this->type_units.size ()) + { + complaint (_(".debug_names entry has bad TU index %s" + " [in module %s]"), + pulongest (ull), + bfd_get_filename (abfd)); + continue; + } + + per_cu = this->type_units[ull]; + break; } - break; case DW_IDX_die_offset: die_offset = sect_offset (ull); /* In a per-CU index (as opposed to a per-module index), index entries without CU attribute implicitly refer to the single CU. */ - if (per_cu == NULL) - per_cu = per_objfile->per_bfd->get_cu (0); + if (per_cu == nullptr) + per_cu = this->comp_units[0]; break; case DW_IDX_parent: parent = ull; @@ -416,15 +425,11 @@ cooked_index_worker_debug_names::do_reading () { complaint_interceptor complaint_handler; - try + /* Arbitrarily put all exceptions into the first result. */ + m_map.indices[0].catch_error ([&] () { m_map.scan_all_names (); - } - catch (gdb_exception &exc) - { - /* Arbitrarily put all exceptions into the first result. */ - m_map.indices[0].note_error (std::move (exc)); - } + }); bool first = true; for (auto &iter : m_map.indices) @@ -444,45 +449,45 @@ cooked_index_worker_debug_names::do_reading () bfd_thread_cleanup (); } -/* Check the signatured type hash table from .debug_names. */ +/* Build the list of TUs (mapped_debug_names_reader::type_units) from the index + header and verify that it matches the list of TUs read from the DIEs in + `.debug_info`. + + Return true if they match, false otherwise. */ static bool -check_signatured_type_table_from_debug_names - (dwarf2_per_objfile *per_objfile, - const mapped_debug_names_reader &map, - struct dwarf2_section_info *section) +build_and_check_tu_list_from_debug_names (dwarf2_per_objfile *per_objfile, + mapped_debug_names_reader &map, + dwarf2_section_info *section) { struct objfile *objfile = per_objfile->objfile; dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - int nr_cus = per_bfd->all_comp_units.size (); - int nr_cus_tus = per_bfd->all_units.size (); section->read (objfile); - uint32_t j = nr_cus; for (uint32_t i = 0; i < map.tu_count; ++i) { + /* Read one entry from the TU list. */ sect_offset sect_off = (sect_offset) (extract_unsigned_integer (map.tu_table_reordered + i * map.offset_size, map.offset_size, map.dwarf5_byte_order)); - bool found = false; - for (; j < nr_cus_tus; j++) - if (per_bfd->get_cu (j)->sect_off == sect_off) - { - found = true; - break; - } - if (!found) + /* Find the matching dwarf2_per_cu. */ + dwarf2_per_cu *per_cu = dwarf2_find_unit ({ section, sect_off }, + per_bfd); + + if (per_cu == nullptr || !per_cu->is_debug_types) { warning (_("Section .debug_names has incorrect entry in TU table," " ignoring .debug_names.")); return false; } - per_bfd->all_comp_units_index_tus.push_back (per_bfd->get_cu (j)); + + map.type_units.emplace_back (per_cu); } + return true; } @@ -704,40 +709,11 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile, list. */ static bool -check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd, - const mapped_debug_names_reader &map, - dwarf2_section_info §ion, - bool is_dwz) +build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd, + mapped_debug_names_reader &map, + dwarf2_section_info §ion) { - int nr_cus = per_bfd->all_comp_units.size (); - - if (!map.augmentation_is_gdb) - { - uint32_t j = 0; - for (uint32_t i = 0; i < map.cu_count; ++i) - { - sect_offset sect_off - = (sect_offset) (extract_unsigned_integer - (map.cu_table_reordered + i * map.offset_size, - map.offset_size, - map.dwarf5_byte_order)); - bool found = false; - for (; j < nr_cus; j++) - if (per_bfd->get_cu (j)->sect_off == sect_off) - { - found = true; - break; - } - if (!found) - { - warning (_("Section .debug_names has incorrect entry in CU table," - " ignoring .debug_names.")); - return false; - } - per_bfd->all_comp_units_index_cus.push_back (per_bfd->get_cu (j)); - } - return true; - } + int nr_cus = per_bfd->num_comp_units; if (map.cu_count != nr_cus) { @@ -753,43 +729,51 @@ check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd, (map.cu_table_reordered + i * map.offset_size, map.offset_size, map.dwarf5_byte_order)); - if (sect_off != per_bfd->get_cu (i)->sect_off) + + /* Find the matching dwarf2_per_cu. */ + dwarf2_per_cu *per_cu = dwarf2_find_unit ({ §ion, sect_off }, per_bfd); + + if (per_cu == nullptr || per_cu->is_debug_types) { warning (_("Section .debug_names has incorrect entry in CU table," " ignoring .debug_names.")); return false; } + + map.comp_units.emplace_back (per_cu); } return true; } -/* Read the CU list from the mapped index, and use it to create all - the CU objects for this dwarf2_per_objfile. */ +/* Build the list of CUs (mapped_debug_names_reader::compile_units) from the + index header and verify that it matches the list of CUs read from the DIEs in + `.debug_info`. + + Return true if they match, false otherwise. */ static bool -check_cus_from_debug_names (dwarf2_per_bfd *per_bfd, - const mapped_debug_names_reader &map, - const mapped_debug_names_reader &dwz_map) +build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd, + mapped_debug_names_reader &map, + mapped_debug_names_reader &dwz_map) { - if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->infos[0], - false /* is_dwz */)) + if (!build_and_check_cu_list_from_debug_names (per_bfd, map, + per_bfd->infos[0])) return false; if (dwz_map.cu_count == 0) return true; dwz_file *dwz = per_bfd->get_dwz_file (); - return check_cus_from_debug_names_list (per_bfd, dwz_map, dwz->info, - true /* is_dwz */); + return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info); } -/* This does all the work for dwarf2_read_debug_names, but putting it - into a separate function makes some cleanup a bit simpler. */ +/* See read-debug-names.h. */ -static bool -do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) +bool +dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) { + scoped_remove_all_units remove_all_units (*per_objfile->per_bfd); mapped_debug_names_reader map; mapped_debug_names_reader dwz_map; struct objfile *objfile = per_objfile->objfile; @@ -819,7 +803,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) } create_all_units (per_objfile); - if (!check_cus_from_debug_names (per_bfd, map, dwz_map)) + if (!build_and_check_cu_lists_from_debug_names (per_bfd, map, dwz_map)) return false; if (map.tu_count != 0) @@ -835,8 +819,8 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) ? &per_bfd->types[0] : &per_bfd->infos[0]); - if (!check_signatured_type_table_from_debug_names (per_objfile, - map, section)) + if (!build_and_check_tu_list_from_debug_names (per_objfile, map, + section)) return false; } @@ -866,17 +850,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) (per_objfile, std::move (map))); auto idx = std::make_unique<debug_names_index> (std::move (cidn)); per_bfd->start_reading (std::move (idx)); + remove_all_units.disable (); return true; } - -/* See read-debug-names.h. */ - -bool -dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) -{ - bool result = do_dwarf2_read_debug_names (per_objfile); - if (!result) - per_objfile->per_bfd->all_units.clear (); - return result; -} diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c index 2029c3e..fc7b654 100644 --- a/gdb/dwarf2/read-gdb-index.c +++ b/gdb/dwarf2/read-gdb-index.c @@ -117,6 +117,10 @@ struct mapped_gdb_index : public dwarf_scanner_base /* Index data format version. */ int version = 0; + /* Compile units followed by type units, in the order as found in the + index. Indices found in index entries can index directly into this. */ + std::vector<dwarf2_per_cu *> units; + /* The address table data. */ gdb::array_view<const gdb_byte> address_table; @@ -1106,14 +1110,14 @@ dw2_expand_marked_cus (dwarf2_per_objfile *per_objfile, offset_type idx, } /* Don't crash on bad data. */ - if (cu_index >= per_objfile->per_bfd->all_units.size ()) + if (cu_index >= index.units.size ()) { complaint (_(".gdb_index entry has bad CU index" " [in module %s]"), objfile_name (per_objfile->objfile)); continue; } - dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (cu_index); + dwarf2_per_cu *per_cu = index.units[cu_index]; if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, expansion_notify, lang_matcher)) @@ -1313,7 +1317,7 @@ static void create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd, const gdb_byte *cu_list, offset_type n_elements, struct dwarf2_section_info *section, - int is_dwz) + int is_dwz, std::vector<dwarf2_per_cu *> &units) { for (offset_type i = 0; i < n_elements; i += 2) { @@ -1324,10 +1328,10 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd, ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); cu_list += 2 * 8; - per_bfd->all_units.emplace_back (per_bfd->allocate_per_cu (section, - sect_off, - length, - is_dwz)); + dwarf2_per_cu_up per_cu = per_bfd->allocate_per_cu (section, sect_off, + length, is_dwz); + units.emplace_back (per_cu.get ()); + per_bfd->all_units.emplace_back (std::move (per_cu)); } } @@ -1337,20 +1341,21 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd, static void create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd, const gdb_byte *cu_list, offset_type cu_list_elements, + std::vector<dwarf2_per_cu *> &units, const gdb_byte *dwz_list, offset_type dwz_elements) { gdb_assert (per_bfd->all_units.empty ()); per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2); create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements, - &per_bfd->infos[0], 0); + &per_bfd->infos[0], 0, units); if (dwz_elements == 0) return; dwz_file *dwz = per_bfd->get_dwz_file (); create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements, - &dwz->info, 1); + &dwz->info, 1, units); } /* Create the signatured type hash table from the index. */ @@ -1358,7 +1363,8 @@ create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd, static void create_signatured_type_table_from_gdb_index (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section, - const gdb_byte *bytes, offset_type elements) + const gdb_byte *bytes, offset_type elements, + std::vector<dwarf2_per_cu *> &units) { signatured_type_set sig_types_hash; @@ -1382,6 +1388,7 @@ create_signatured_type_table_from_gdb_index sig_type->type_offset_in_tu = type_offset_in_tu; sig_types_hash.emplace (sig_type.get ()); + units.emplace_back (sig_type.get ()); per_bfd->all_units.emplace_back (sig_type.release ()); } @@ -1412,21 +1419,21 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile, cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); iter += 4; - if (lo > hi) + if (lo >= hi) { complaint (_(".gdb_index address table has invalid range (%s - %s)"), hex_string (lo), hex_string (hi)); continue; } - if (cu_index >= per_bfd->all_units.size ()) + if (cu_index >= index->units.size ()) { complaint (_(".gdb_index address table has invalid CU number %u"), (unsigned) cu_index); continue; } - mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index)); + mutable_map.set_empty (lo, hi - 1, index->units[cu_index]); } index->index_addrmap @@ -1482,6 +1489,7 @@ dwarf2_read_gdb_index offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; struct objfile *objfile = per_objfile->objfile; dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + scoped_remove_all_units remove_all_units (*per_bfd); gdb::array_view<const gdb_byte> main_index_contents = get_gdb_index_contents (objfile, per_bfd); @@ -1528,8 +1536,8 @@ dwarf2_read_gdb_index } } - create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list, - dwz_list_elements); + create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, map->units, + dwz_list, dwz_list_elements); if (types_list_elements) { @@ -1537,10 +1545,7 @@ dwarf2_read_gdb_index an index. */ if (per_bfd->infos.size () > 1 || per_bfd->types.size () > 1) - { - per_bfd->all_units.clear (); - return false; - } + return false; dwarf2_section_info *section = (per_bfd->types.size () == 1 @@ -1548,7 +1553,8 @@ dwarf2_read_gdb_index : &per_bfd->infos[0]); create_signatured_type_table_from_gdb_index (per_bfd, section, types_list, - types_list_elements); + types_list_elements, + map->units); } finalize_all_units (per_bfd); @@ -1558,14 +1564,12 @@ dwarf2_read_gdb_index set_main_name_from_gdb_index (per_objfile, map.get ()); per_bfd->index_table = std::move (map); + remove_all_units.disable (); return true; } -void _initialize_read_gdb_index (); - -void -_initialize_read_gdb_index () +INIT_GDB_FILE (read_gdb_index) { add_setshow_boolean_cmd ("use-deprecated-index-sections", no_class, &use_deprecated_index_sections, _("\ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 7b019f9..29650c5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -31,7 +31,7 @@ #include "dwarf2/abbrev.h" #include "dwarf2/aranges.h" #include "dwarf2/attribute.h" -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/unit-head.h" #include "dwarf2/cooked-index-worker.h" #include "dwarf2/cooked-indexer.h" #include "dwarf2/cu.h" @@ -52,6 +52,7 @@ #include "event-top.h" #include "exceptions.h" #include "gdbsupport/task-group.h" +#include "maint.h" #include "symtab.h" #include "gdbtypes.h" #include "objfiles.h" @@ -146,7 +147,7 @@ static const registry<bfd>::key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key; static const registry<objfile>::key<dwarf2_per_bfd> dwarf2_per_bfd_objfile_data_key; -/* The "aclass" indices for various kinds of computed DWARF symbols. */ +/* The "loc_class" indices for various kinds of computed DWARF symbols. */ static int dwarf2_locexpr_index; static int dwarf2_loclist_index; @@ -279,7 +280,7 @@ struct dwo_sections struct dwarf2_section_info str; struct dwarf2_section_info str_offsets; /* In the case of a virtual DWO file, these two are unused. */ - struct dwarf2_section_info info; + std::vector<dwarf2_section_info> infos; std::vector<dwarf2_section_info> types; }; @@ -288,24 +289,29 @@ struct dwo_sections struct dwo_unit { /* Backlink to the containing struct dwo_file. */ - struct dwo_file *dwo_file; + struct dwo_file *dwo_file = nullptr; /* The "id" that distinguishes this CU/TU. .debug_info calls this "dwo_id", .debug_types calls this "signature". Since signatures came first, we stick with it for consistency. */ - ULONGEST signature; + ULONGEST signature = 0; /* The section this CU/TU lives in, in the DWO file. */ - struct dwarf2_section_info *section; + dwarf2_section_info *section = nullptr; + + /* This is set if SECTION is owned by this dwo_unit. */ + dwarf2_section_info_up section_holder; /* Same as dwarf2_per_cu::{sect_off,length} but in the DWO section. */ - sect_offset sect_off; - unsigned int length; + sect_offset sect_off {}; + unsigned int length = 0; /* For types, offset in the type's DIE of the type defined by this TU. */ cu_offset type_offset_in_tu; }; +using dwo_unit_up = std::unique_ptr<dwo_unit>; + /* Hash function for dwo_unit objects, based on the signature. */ struct dwo_unit_hash @@ -315,7 +321,7 @@ struct dwo_unit_hash std::size_t operator() (ULONGEST signature) const noexcept { return signature; } - std::size_t operator() (const dwo_unit *unit) const noexcept + std::size_t operator() (const dwo_unit_up &unit) const noexcept { return (*this) (unit->signature); } }; @@ -329,16 +335,16 @@ struct dwo_unit_eq { using is_transparent = void; - bool operator() (ULONGEST sig, const dwo_unit *unit) const noexcept + bool operator() (ULONGEST sig, const dwo_unit_up &unit) const noexcept { return sig == unit->signature; } - bool operator() (const dwo_unit *a, const dwo_unit *b) const noexcept + bool operator() (const dwo_unit_up &a, const dwo_unit_up &b) const noexcept { return (*this) (a->signature, b); } }; /* Set of dwo_unit object, using their signature as identity. */ -using dwo_unit_set = gdb::unordered_set<dwo_unit *, dwo_unit_hash, dwo_unit_eq>; +using dwo_unit_set = gdb::unordered_set<dwo_unit_up, dwo_unit_hash, dwo_unit_eq>; /* include/dwarf2.h defines the DWP section codes. It defines a max value but it doesn't define a min value, which we @@ -598,6 +604,11 @@ struct dwp_file dwo_unit_set loaded_cus; dwo_unit_set loaded_tus; +#if CXX_STD_THREAD + /* Mutex to synchronize access to LOADED_CUS and LOADED_TUS. */ + std::mutex loaded_cutus_lock; +#endif + /* Table to map ELF section numbers to their sections. This is only needed for the DWP V1 file format. */ unsigned int num_sections = 0; @@ -622,15 +633,21 @@ struct variant_field /* A variant can contain other variant parts. */ std::vector<variant_part_builder> variant_parts; - /* If we see a DW_TAG_variant, then this will be set if this is the - default branch. */ - bool default_branch = false; /* If we see a DW_AT_discr_value, then this will be the discriminant - value. */ - ULONGEST discriminant_value = 0; + value. Just the attribute is stored here, because we have to + defer deciding whether the value is signed or unsigned until the + end. */ + const attribute *discriminant_attr = nullptr; /* If we see a DW_AT_discr_list, then this is a pointer to the list data. */ struct dwarf_block *discr_list_data = nullptr; + + /* If both DW_AT_discr_value and DW_AT_discr_list are absent, then + this is the default branch. */ + bool is_default () const + { + return discriminant_attr == nullptr && discr_list_data == nullptr; + } }; /* This represents a DW_TAG_variant_part. */ @@ -727,9 +744,6 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty, /* local function prototypes */ -static void build_type_psymtabs_reader (cutu_reader *reader, - cooked_index_worker_result *storage); - static void var_decode_location (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu); @@ -742,9 +756,9 @@ static unrelocated_addr read_addr_index (struct dwarf2_cu *cu, static sect_offset read_abbrev_offset (dwarf2_per_objfile *per_objfile, dwarf2_section_info *, sect_offset); -static const char *read_indirect_string - (dwarf2_per_objfile *per_objfile, bfd *, const gdb_byte *, - const struct comp_unit_head *, unsigned int *); +static const char *read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *, + const gdb_byte *, const unit_head *, + unsigned int *); static unrelocated_addr read_addr_index_from_leb128 (struct dwarf2_cu *, const gdb_byte *, @@ -1318,7 +1332,7 @@ dwarf2_per_bfd::locate_sections (asection *sectp, bfd_size_type size = sectp->size; warning (_("Discarding section %s which has an invalid size (%s) " "[in module %s]"), - bfd_section_name (sectp), phex_nz (size, sizeof (size)), + bfd_section_name (sectp), phex_nz (size), this->filename ()); } else if (names.info.matches (sectp->name)) @@ -1676,6 +1690,7 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section, dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off, length, is_dwz)); result->index = all_units.size (); + this->num_comp_units++; return result; } @@ -1692,7 +1707,7 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section, = std::make_unique<signatured_type> (this, section, sect_off, length, is_dwz, signature); result->index = all_units.size (); - tu_stats.nr_tus++; + this->num_type_units++; return result; } @@ -1887,13 +1902,13 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile, for (int i = 0; i < total; ++i) { - dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (i); + dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_unit (i); if (!per_objfile->symtab_set_p (per_cu)) ++count; } - gdb_printf (_(" Number of read CUs: %d\n"), total - count); - gdb_printf (_(" Number of unread CUs: %d\n"), count); + gdb_printf (_(" Number of read units: %d\n"), total - count); + gdb_printf (_(" Number of unread units: %d\n"), count); } void @@ -2356,6 +2371,24 @@ get_abbrev_section_for_cu (dwarf2_per_cu *this_cu) return abbrev; } +/* "less than" function used to both sort and bisect units in the + `dwarf2_per_bfd::all_units` vector. Return true if the LHS CU comes before + (is "less" than) the section and offset in RHS. + + For simplicity, sort sections by their pointer. This is not ideal, because + it can cause the behavior to change across runs, making some bugs harder to + investigate. An improvement would be for sections to be sorted by their + properties. */ + +static bool +all_units_less_than (const dwarf2_per_cu &lhs, const section_and_offset &rhs) +{ + if (lhs.section != rhs.section) + return lhs.section < rhs.section; + + return lhs.sect_off < rhs.offset; +} + /* Fetch the abbreviation table offset from a comp or type unit header. */ static sect_offset @@ -2385,109 +2418,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile, return (sect_offset) read_offset (abfd, info_ptr, offset_size); } -/* A helper for create_dwo_debug_types_hash_table. Read types from SECTION - and fill them into DWO_FILE's type unit hash table. It will process only - type units, therefore DW_UT_type. */ - -void -cutu_reader::create_dwo_debug_type_hash_table (dwarf2_per_bfd *per_bfd, - dwo_file *dwo_file, - dwarf2_section_info *section, - rcuh_kind section_kind) -{ - struct dwarf2_section_info *abbrev_section; - bfd *abfd; - const gdb_byte *info_ptr, *end_ptr; - - abbrev_section = &dwo_file->sections.abbrev; - - dwarf_read_debug_printf ("Reading %s for %s", - section->get_name (), - abbrev_section->get_file_name ()); - - info_ptr = section->buffer; - - if (info_ptr == NULL) - return; - - /* We can't set abfd until now because the section may be empty or - not present, in which case the bfd is unknown. */ - abfd = section->get_bfd_owner (); - - /* We don't use cutu_reader here because we don't need to read - any dies: the signature is in the header. */ - - end_ptr = info_ptr + section->size; - while (info_ptr < end_ptr) - { - const gdb_byte *ptr = info_ptr; - struct comp_unit_head header; - unsigned int length; - - sect_offset sect_off = (sect_offset) (ptr - section->buffer); - - /* Initialize it due to a false compiler warning. */ - header.signature = -1; - header.type_cu_offset_in_tu = (cu_offset) -1; - - /* We need to read the type's signature in order to build the hash - table, but we don't need anything else just yet. */ - - ptr = read_and_check_comp_unit_head (&header, section, abbrev_section, - ptr, section_kind); - - length = header.get_length_with_initial (); - - /* Skip dummy type units. */ - if (ptr >= info_ptr + length - || peek_abbrev_code (abfd, ptr) == 0 - || (header.unit_type != DW_UT_type - && header.unit_type != DW_UT_split_type)) - { - info_ptr += length; - continue; - } - - dwo_unit *dwo_tu = OBSTACK_ZALLOC (&per_bfd->obstack, dwo_unit); - dwo_tu->dwo_file = dwo_file; - dwo_tu->signature = header.signature; - dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu; - dwo_tu->section = section; - dwo_tu->sect_off = sect_off; - dwo_tu->length = length; - - auto [it, inserted] = dwo_file->tus.emplace (dwo_tu); - if (!inserted) - complaint (_("debug type entry at offset %s is duplicate to" - " the entry at offset %s, signature %s"), - sect_offset_str (sect_off), - sect_offset_str ((*it)->sect_off), - hex_string (header.signature)); - - dwarf_read_debug_printf_v (" offset %s, signature %s", - sect_offset_str (sect_off), - hex_string (header.signature)); - - info_ptr += length; - } -} - -/* Create the hash table of all entries in the .debug_types - (or .debug_types.dwo) section(s). - DWO_FILE is a pointer to the DWO file object. - - Note: This function processes DWO files only, not DWP files. */ - -void -cutu_reader::create_dwo_debug_types_hash_table - (dwarf2_per_bfd *per_bfd, dwo_file *dwo_file, - gdb::array_view<dwarf2_section_info> type_sections) -{ - for (dwarf2_section_info §ion : type_sections) - create_dwo_debug_type_hash_table (per_bfd, dwo_file, §ion, - rcuh_kind::TYPE); -} - /* Add an entry for signature SIG to per_bfd->signatured_types. */ static signatured_type_set::iterator @@ -2502,7 +2432,17 @@ add_type_unit (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section, false /* is_dwz */, sig); signatured_type *sig_type = sig_type_holder.get (); - per_bfd->all_units.emplace_back (sig_type_holder.release ()); + /* Preserve the ordering of per_bfd->all_units. */ + auto insert_it + = std::lower_bound (per_bfd->all_units.begin (), per_bfd->all_units.end (), + sig_type, + [] (const dwarf2_per_cu_up &lhs, + const signatured_type *rhs) { + return all_units_less_than (*lhs, { rhs->section, + rhs->sect_off }); + }); + + per_bfd->all_units.emplace (insert_it, sig_type_holder.release ()); auto emplace_ret = per_bfd->signatured_types.emplace (sig_type); /* Assert that an insertion took place - that there wasn't a type unit with @@ -2586,7 +2526,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) if (it == dwo_file->tus.end ()) return nullptr; - dwo_unit *dwo_entry = *it; + dwo_unit *dwo_entry = it->get (); /* If the global table doesn't have an entry for this TU, add one. */ if (sig_type_it == per_bfd->signatured_types.end ()) @@ -2789,9 +2729,9 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, { signatured_type *sig_type = (struct signatured_type *) per_cu; - m_info_ptr = read_and_check_comp_unit_head (&cu->header, section, - dwo_abbrev_section, - m_info_ptr, rcuh_kind::TYPE); + m_info_ptr = read_and_check_unit_head (&cu->header, section, + dwo_abbrev_section, m_info_ptr, + ruh_kind::TYPE); /* This is not an assert because it can be caused by bad debug info. */ if (sig_type->signature != cu->header.signature) @@ -2808,7 +2748,7 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, /* For DWOs coming from DWP files, we don't know the CU length nor the type's offset in the TU until now. */ dwo_unit->length = cu->header.get_length_with_initial (); - dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu; + dwo_unit->type_offset_in_tu = cu->header.type_offset_in_tu; /* Establish the type offset that can be used to lookup the type. For DWO files, we don't know it until now. */ @@ -2817,10 +2757,9 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, } else { - m_info_ptr - = read_and_check_comp_unit_head (&cu->header, section, - dwo_abbrev_section, m_info_ptr, - rcuh_kind::COMPILE); + m_info_ptr = read_and_check_unit_head (&cu->header, section, + dwo_abbrev_section, m_info_ptr, + ruh_kind::COMPILE); gdb_assert (dwo_unit->sect_off == cu->header.sect_off); /* For DWOs coming from DWP files, we don't know the CU length until now. */ @@ -2877,13 +2816,6 @@ dwo_unit * cutu_reader::lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name) { -#if CXX_STD_THREAD - /* We need a lock here to handle the DWO hash table. */ - static std::mutex dwo_lock; - - std::lock_guard<std::mutex> guard (dwo_lock); -#endif - dwarf2_per_cu *per_cu = cu->per_cu; struct dwo_unit *dwo_unit; const char *comp_dir; @@ -3038,26 +2970,26 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, } /* Get the header. */ - if (to_underlying (cu->header.first_die_cu_offset) != 0 && !rereading_dwo_cu) + if (to_underlying (cu->header.first_die_offset_in_unit) != 0 + && !rereading_dwo_cu) { /* We already have the header, there's no need to read it in again. */ - m_info_ptr += to_underlying (cu->header.first_die_cu_offset); + m_info_ptr += to_underlying (cu->header.first_die_offset_in_unit); } else { if (this_cu.is_debug_types) { - m_info_ptr - = read_and_check_comp_unit_head (&cu->header, section, - abbrev_section, m_info_ptr, - rcuh_kind::TYPE); + m_info_ptr = read_and_check_unit_head (&cu->header, section, + abbrev_section, m_info_ptr, + ruh_kind::TYPE); /* Since per_cu is the first member of struct signatured_type, we can go from a pointer to one to a pointer to the other. */ sig_type = (struct signatured_type *) &this_cu; gdb_assert (sig_type->signature == cu->header.signature); gdb_assert (sig_type->type_offset_in_tu - == cu->header.type_cu_offset_in_tu); + == cu->header.type_offset_in_tu); gdb_assert (this_cu.sect_off == cu->header.sect_off); /* LENGTH has not been set yet for type units if we're @@ -3070,10 +3002,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, } else { - m_info_ptr - = read_and_check_comp_unit_head (&cu->header, section, - abbrev_section, m_info_ptr, - rcuh_kind::COMPILE); + m_info_ptr = read_and_check_unit_head (&cu->header, section, + abbrev_section, m_info_ptr, + ruh_kind::COMPILE); gdb_assert (this_cu.sect_off == cu->header.sect_off); this_cu.set_length (cu->header.get_length_with_initial ()); @@ -3205,11 +3136,11 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, m_info_ptr = section->buffer + to_underlying (this_cu.sect_off); const gdb_byte *begin_info_ptr = m_info_ptr; - m_info_ptr = read_and_check_comp_unit_head (&m_new_cu->header, section, - abbrev_section, m_info_ptr, - (this_cu.is_debug_types - ? rcuh_kind::TYPE - : rcuh_kind::COMPILE)); + m_info_ptr = read_and_check_unit_head (&m_new_cu->header, section, + abbrev_section, m_info_ptr, + (this_cu.is_debug_types + ? ruh_kind::TYPE + : ruh_kind::COMPILE)); m_new_cu->str_offsets_base = parent_cu.str_offsets_base; m_new_cu->addr_base = parent_cu.addr_base; @@ -3283,33 +3214,131 @@ get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list return {cu->dwo_unit, static_cast<sect_offset> (line_offset)}; } -/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. - Process compilation unit THIS_CU for a psymtab. */ +/* A subclass of cooked_index_worker that handles scanning + .debug_info. */ -static void -process_psymtab_comp_unit (dwarf2_per_cu *this_cu, - dwarf2_per_objfile *per_objfile, - cooked_index_worker_result *storage) +class cooked_index_worker_debug_info : public cooked_index_worker +{ +public: + cooked_index_worker_debug_info (dwarf2_per_objfile *per_objfile) + : cooked_index_worker (per_objfile) + { + gdb_assert (is_main_thread ()); + + struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + + dwarf_read_debug_printf ("Building psymtabs of objfile %s ...", + objfile_name (objfile)); + + per_bfd->map_info_sections (objfile); + } + +private: + void do_reading () override; + + /* Print collected type unit statistics. */ + + void print_tu_stats (dwarf2_per_objfile *per_objfile) + { + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + tu_stats *tu_stats = &per_bfd->tu_stats; + + dwarf_read_debug_printf ("Type unit statistics:"); + dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units); + dwarf_read_debug_printf (" %d uniq abbrev tables", + tu_stats->nr_uniq_abbrev_tables); + dwarf_read_debug_printf (" %d symtabs from stmt_list entries", + tu_stats->nr_symtabs); + dwarf_read_debug_printf (" %d symtab sharers", + tu_stats->nr_symtab_sharers); + dwarf_read_debug_printf (" %d type units without a stmt_list", + tu_stats->nr_stmt_less_type_units); + dwarf_read_debug_printf (" %d all_type_units reallocs", + tu_stats->nr_all_type_units_reallocs); + } + + void print_stats () override + { + if (dwarf_read_debug > 0) + print_tu_stats (m_per_objfile); + + if (dwarf_read_debug > 1) + { + dwarf_read_debug_printf_v ("Final m_all_parents_map:"); + m_all_parents_map.dump (m_per_objfile->per_bfd); + } + } + + /* After the last DWARF-reading task has finished, this function + does the remaining work to finish the scan. */ + void done_reading () override; + + /* An iterator for the comp units. */ + using unit_iterator = std::vector<dwarf2_per_cu_up>::iterator; + + /* Process a batch of CUs. This may be called multiple times in + separate threads. TASK_NUMBER indicates which task this is -- + the result is stored in that slot of M_RESULTS. */ + void process_units (size_t task_number, unit_iterator first, + unit_iterator end); + + /* Process unit THIS_CU. */ + void process_unit (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage); + + /* Process all type units existing in PER_OBJFILE::PER_BFD::ALL_UNITS. */ + void process_type_units (dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage); + + /* Process the type unit wrapped in READER. */ + void process_type_unit (cutu_reader *reader, + cooked_index_worker_result *storage); + + /* Process all type units of all DWO files. + + This is needed in case a TU was emitted without its skeleton. + Note: This can't be done until we know what all the DWO files are. */ + void process_skeletonless_type_units (dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage); + + /* Process the type unit represented by DWO_UNIT. */ + void process_skeletonless_type_unit (dwo_unit *dwo_unit, + dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage); + + /* A storage object for "leftovers" -- see the 'start' method, but + essentially things not parsed during the normal CU parsing + passes. */ + cooked_index_worker_result m_index_storage; +}; + +void +cooked_index_worker_debug_info::process_unit + (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage) { cutu_reader *reader = storage->get_reader (this_cu); if (reader == nullptr) { - cutu_reader new_reader (*this_cu, *per_objfile, nullptr, nullptr, false, - language_minimal, - &storage->get_abbrev_table_cache ()); + const abbrev_table_cache &abbrev_table_cache + = storage->get_abbrev_table_cache (); + auto new_reader = std::make_unique<cutu_reader> (*this_cu, *per_objfile, + nullptr, nullptr, false, + language_minimal, + &abbrev_table_cache); - if (new_reader.cu () == nullptr || new_reader.is_dummy ()) + if (new_reader->is_dummy ()) return; - auto copy = std::make_unique<cutu_reader> (std::move (new_reader)); - reader = storage->preserve (std::move (copy)); + reader = storage->preserve (std::move (new_reader)); } - if (reader->top_level_die () == nullptr || reader->is_dummy ()) + if (reader->is_dummy ()) return; if (this_cu->is_debug_types) - build_type_psymtabs_reader (reader, storage); + process_type_unit (reader, storage); else if (reader->top_level_die ()->tag != DW_TAG_partial_unit) { bool nope = false; @@ -3322,11 +3351,9 @@ process_psymtab_comp_unit (dwarf2_per_cu *this_cu, } } -/* Reader function for build_type_psymtabs. */ - -static void -build_type_psymtabs_reader (cutu_reader *reader, - cooked_index_worker_result *storage) +void +cooked_index_worker_debug_info::process_type_unit + (cutu_reader *reader, cooked_index_worker_result *storage) { struct dwarf2_cu *cu = reader->cu (); dwarf2_per_cu *per_cu = cu->per_cu; @@ -3360,32 +3387,15 @@ struct tu_abbrev_offset sect_offset abbrev_offset; }; -/* Efficiently read all the type units. - - The efficiency is because we sort TUs by the abbrev table they use and - only read each abbrev table once. In one program there are 200K TUs - sharing 8K abbrev tables. - - The main purpose of this function is to support building the - dwarf2_per_objfile->per_bfd->type_unit_groups table. - TUs typically share the DW_AT_stmt_list of the CU they came from, so we - can collapse the search space by grouping them by stmt_list. - The savings can be significant, in the same program from above the 200K TUs - share 8K stmt_list tables. - - FUNC is expected to call get_type_unit_group, which will create the - struct type_unit_group if necessary and add it to - dwarf2_per_objfile->per_bfd->type_unit_groups. */ - -static void -build_type_psymtabs (dwarf2_per_objfile *per_objfile, - cooked_index_worker_result *storage) +void +cooked_index_worker_debug_info::process_type_units + (dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage) { struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats; abbrev_table_up abbrev_table; sect_offset abbrev_offset; - if (per_objfile->per_bfd->all_type_units.size () == 0) + if (per_objfile->per_bfd->num_type_units == 0) return; /* TUs typically share abbrev tables, and there can be way more TUs than @@ -3412,7 +3422,7 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile, /* Sort in a separate table to maintain the order of all_units for .gdb_index: TU indices directly index all_type_units. */ std::vector<tu_abbrev_offset> sorted_by_abbrev; - sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ()); + sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units); for (const auto &cu : per_objfile->per_bfd->all_units) if (cu->is_debug_types) @@ -3445,38 +3455,17 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile, abbrev_table.get (), nullptr, false, language_minimal); if (!reader.is_dummy ()) - build_type_psymtabs_reader (&reader, storage); + storage->catch_error ([&] () + { + process_type_unit (&reader, storage); + }); } } -/* Print collected type unit statistics. */ - -static void -print_tu_stats (dwarf2_per_objfile *per_objfile) -{ - struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats; - - dwarf_read_debug_printf ("Type unit statistics:"); - dwarf_read_debug_printf (" %d TUs", tu_stats->nr_tus); - dwarf_read_debug_printf (" %d uniq abbrev tables", - tu_stats->nr_uniq_abbrev_tables); - dwarf_read_debug_printf (" %d symtabs from stmt_list entries", - tu_stats->nr_symtabs); - dwarf_read_debug_printf (" %d symtab sharers", - tu_stats->nr_symtab_sharers); - dwarf_read_debug_printf (" %d type units without a stmt_list", - tu_stats->nr_stmt_less_type_units); - dwarf_read_debug_printf (" %d all_type_units reallocs", - tu_stats->nr_all_type_units_reallocs); -} - -/* Traversal function for process_skeletonless_type_units. - Read a TU in a DWO file and build partial symbols for it. */ - -static void -process_skeletonless_type_unit (dwo_unit *dwo_unit, - dwarf2_per_objfile *per_objfile, - cooked_index_worker_result *storage) +void +cooked_index_worker_debug_info::process_skeletonless_type_unit + (dwo_unit *dwo_unit, dwarf2_per_objfile *per_objfile, + cooked_index_worker_result *storage) { dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; @@ -3498,82 +3487,29 @@ process_skeletonless_type_unit (dwo_unit *dwo_unit, cutu_reader reader (**sig_type_it, *per_objfile, nullptr, nullptr, false, language_minimal); if (!reader.is_dummy ()) - build_type_psymtabs_reader (&reader, storage); + process_type_unit (&reader, storage); } -/* Scan all TUs of DWO files, verifying we've processed them. - This is needed in case a TU was emitted without its skeleton. - 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, - cooked_index_worker_result *storage) +void +cooked_index_worker_debug_info::process_skeletonless_type_units + (dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage) { + scoped_time_it time_it ("DWARF skeletonless type units", m_per_command_time); + /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */ if (per_objfile->per_bfd->dwp_file == nullptr) for (const dwo_file_up &file : per_objfile->per_bfd->dwo_files) - for (dwo_unit *unit : file->tus) - process_skeletonless_type_unit (unit, per_objfile, storage); + for (const dwo_unit_up &unit : file->tus) + storage->catch_error ([&] () + { + process_skeletonless_type_unit (unit.get (), per_objfile, storage); + }); } -/* A subclass of cooked_index_worker that handles scanning - .debug_info. */ - -class cooked_index_worker_debug_info : public cooked_index_worker -{ -public: - cooked_index_worker_debug_info (dwarf2_per_objfile *per_objfile) - : cooked_index_worker (per_objfile) - { - gdb_assert (is_main_thread ()); - - struct objfile *objfile = per_objfile->objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - - dwarf_read_debug_printf ("Building psymtabs of objfile %s ...", - objfile_name (objfile)); - - per_bfd->map_info_sections (objfile); - } - -private: - - void do_reading () override; - - void print_stats () override - { - if (dwarf_read_debug > 0) - print_tu_stats (m_per_objfile); - if (dwarf_read_debug > 1) - { - dwarf_read_debug_printf_v ("Final m_all_parents_map:"); - m_all_parents_map.dump (m_per_objfile->per_bfd); - } - } - - /* After the last DWARF-reading task has finished, this function - does the remaining work to finish the scan. */ - void done_reading () override; - - /* An iterator for the comp units. */ - using unit_iterator = std::vector<dwarf2_per_cu_up>::iterator; - - /* Process a batch of CUs. This may be called multiple times in - separate threads. TASK_NUMBER indicates which task this is -- - the result is stored in that slot of M_RESULTS. */ - void process_cus (size_t task_number, unit_iterator first, - unit_iterator end); - - /* A storage object for "leftovers" -- see the 'start' method, but - essentially things not parsed during the normal CU parsing - passes. */ - cooked_index_worker_result m_index_storage; -}; - void -cooked_index_worker_debug_info::process_cus (size_t task_number, - unit_iterator first, - unit_iterator end) +cooked_index_worker_debug_info::process_units (size_t task_number, + unit_iterator first, + unit_iterator end) { SCOPE_EXIT { bfd_thread_cleanup (); }; @@ -3586,14 +3522,10 @@ cooked_index_worker_debug_info::process_cus (size_t task_number, { dwarf2_per_cu *per_cu = inner->get (); - try - { - process_psymtab_comp_unit (per_cu, m_per_objfile, &thread_storage); - } - catch (gdb_exception &except) + thread_storage.catch_error ([&] () { - thread_storage.note_error (std::move (except)); - } + process_unit (per_cu, m_per_objfile, &thread_storage); + }); } thread_storage.done_reading (complaint_handler.release ()); @@ -3618,7 +3550,7 @@ cooked_index_worker_debug_info::do_reading () dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; create_all_units (m_per_objfile); - build_type_psymtabs (m_per_objfile, &m_index_storage); + process_type_units (m_per_objfile, &m_index_storage); if (!per_bfd->debug_aranges.empty ()) read_addrmap_from_aranges (m_per_objfile, &per_bfd->debug_aranges, @@ -3671,7 +3603,8 @@ cooked_index_worker_debug_info::do_reading () gdb_assert (iter != last); workers.add_task ([this, task_count, iter, last] () { - process_cus (task_count, iter, last); + scoped_time_it time_it ("DWARF indexing worker", m_per_command_time); + process_units (task_count, iter, last); }); ++task_count; @@ -3688,7 +3621,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, struct dwarf2_section_info *abbrev_section, unsigned int is_dwz, signatured_type_set &sig_types, - rcuh_kind section_kind) + ruh_kind section_kind) { const gdb_byte *info_ptr; struct objfile *objfile = per_objfile->objfile; @@ -3708,9 +3641,9 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, sect_offset sect_off = (sect_offset) (info_ptr - section->buffer); - comp_unit_head cu_header; - read_and_check_comp_unit_head (&cu_header, section, abbrev_section, - info_ptr, section_kind); + unit_head cu_header; + read_and_check_unit_head (&cu_header, section, abbrev_section, info_ptr, + section_kind); unsigned int length = cu_header.get_length_with_initial (); @@ -3723,7 +3656,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, = per_bfd->allocate_signatured_type (section, sect_off, length, is_dwz, cu_header.signature); signatured_type *sig_ptr = sig_type.get (); - sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu; + sig_type->type_offset_in_tu = cu_header.type_offset_in_tu; this_cu.reset (sig_type.release ()); auto inserted = sig_types.emplace (sig_ptr).second; @@ -3741,16 +3674,22 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, } } -/* Initialize the views on all_units. */ +/* See read.h. */ void finalize_all_units (dwarf2_per_bfd *per_bfd) { - size_t nr_tus = per_bfd->tu_stats.nr_tus; - size_t nr_cus = per_bfd->all_units.size () - nr_tus; - gdb::array_view<dwarf2_per_cu_up> tmp = per_bfd->all_units; - per_bfd->all_comp_units = tmp.slice (0, nr_cus); - per_bfd->all_type_units = tmp.slice (nr_cus, nr_tus); + /* Sanity check. */ + gdb_assert (per_bfd->all_units.size () + == per_bfd->num_comp_units + per_bfd->num_type_units); + + /* Ensure that the all_units vector is in the expected order for + dwarf2_find_containing_unit to be able to perform a binary search. */ + std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (), + [] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b) + { + return all_units_less_than (*a, { b->section, b->sect_off }); + }); } /* See read.h. */ @@ -3759,28 +3698,27 @@ void create_all_units (dwarf2_per_objfile *per_objfile) { gdb_assert (per_objfile->per_bfd->all_units.empty ()); + scoped_remove_all_units remove_all_units (*per_objfile->per_bfd); signatured_type_set sig_types; for (dwarf2_section_info §ion : per_objfile->per_bfd->infos) read_comp_units_from_section (per_objfile, §ion, &per_objfile->per_bfd->abbrev, 0, sig_types, - rcuh_kind::COMPILE); + ruh_kind::COMPILE); for (dwarf2_section_info §ion : per_objfile->per_bfd->types) read_comp_units_from_section (per_objfile, §ion, &per_objfile->per_bfd->abbrev, 0, sig_types, - rcuh_kind::TYPE); + ruh_kind::TYPE); dwz_file *dwz = per_objfile->per_bfd->get_dwz_file (); if (dwz != NULL) { read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1, - sig_types, rcuh_kind::COMPILE); + sig_types, ruh_kind::COMPILE); if (!dwz->types.empty ()) { - per_objfile->per_bfd->all_units.clear (); - /* See enhancement PR symtab/30838. */ error (_(DWARF_ERROR_PREFIX ".debug_types section not supported in dwz file")); @@ -3790,6 +3728,7 @@ create_all_units (dwarf2_per_objfile *per_objfile) per_objfile->per_bfd->signatured_types = std::move (sig_types); finalize_all_units (per_objfile->per_bfd); + remove_all_units.disable (); } /* Return the initial uleb128 in the die at INFO_PTR. */ @@ -4322,7 +4261,7 @@ fixup_go_packaging (struct dwarf2_cu *cu) struct symbol *sym = list->symbol[i]; if (sym->language () == language_go - && sym->aclass () == LOC_BLOCK) + && sym->loc_class () == LOC_BLOCK) { gdb::unique_xmalloc_ptr<char> this_package_name = go_symbol_package_name (sym); @@ -4359,7 +4298,7 @@ fixup_go_packaging (struct dwarf2_cu *cu) sym->set_language (language_go, &objfile->objfile_obstack); sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd); sym->set_domain (TYPE_DOMAIN); - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); sym->set_type (type); add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ()); @@ -4569,9 +4508,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) else { struct type *disr_type = nullptr; - for (int i = 0; i < type->num_fields (); ++i) + for (const auto &field : type->fields ()) { - disr_type = type->field (i).type (); + disr_type = field.type (); if (disr_type->code () != TYPE_CODE_STRUCT) { @@ -4610,7 +4549,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) field *new_fields = (struct field *) TYPE_ZALLOC (type, ((type->num_fields () + 1) * sizeof (struct field))); - memcpy (new_fields + 1, type->fields (), + memcpy (new_fields + 1, type->fields ().data (), type->num_fields () * sizeof (struct field)); type->set_fields (new_fields); type->set_num_fields (type->num_fields () + 1); @@ -4624,13 +4563,12 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) variant name. For convenience we build a map here. */ struct type *enum_type = disr_field->type (); gdb::unordered_map<std::string_view, ULONGEST> discriminant_map; - for (int i = 0; i < enum_type->num_fields (); ++i) + for (const auto &field : enum_type->fields ()) { - if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL) + if (field.loc_kind () == FIELD_LOC_KIND_ENUMVAL) { - const char *name - = rust_last_path_segment (enum_type->field (i).name ()); - discriminant_map[name] = enum_type->field (i).loc_enumval (); + const char *name = rust_last_path_segment (field.name ()); + discriminant_map[name] = field.loc_enumval (); } } @@ -4666,7 +4604,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) if (sub_type->num_fields () > 0) { sub_type->set_num_fields (sub_type->num_fields () - 1); - sub_type->set_fields (sub_type->fields () + 1); + sub_type->set_fields (sub_type->fields ().data () + 1); } type->field (i).set_name (variant_name); sub_type->set_name @@ -5006,6 +4944,21 @@ process_full_type_unit (dwarf2_cu *cu) cu->reset_builder (); } +/* See read.h. */ + +const dwarf2_section_info & +get_section_for_ref (const attribute &attr, dwarf2_cu *cu) +{ + gdb_assert (attr.form_is_ref ()); + + if (attr.form_is_alt ()) + return cu->per_cu->per_bfd->get_dwz_file (true)->info; + + /* If the source is already in the supplementary (dwz) file, then CU->SECTION + already represents the section in the supplementary file. */ + return cu->section (); +} + /* Process an imported unit DIE. */ static void @@ -5025,12 +4978,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_import, cu); if (attr != NULL) { + const dwarf2_section_info §ion = get_section_for_ref (*attr, cu); sect_offset sect_off = attr->get_ref_die_offset (); - bool is_dwz = attr->form_is_alt () || cu->per_cu->is_dwz; dwarf2_per_objfile *per_objfile = cu->per_objfile; dwarf2_per_cu *per_cu - = dwarf2_find_containing_comp_unit (sect_off, is_dwz, - per_objfile->per_bfd); + = dwarf2_find_containing_unit ({ §ion, sect_off }, per_objfile); /* 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, @@ -5732,7 +5684,7 @@ read_alias (struct die_info *die, struct dwarf2_cu *cu) type = die_type (d, imported_cu); struct symbol *sym = new_symbol (die, type, cu); attr = dwarf2_attr (d, DW_AT_location, imported_cu); - sym->set_aclass_index (LOC_UNRESOLVED); + sym->set_loc_class_index (LOC_UNRESOLVED); if (attr != nullptr) var_decode_location (attr, sym, cu); return true; @@ -5955,7 +5907,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu) && res.get_name () != nullptr && IS_ABSOLUTE_PATH (res.get_name ())) { - res.set_comp_dir (ldirname (res.get_name ())); + res.set_comp_dir (gdb_ldirname (res.get_name ())); res.set_name (make_unique_xstrdup (lbasename (res.get_name ()))); } @@ -6151,6 +6103,20 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) } } +/* See cu.h. + + This function is defined in this file (instead of cu.c) because it needs + to see the definition of struct dwo_unit. */ + +const dwarf2_section_info & +dwarf2_cu::section () const +{ + if (this->dwo_unit != nullptr) + return *this->dwo_unit->section; + else + return *this->per_cu->section; +} + void dwarf2_cu::setup_type_unit_groups (struct die_info *die) { @@ -6302,84 +6268,158 @@ static dwo_file * lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name, const char *comp_dir) { +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (per_bfd->dwo_files_lock); +#endif + auto it = per_bfd->dwo_files.find (dwo_file_search {dwo_name, comp_dir}); return it != per_bfd->dwo_files.end () ? it->get() : nullptr; } -/* Create the dwo_units for the CUs in a DWO_FILE. - Note: This function processes DWO files only, not DWP files. */ +/* Add DWO_FILE to the per-BFD DWO file hash table. + + Return the dwo_file actually kept in the hash table. + + If another thread raced with this one, opening the exact same DWO file and + inserting it first in the hash table, then keep that other thread's copy + and DWO_FILE gets freed. */ + +static dwo_file * +add_dwo_file (dwarf2_per_bfd *per_bfd, dwo_file_up dwo_file) +{ +#if CXX_STD_THREAD + std::lock_guard<std::mutex> lock (per_bfd->dwo_files_lock); +#endif + + return per_bfd->dwo_files.emplace (std::move (dwo_file)).first->get (); +} void -cutu_reader::create_dwo_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) +cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file, + dwarf2_cu &skeleton_cu, + dwarf2_section_info §ion, + ruh_kind section_kind) { - dwarf2_per_objfile *per_objfile = cu->per_objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - const gdb_byte *info_ptr, *end_ptr; - auto §ion = dwo_file.sections.info; + dwarf2_per_objfile &per_objfile = *skeleton_cu.per_objfile; + dwarf2_per_bfd &per_bfd = *per_objfile.per_bfd; - info_ptr = section.buffer; + const gdb_byte *info_ptr = section.buffer; if (info_ptr == NULL) return; - dwarf_read_debug_printf ("Reading %s for %s:", - section.get_name (), + dwarf_read_debug_printf ("Reading %s for %s:", section.get_name (), section.get_file_name ()); - end_ptr = info_ptr + section.size; + const gdb_byte *end_ptr = info_ptr + section.size; + while (info_ptr < end_ptr) { sect_offset sect_off = (sect_offset) (info_ptr - section.buffer); + unit_head header; + dwarf2_section_info *abbrev_section = &dwo_file.sections.abbrev; + const gdb_byte *info_ptr_post_header + = read_and_check_unit_head (&header, §ion, abbrev_section, + info_ptr, section_kind); - /* The length of the CU gets set by the cutu_reader just below. */ - dwarf2_per_cu per_cu (per_bfd, §ion, sect_off, 0 /* length */, - false /* is_dwz */); - cutu_reader reader (per_cu, *per_objfile, language_minimal, - *cu, dwo_file); - - info_ptr += per_cu.length (); + unsigned int length = header.get_length_with_initial (); + info_ptr += length; - if (reader.is_dummy()) + /* Skip dummy units. */ + if (info_ptr_post_header >= info_ptr + || peek_abbrev_code (section.get_bfd_owner (), + info_ptr_post_header) == 0) continue; - /* DWARF 5 .debug_info.dwo sections may contain some type units. Skip - everything that is not a compile unit. */ - if (const auto ut = reader.cu ()->header.unit_type; - ut != DW_UT_compile && ut != DW_UT_split_compile) + if (header.unit_type != DW_UT_compile + && header.unit_type != DW_UT_split_compile + && header.unit_type != DW_UT_type + && header.unit_type != DW_UT_split_type) continue; - std::optional<ULONGEST> signature - = lookup_dwo_id (reader.cu (), reader.top_level_die ()); - if (!signature.has_value ()) + ULONGEST signature; + + /* For type units (all DWARF versions) and DWARF 5 compile units, the + signature/DWO ID is already available in the header. For compile + units in DWARF < 5, we need to read the DW_AT_GNU_dwo_id attribute + from the top-level DIE. + + For DWARF < 5 compile units, the unit type will be set to DW_UT_compile + by read_and_check_comp_unit_head. */ + if (header.version < 5 && header.unit_type == DW_UT_compile) { - complaint (_(DWARF_ERROR_PREFIX - "debug entry at offset %s is missing its dwo_id" - " [in module %s]"), - sect_offset_str (sect_off), - dwo_file.dwo_name.c_str ()); - continue; + /* The length of the CU is not necessary. */ + dwarf2_per_cu per_cu (&per_bfd, §ion, sect_off, length, + false /* is_dwz */); + cutu_reader reader (per_cu, per_objfile, language_minimal, + skeleton_cu, dwo_file); + + std::optional<ULONGEST> opt_signature + = lookup_dwo_id (reader.cu (), reader.top_level_die ()); + + if (!opt_signature.has_value ()) + { + complaint (_ (DWARF_ERROR_PREFIX + "debug entry at offset %s is missing its dwo_id" + " [in module %s]"), + sect_offset_str (sect_off), + dwo_file.dwo_name.c_str ()); + continue; + } + + signature = *opt_signature; } + else + signature = header.signature; - dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit); + auto dwo_unit = std::make_unique<struct dwo_unit> (); + /* Set the fields common to compile and type units. */ dwo_unit->dwo_file = &dwo_file; - dwo_unit->signature = *signature; + dwo_unit->signature = signature; dwo_unit->section = §ion; dwo_unit->sect_off = sect_off; - dwo_unit->length = per_cu.length (); + dwo_unit->length = length; - dwarf_read_debug_printf (" offset %s, dwo_id %s", - sect_offset_str (sect_off), - hex_string (dwo_unit->signature)); + switch (header.unit_type) + { + case DW_UT_compile: + case DW_UT_split_compile: + { + dwarf_read_debug_printf (" compile unit at offset %s, dwo_id %s", + sect_offset_str (sect_off), + hex_string (dwo_unit->signature)); - auto [it, inserted] = dwo_file.cus.emplace (dwo_unit); - if (!inserted) - complaint (_("debug cu entry at offset %s is duplicate to" - " the entry at offset %s, signature %s"), - sect_offset_str (sect_off), - sect_offset_str ((*it)->sect_off), - hex_string (dwo_unit->signature)); + auto [it, inserted] = dwo_file.cus.emplace (std::move (dwo_unit)); + if (!inserted) + complaint (_("debug cu entry at offset %s is duplicate to" + " the entry at offset %s, signature %s"), + sect_offset_str (sect_off), + sect_offset_str ((*it)->sect_off), + hex_string (dwo_unit->signature)); + break; + } + + case DW_UT_type: + case DW_UT_split_type: + { + dwo_unit->type_offset_in_tu = header.type_offset_in_tu; + + dwarf_read_debug_printf (" type unit at offset %s, signature %s", + sect_offset_str (sect_off), + hex_string (dwo_unit->signature)); + + auto [it, inserted] = dwo_file.tus.emplace (std::move (dwo_unit)); + if (!inserted) + complaint (_("debug type entry at offset %s is duplicate to" + " the entry at offset %s, signature %s"), + sect_offset_str (sect_off), + sect_offset_str ((*it)->sect_off), + hex_string (header.signature)); + break; + } + } } } @@ -6851,7 +6891,7 @@ locate_v1_virtual_dwo_sections (asection *sectp, COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU. This is for DWP version 1 files. */ -static struct dwo_unit * +static dwo_unit_up create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file, uint32_t unit_index, @@ -6974,19 +7014,17 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd, types we'll grow the vector and eventually have to reallocate space for it, invalidating all copies of pointers into the previous contents. */ - auto [it, inserted] - = per_bfd->dwo_files.emplace (std::move (new_dwo_file)); - gdb_assert (inserted); - dwo_file = it->get (); + dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file)); } else dwarf_read_debug_printf ("Using existing virtual DWO: %s", virtual_dwo_name.c_str ()); - dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit); + auto dwo_unit = std::make_unique<struct dwo_unit> (); dwo_unit->dwo_file = dwo_file; dwo_unit->signature = signature; - dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info); + dwo_unit->section_holder = std::make_unique<dwarf2_section_info> (); + dwo_unit->section = dwo_unit->section_holder.get (); *dwo_unit->section = sections.info_or_types; /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */ @@ -7044,7 +7082,7 @@ create_dwp_v2_or_v5_section (dwarf2_per_bfd *per_bfd, COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU. This is for DWP version 2 files. */ -static struct dwo_unit * +static dwo_unit_up create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file, uint32_t unit_index, @@ -7179,19 +7217,17 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd, types we'll grow the vector and eventually have to reallocate space for it, invalidating all copies of pointers into the previous contents. */ - auto [it, inserted] - = per_bfd->dwo_files.emplace (std::move (new_dwo_file)); - gdb_assert (inserted); - dwo_file = it->get (); + dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file)); } else dwarf_read_debug_printf ("Using existing virtual DWO: %s", virtual_dwo_name.c_str ()); - dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit); + auto dwo_unit = std::make_unique<struct dwo_unit> (); dwo_unit->dwo_file = dwo_file; dwo_unit->signature = signature; - dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info); + dwo_unit->section_holder = std::make_unique<dwarf2_section_info> (); + dwo_unit->section = dwo_unit->section_holder.get (); *dwo_unit->section = create_dwp_v2_or_v5_section (per_bfd, is_debug_types @@ -7209,7 +7245,7 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd, COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU. This is for DWP version 5 files. */ -static struct dwo_unit * +static dwo_unit_up create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file, uint32_t unit_index, @@ -7349,16 +7385,13 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd, types we'll grow the vector and eventually have to reallocate space for it, invalidating all copies of pointers into the previous contents. */ - auto [it, inserted] - = per_bfd->dwo_files.emplace (std::move (new_dwo_file)); - gdb_assert (inserted); - dwo_file = it->get (); + dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file)); } else dwarf_read_debug_printf ("Using existing virtual DWO: %s", virtual_dwo_name.c_str ()); - dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit); + auto dwo_unit = std::make_unique<struct dwo_unit> (); dwo_unit->dwo_file = dwo_file; dwo_unit->signature = signature; dwo_unit->section @@ -7389,9 +7422,15 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd, auto &dwo_unit_set = is_debug_types ? dwp_file->loaded_tus : dwp_file->loaded_cus; - if (auto it = dwo_unit_set.find (signature); - it != dwo_unit_set.end ()) - return *it; + { +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock); +#endif + + if (auto it = dwo_unit_set.find (signature); + it != dwo_unit_set.end ()) + return it->get (); + } /* Use a for loop so that we don't loop forever on bad debug info. */ for (unsigned int i = 0; i < dwp_htab->nr_slots; ++i) @@ -7405,7 +7444,7 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd, uint32_t unit_index = read_4_bytes (dbfd, dwp_htab->unit_table + hash * sizeof (uint32_t)); - dwo_unit *dwo_unit; + dwo_unit_up dwo_unit; if (dwp_file->version == 1) dwo_unit @@ -7420,9 +7459,14 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd, = create_dwo_unit_in_dwp_v5 (per_bfd, dwp_file, unit_index, comp_dir, signature, is_debug_types); - auto [it, inserted] = dwo_unit_set.emplace (dwo_unit); - gdb_assert (inserted); - return *it; + /* If another thread raced with this one, opening the exact same + DWO unit, then we'll keep that other thread's copy. */ +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock); +#endif + + auto it = dwo_unit_set.emplace (std::move (dwo_unit)).first; + return it->get (); } if (signature_in_table == 0) @@ -7478,7 +7522,7 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp, search_path = per_bfd->captured_debug_dir.c_str (); /* Add the path for the executable binary to the list of search paths. */ - std::string objfile_dir = ldirname (per_bfd->filename ()); + std::string objfile_dir = gdb_ldirname (per_bfd->filename ()); search_path_holder.reset (concat (objfile_dir.c_str (), dirname_separator_string, search_path, nullptr)); @@ -7499,14 +7543,23 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp, if (sym_bfd == NULL) return NULL; - if (!bfd_check_format (sym_bfd.get (), bfd_object)) - return NULL; + { +#if CXX_STD_THREAD + /* The operations below are not thread-safe, use a lock to synchronize + concurrent accesses. */ + static std::mutex mutex; + std::lock_guard<std::mutex> lock (mutex); +#endif - /* Success. Record the bfd as having been included by the objfile's bfd. + if (!bfd_check_format (sym_bfd.get (), bfd_object)) + return NULL; + + /* Success. Record the bfd as having been included by the objfile's bfd. This is important because things like demangled_names_hash lives in the objfile's per_bfd space and may have references to things like symbol names that live in the DWO/DWP file's per_bfd space. PR 16426. */ - gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ()); + gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ()); + } return sym_bfd; } @@ -7556,47 +7609,66 @@ cutu_reader::open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name, size of each of the DWO debugging sections we are interested in. */ void -cutu_reader::locate_dwo_sections (struct objfile *objfile, bfd *abfd, - asection *sectp, dwo_sections *dwo_sections) +cutu_reader::locate_dwo_sections (objfile *objfile, dwo_file &dwo_file) { const struct dwop_section_names *names = &dwop_section_names; + dwo_sections &dwo_sections = dwo_file.sections; + bool complained_about_macro_already = false; + + for (asection *sec : gdb_bfd_sections (dwo_file.dbfd)) + { + struct dwarf2_section_info *dw_sect = nullptr; + + if (names->abbrev_dwo.matches (sec->name)) + dw_sect = &dwo_sections.abbrev; + else if (names->info_dwo.matches (sec->name)) + dw_sect = &dwo_sections.infos.emplace_back (dwarf2_section_info {}); + else if (names->line_dwo.matches (sec->name)) + dw_sect = &dwo_sections.line; + else if (names->loc_dwo.matches (sec->name)) + dw_sect = &dwo_sections.loc; + else if (names->loclists_dwo.matches (sec->name)) + dw_sect = &dwo_sections.loclists; + else if (names->macinfo_dwo.matches (sec->name)) + dw_sect = &dwo_sections.macinfo; + else if (names->macro_dwo.matches (sec->name)) + { + /* gcc versions <= 13 generate multiple .debug_macro.dwo sections with + some unresolved links between them. It's not usable, so do as if + there were not there. */ + if (!complained_about_macro_already) + { + if (dwo_sections.macro.s.section == nullptr) + dw_sect = &dwo_sections.macro; + else + { + warning (_("Multiple .debug_macro.dwo sections found in " + "%s, ignoring them."), dwo_file.dbfd->filename); - struct dwarf2_section_info *dw_sect = nullptr; - - if (names->abbrev_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->abbrev; - else if (names->info_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->info; - else if (names->line_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->line; - else if (names->loc_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->loc; - else if (names->loclists_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->loclists; - else if (names->macinfo_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->macinfo; - else if (names->macro_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->macro; - else if (names->rnglists_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->rnglists; - else if (names->str_dwo.matches (sectp->name)) - dw_sect = &dwo_sections->str; - else if (names->str_offsets_dwo.matches (sectp->name)) - 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)); - dwo_sections->types.push_back (type_section); - dw_sect = &dwo_sections->types.back (); - } + dwo_sections.macro = dwarf2_section_info {}; + complained_about_macro_already = true; + } + } + } + else if (names->rnglists_dwo.matches (sec->name)) + dw_sect = &dwo_sections.rnglists; + else if (names->str_dwo.matches (sec->name)) + dw_sect = &dwo_sections.str; + else if (names->str_offsets_dwo.matches (sec->name)) + dw_sect = &dwo_sections.str_offsets; + else if (names->types_dwo.matches (sec->name)) + dw_sect = &dwo_sections.types.emplace_back (dwarf2_section_info {}); + + if (dw_sect != nullptr) + { + /* Make sure we don't overwrite a section info that has been filled in + already. */ + gdb_assert (!dw_sect->readin); - if (dw_sect != nullptr) - { - dw_sect->s.section = sectp; - dw_sect->size = bfd_section_size (sectp); - dw_sect->read (objfile); + dw_sect->s.section = sec; + dw_sect->size = bfd_section_size (sec); + dw_sect->read (objfile); + } } } @@ -7609,7 +7681,6 @@ cutu_reader::open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir) { dwarf2_per_objfile *per_objfile = cu->per_objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; gdb_bfd_ref_ptr dbfd = open_dwo_file (per_objfile->per_bfd, dwo_name, comp_dir); @@ -7625,19 +7696,13 @@ cutu_reader::open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, dwo_file->comp_dir = comp_dir; dwo_file->dbfd = std::move (dbfd); - for (asection *sec : gdb_bfd_sections (dwo_file->dbfd)) - this->locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), sec, - &dwo_file->sections); + this->locate_dwo_sections (per_objfile->objfile, *dwo_file); - create_dwo_cus_hash_table (cu, *dwo_file); + for (dwarf2_section_info §ion : dwo_file->sections.infos) + create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::COMPILE); - if (cu->header.version < 5) - create_dwo_debug_types_hash_table (per_bfd, dwo_file.get (), - dwo_file->sections.types); - else - create_dwo_debug_type_hash_table (per_bfd, dwo_file.get (), - &dwo_file->sections.info, - rcuh_kind::COMPILE); + for (dwarf2_section_info §ion : dwo_file->sections.types) + create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::TYPE); dwarf_read_debug_printf ("DWO file found: %s", dwo_name); @@ -7673,6 +7738,10 @@ dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd, if (dw_sect != nullptr) { + /* Make sure we don't overwrite a section info that has been filled in + already. */ + gdb_assert (!dw_sect->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7718,6 +7787,10 @@ dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd, if (dw_sect != nullptr) { + /* Make sure we don't overwrite a section info that has been filled in + already. */ + gdb_assert (!dw_sect->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7761,6 +7834,10 @@ dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd, if (dw_sect != nullptr) { + /* Make sure we don't overwrite a section info that has been filled in + already. */ + gdb_assert (!dw_sect->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7822,7 +7899,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) struct objfile *backlink = objfile->separate_debug_objfile_backlink; const char *backlink_basename = lbasename (backlink->original_name); - dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename; + dwp_name = gdb_ldirname (objfile->original_name) + SLASH_STRING + backlink_basename; } else dwp_name = objfile->original_name; @@ -7972,12 +8049,7 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, = open_and_init_dwo_file (cu, dwo_name, comp_dir); if (new_dwo_file != nullptr) - { - auto [it, inserted] - = per_bfd->dwo_files.emplace (std::move (new_dwo_file)); - gdb_assert (inserted); - dwo_file = (*it).get (); - } + dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file)); } if (dwo_file != NULL) @@ -7988,13 +8060,13 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, { if (auto it = dwo_file->tus.find (signature); it != dwo_file->tus.end ()) - dwo_cutu = *it; + dwo_cutu = it->get (); } else if (!is_debug_types && !dwo_file->cus.empty ()) { if (auto it = dwo_file->cus.find (signature); it != dwo_file->cus.end ()) - dwo_cutu = *it; + dwo_cutu = it->get (); } if (dwo_cutu != NULL) @@ -8101,8 +8173,8 @@ queue_and_load_all_dwo_tus (dwarf2_cu *cu) dwo_file = dwo_unit->dwo_file; - for (struct dwo_unit *unit : dwo_file->tus) - queue_and_load_dwo_tu (unit, cu); + for (const dwo_unit_up &unit : dwo_file->tus) + queue_and_load_dwo_tu (unit.get (), cu); } /* Read in various DIEs. */ @@ -8778,7 +8850,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) struct dwarf2_locexpr_baton *dlbaton; struct dwarf_block *block = attr->as_block (); - dlbaton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); + dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_locexpr_baton); dlbaton->data = block->data; dlbaton->size = block->size; dlbaton->per_objfile = per_objfile; @@ -8877,7 +8950,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET; sect_offset sect_off = origin->get_ref_die_offset (); - if (!cu->header.offset_in_cu_p (sect_off)) + if (!cu->header.offset_in_unit_p (sect_off)) { /* As DW_OP_GNU_parameter_ref uses CU-relative offset this binding can be done only inside one CU. Such referenced DIE @@ -9245,7 +9318,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag, { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct objfile *objfile = per_objfile->objfile; - struct comp_unit_head *cu_header = &cu->header; + unit_head *cu_header = &cu->header; bfd *obfd = objfile->obfd.get (); unsigned int addr_size = cu_header->addr_size; CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); @@ -9901,69 +9974,44 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu) } } -/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset. Set - *OFFSET to the byte offset. If the attribute was not found return - 0, otherwise return 1. If it was found but could not properly be - handled, set *OFFSET to 0. */ +/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and + store the results in FIELD. */ -static int +static void handle_member_location (struct die_info *die, struct dwarf2_cu *cu, - LONGEST *offset) + struct field *field) { - struct attribute *attr; + const auto data_member_location_attr + = dwarf2_attr (die, DW_AT_data_member_location, cu); - attr = dwarf2_attr (die, DW_AT_data_member_location, cu); - if (attr != NULL) + if (data_member_location_attr != nullptr) { - *offset = 0; - CORE_ADDR temp; + bool has_bit_offset = false; + LONGEST bit_offset = 0; + LONGEST anonymous_size = 0; + const auto bit_offset_attr = dwarf2_attr (die, DW_AT_bit_offset, cu); - /* Note that we do not check for a section offset first here. - This is because DW_AT_data_member_location is new in DWARF 4, - so if we see it, we can assume that a constant form is really - a constant and not a section offset. */ - if (attr->form_is_constant ()) - *offset = attr->constant_value (0); - else if (attr->form_is_section_offset ()) - dwarf2_complex_location_expr_complaint (); - else if (attr->form_is_block () - && decode_locdesc (attr->as_block (), cu, &temp)) - { - *offset = temp; - } - else - dwarf2_complex_location_expr_complaint (); - - return 1; - } - else - { - attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); - if (attr != nullptr) + if (bit_offset_attr != nullptr && bit_offset_attr->form_is_constant ()) { - *offset = attr->constant_value (0); - return 1; - } - } + has_bit_offset = true; + bit_offset = bit_offset_attr->confused_constant ().value_or (0); - return 0; -} + const auto byte_size_attr = dwarf2_attr (die, DW_AT_byte_size, cu); -/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and - store the results in FIELD. */ - -static void -handle_member_location (struct die_info *die, struct dwarf2_cu *cu, - struct field *field) -{ - struct attribute *attr; + if (byte_size_attr != nullptr && byte_size_attr->form_is_constant ()) + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size + = byte_size_attr->unsigned_constant ().value_or (0); + } + } - attr = dwarf2_attr (die, DW_AT_data_member_location, cu); - if (attr != NULL) - { - if (attr->form_is_constant ()) + if (data_member_location_attr->form_is_constant ()) { - LONGEST offset = attr->constant_value (0); + LONGEST offset + = data_member_location_attr->confused_constant ().value_or (0); /* Work around this GCC 11 bug, where it would erroneously use -1 data member locations, instead of 0: @@ -9978,23 +10026,40 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu, } field->set_loc_bitpos (offset * bits_per_byte); + if (has_bit_offset) + apply_bit_offset_to_field (*field, bit_offset, anonymous_size); } - else if (attr->form_is_section_offset ()) - dwarf2_complex_location_expr_complaint (); - else if (attr->form_is_block ()) + else if (data_member_location_attr->form_is_block ()) { CORE_ADDR offset; - if (decode_locdesc (attr->as_block (), cu, &offset)) - field->set_loc_bitpos (offset * bits_per_byte); + if (decode_locdesc (data_member_location_attr->as_block (), cu, + &offset)) + { + field->set_loc_bitpos (offset * bits_per_byte); + + if (has_bit_offset) + apply_bit_offset_to_field (*field, bit_offset, anonymous_size); + } else { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct objfile *objfile = per_objfile->objfile; - struct dwarf2_locexpr_baton *dlbaton - = XOBNEW (&objfile->objfile_obstack, - struct dwarf2_locexpr_baton); - dlbaton->data = attr->as_block ()->data; - dlbaton->size = attr->as_block ()->size; + struct dwarf2_locexpr_baton *dlbaton; + if (has_bit_offset) + { + dwarf2_field_location_baton *flbaton + = OBSTACK_ZALLOC (&objfile->objfile_obstack, + dwarf2_field_location_baton); + flbaton->is_field_location = true; + flbaton->bit_offset = bit_offset; + flbaton->explicit_byte_size = anonymous_size; + dlbaton = flbaton; + } + else + dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_locexpr_baton); + dlbaton->data = data_member_location_attr->as_block ()->data; + dlbaton->size = data_member_location_attr->as_block ()->size; /* When using this baton, we want to compute the address of the field, not the value. This is why is_reference is set to false here. */ @@ -10002,28 +10067,74 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu, dlbaton->per_objfile = per_objfile; dlbaton->per_cu = cu->per_cu; - field->set_loc_dwarf_block (dlbaton); + field->set_loc_dwarf_block_addr (dlbaton); } } else - dwarf2_complex_location_expr_complaint (); + complaint (_("Unsupported form %s for DW_AT_data_member_location"), + dwarf_form_name (data_member_location_attr->form)); } else { - attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); - if (attr != nullptr) - field->set_loc_bitpos (attr->constant_value (0)); + const auto data_bit_offset_attr + = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + + if (data_bit_offset_attr != nullptr) + { + if (data_bit_offset_attr->form_is_constant ()) + field->set_loc_bitpos (data_bit_offset_attr->unsigned_constant () + .value_or (0)); + else if (data_bit_offset_attr->form_is_block ()) + { + /* This is a DWARF extension. See + https://dwarfstd.org/issues/250501.1.html. */ + dwarf2_per_objfile *per_objfile = cu->per_objfile; + dwarf2_locexpr_baton *dlbaton + = OBSTACK_ZALLOC (&per_objfile->objfile->objfile_obstack, + dwarf2_locexpr_baton); + dlbaton->data = data_bit_offset_attr->as_block ()->data; + dlbaton->size = data_bit_offset_attr->as_block ()->size; + dlbaton->per_objfile = per_objfile; + dlbaton->per_cu = cu->per_cu; + + field->set_loc_dwarf_block_bitpos (dlbaton); + } + else + complaint (_("Unsupported form %s for DW_AT_data_bit_offset"), + dwarf_form_name (data_bit_offset_attr->form)); + } } } +/* A helper that computes the location of a field. The CU and the + DW_TAG_member DIE are passed in. The results are stored in + *FP. */ + +static void +compute_field_location (dwarf2_cu *cu, die_info *die, field *fp) +{ + /* Get type of field. */ + fp->set_type (die_type (die, cu)); + + fp->set_loc_bitpos (0); + + /* Get bit size of field (zero if none). */ + attribute *attr = dwarf2_attr (die, DW_AT_bit_size, cu); + if (attr != nullptr) + fp->set_bitsize (attr->unsigned_constant ().value_or (0)); + else + fp->set_bitsize (0); + + /* Get bit offset of field. */ + handle_member_location (die, cu, fp); +} + /* Add an aggregate field to the field list. */ static void dwarf2_add_field (struct field_info *fip, struct die_info *die, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->per_objfile->objfile; - struct gdbarch *gdbarch = objfile->arch (); struct nextfield *new_field; struct attribute *attr; struct field *fp; @@ -10073,64 +10184,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } /* Data member other than a C++ static data member. */ - /* Get type of field. */ - fp->set_type (die_type (die, cu)); - - fp->set_loc_bitpos (0); - - /* Get bit size of field (zero if none). */ - attr = dwarf2_attr (die, DW_AT_bit_size, cu); - if (attr != nullptr) - fp->set_bitsize (attr->constant_value (0)); - else - fp->set_bitsize (0); - - /* Get bit offset of field. */ - handle_member_location (die, cu, fp); - attr = dwarf2_attr (die, DW_AT_bit_offset, cu); - if (attr != nullptr && attr->form_is_constant ()) - { - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) - { - /* For big endian bits, the DW_AT_bit_offset gives the - additional bit offset from the MSB of the containing - 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. */ - fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0)); - } - else - { - /* For little endian bits, compute the bit offset to the - MSB of the anonymous object, subtract off the number of - bits from the MSB of the field to the MSB of the - object, and then subtract off the number of bits of - the field itself. The result is the bit offset of - the LSB of the field. */ - int anonymous_size; - int bit_offset = attr->constant_value (0); - - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr != nullptr && attr->form_is_constant ()) - { - /* The size of the anonymous object containing - the bit field is explicit, so use the - indicated size (in bytes). */ - anonymous_size = attr->constant_value (0); - } - else - { - /* The size of the anonymous object containing - the bit field must be inferred from the type - attribute of the data member containing the - bit field. */ - anonymous_size = fp->type ()->length (); - } - fp->set_loc_bitpos (fp->loc_bitpos () - + anonymous_size * bits_per_byte - - bit_offset - fp->bitsize ()); - } - } + compute_field_location (cu, die, fp); /* Get name of field. */ fieldname = dwarf2_name (die, cu); @@ -10269,13 +10323,19 @@ convert_variant_range (struct obstack *obstack, const variant_field &variant, { std::vector<discriminant_range> ranges; - if (variant.default_branch) + if (variant.is_default ()) return {}; if (variant.discr_list_data == nullptr) { - discriminant_range r - = {variant.discriminant_value, variant.discriminant_value}; + ULONGEST value; + + if (is_unsigned) + value = variant.discriminant_attr->unsigned_constant ().value_or (0); + else + value = variant.discriminant_attr->signed_constant ().value_or (0); + + discriminant_range r = { value, value }; ranges.push_back (r); } else @@ -10572,7 +10632,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, smash_to_method_type (fnp->type, type, this_type->target_type (), this_type->fields (), - this_type->num_fields (), this_type->has_varargs ()); /* Handle static member functions. @@ -10794,8 +10853,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile) self_type = pfn_type->field (0).type ()->target_type (); new_type = type_allocator (type).new_type (); smash_to_method_type (new_type, self_type, pfn_type->target_type (), - pfn_type->fields (), pfn_type->num_fields (), - pfn_type->has_varargs ()); + pfn_type->fields (), pfn_type->has_varargs ()); smash_to_methodptr_type (type, new_type); } @@ -11089,7 +11147,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) if (attr != nullptr) { if (attr->form_is_constant ()) - type->set_length (attr->constant_value (0)); + type->set_length (attr->unsigned_constant ().value_or (0)); else { struct dynamic_prop prop; @@ -11234,12 +11292,14 @@ handle_variant (struct die_info *die, struct type *type, { discr = dwarf2_attr (die, DW_AT_discr_list, cu); if (discr == nullptr || discr->as_block ()->size == 0) - variant.default_branch = true; + { + /* Nothing to do here -- default branch. */ + } else variant.discr_list_data = discr->as_block (); } else - variant.discriminant_value = discr->constant_value (0); + variant.discriminant_attr = discr; for (die_info *variant_child : die->children ()) handle_struct_member_die (variant_child, type, fi, template_args, cu); @@ -11301,6 +11361,21 @@ handle_struct_member_die (struct die_info *child_die, struct type *type, handle_variant (child_die, type, fi, template_args, cu); } +/* Create a property baton for a field. DIE is the field's DIE. The + baton's "field" member is filled in, but the other members of the + baton are not. The new property baton is returned. */ + +static dwarf2_property_baton * +find_field_create_baton (dwarf2_cu *cu, die_info *die) +{ + dwarf2_property_baton *result + = XOBNEW (&cu->per_objfile->objfile->objfile_obstack, + struct dwarf2_property_baton); + memset (&result->field, 0, sizeof (result->field)); + compute_field_location (cu, die, &result->field); + return result; +} + /* 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 @@ -11565,25 +11640,30 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order) /* Assuming DIE is an enumeration type, and TYPE is its associated type, update TYPE using some information only available in DIE's - children. In particular, the fields are computed. */ + children. In particular, the fields are computed. If IS_UNSIGNED + is set, the enumeration type's sign is already known (a true value + means unsigned), and so examining the constants to determine the + sign isn't needed; when this is unset, the enumerator constants are + read as signed values. */ static void update_enumeration_type_from_children (struct die_info *die, struct type *type, - struct dwarf2_cu *cu) + struct dwarf2_cu *cu, + std::optional<bool> is_unsigned) { - int unsigned_enum = 1; - int flag_enum = 1; + /* This is used to check whether the enum is signed or unsigned; for + simplicity, it is always correct regardless of whether + IS_UNSIGNED is set. */ + bool unsigned_enum = is_unsigned.value_or (true); + bool flag_enum = true; - auto_obstack obstack; std::vector<struct field> fields; for (die_info *child_die : die->children ()) { struct attribute *attr; LONGEST value; - const gdb_byte *bytes; - struct dwarf2_locexpr_baton *baton; const char *name; if (child_die->tag != DW_TAG_enumerator) @@ -11597,19 +11677,26 @@ update_enumeration_type_from_children (struct die_info *die, if (name == NULL) name = "<anonymous enumerator>"; - dwarf2_const_value_attr (attr, type, name, &obstack, cu, - &value, &bytes, &baton); - if (value < 0) - { - unsigned_enum = 0; - flag_enum = 0; - } + /* Can't check UNSIGNED_ENUM here because that is + optimistic. */ + if (is_unsigned.has_value () && *is_unsigned) + value = attr->unsigned_constant ().value_or (0); else { - if (count_one_bits_ll (value) >= 2) - flag_enum = 0; + /* Read as signed, either because we don't know the sign or + because we know it is definitely signed. */ + value = attr->signed_constant ().value_or (0); + + if (value < 0) + { + unsigned_enum = false; + flag_enum = false; + } } + if (flag_enum && count_one_bits_ll (value) >= 2) + flag_enum = false; + struct field &field = fields.emplace_back (); field.set_name (dwarf2_physname (name, child_die, cu)); field.set_loc_enumval (value); @@ -11618,13 +11705,10 @@ update_enumeration_type_from_children (struct die_info *die, if (!fields.empty ()) type->copy_fields (fields); else - flag_enum = 0; - - if (unsigned_enum) - type->set_is_unsigned (true); + flag_enum = false; - if (flag_enum) - type->set_is_flag_enum (true); + type->set_is_unsigned (unsigned_enum); + type->set_is_flag_enum (flag_enum); } /* Given a DW_AT_enumeration_type die, set its type. We do not @@ -11668,7 +11752,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr != nullptr) - type->set_length (attr->constant_value (0)); + type->set_length (attr->unsigned_constant ().value_or (0)); else type->set_length (0); @@ -11682,6 +11766,11 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) if (die_is_declaration (die, cu)) type->set_is_stub (true); + /* If the underlying type is known, and is unsigned, then we'll + assume the enumerator constants are unsigned. Otherwise we have + to assume they are signed. */ + std::optional<bool> is_unsigned; + /* If this type has an underlying type that is not a stub, then we may use its attributes. We always use the "unsigned" attribute in this situation, because ordinarily we guess whether the type @@ -11694,7 +11783,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) struct type *underlying_type = type->target_type (); underlying_type = check_typedef (underlying_type); - type->set_is_unsigned (underlying_type->is_unsigned ()); + is_unsigned = underlying_type->is_unsigned (); + type->set_is_unsigned (*is_unsigned); if (type->length () == 0) type->set_length (underlying_type->length ()); @@ -11714,7 +11804,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) Note that, as usual, this must come after set_die_type to avoid infinite recursion when trying to compute the names of the enumerators. */ - update_enumeration_type_from_children (die, type, cu); + update_enumeration_type_from_children (die, type, cu, is_unsigned); return type; } @@ -12064,7 +12154,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_bit_stride, cu); if (attr != NULL) - bit_stride = attr->constant_value (0); + bit_stride = attr->unsigned_constant ().value_or (0); /* Irix 6.2 native cc creates array types without children for arrays with unspecified length. */ @@ -12279,7 +12369,8 @@ mark_common_block_symbol_computed (struct symbol *sym, gdb_assert (member_loc->form_is_block () || member_loc->form_is_constant ()); - baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); + baton = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_locexpr_baton); baton->per_objfile = per_objfile; baton->per_cu = cu->per_cu; gdb_assert (baton->per_cu); @@ -12288,7 +12379,7 @@ mark_common_block_symbol_computed (struct symbol *sym, if (member_loc->form_is_constant ()) { - offset = member_loc->constant_value (0); + offset = member_loc->unsigned_constant ().value_or (0); baton->size += 1 /* DW_OP_addr */ + cu->header.addr_size; } else @@ -12321,7 +12412,7 @@ mark_common_block_symbol_computed (struct symbol *sym, gdb_assert (ptr - baton->data == baton->size); SYMBOL_LOCATION_BATON (sym) = baton; - sym->set_aclass_index (dwarf2_locexpr_index); + sym->set_loc_class_index (dwarf2_locexpr_index); } /* Create appropriate locally-scoped variables for all the @@ -12585,7 +12676,7 @@ static struct type * read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) { struct gdbarch *gdbarch = cu->per_objfile->objfile->arch (); - struct comp_unit_head *cu_header = &cu->header; + unit_head *cu_header = &cu->header; struct type *type; struct attribute *attr_byte_size; struct attribute *attr_address_class; @@ -12603,7 +12694,8 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr_byte_size) - byte_size = attr_byte_size->constant_value (cu_header->addr_size); + byte_size = (attr_byte_size->unsigned_constant () + .value_or (cu_header->addr_size)); else byte_size = cu_header->addr_size; @@ -12682,8 +12774,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu) = type_allocator (cu->per_objfile->objfile, cu->lang ()).new_type (); smash_to_method_type (new_type, domain, to_type->target_type (), - to_type->fields (), to_type->num_fields (), - to_type->has_varargs ()); + to_type->fields (), to_type->has_varargs ()); type = lookup_methodptr_type (new_type); } else @@ -12699,7 +12790,7 @@ static struct type * read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu, enum type_code refcode) { - struct comp_unit_head *cu_header = &cu->header; + unit_head *cu_header = &cu->header; struct type *type, *target_type; struct attribute *attr; @@ -12715,7 +12806,8 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu, type = lookup_reference_type (target_type, refcode); attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr != nullptr) - type->set_length (attr->constant_value (cu_header->addr_size)); + type->set_length (attr->unsigned_constant () + .value_or (cu_header->addr_size)); else type->set_length (cu_header->addr_size); @@ -12879,9 +12971,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) len = dwarf2_attr (die, DW_AT_byte_size, cu); if (len != nullptr && len->form_is_constant ()) { - /* 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); + LONGEST sz = len->unsigned_constant ().value_or (0); prop_type = objfile_int_type (objfile, sz, true); } else @@ -12900,15 +12990,14 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) else if (attr != nullptr) { /* This DW_AT_string_length just contains the length with no - indirection. There's no need to create a dynamic property in this - case. Pass 0 for the default value as we know it will not be - returned in this case. */ - length = attr->constant_value (0); + indirection. There's no need to create a dynamic property in + this case. */ + length = attr->unsigned_constant ().value_or (0); } else if ((attr = dwarf2_attr (die, DW_AT_byte_size, cu)) != nullptr) { /* We don't currently support non-constant byte sizes for strings. */ - length = attr->constant_value (1); + length = attr->unsigned_constant ().value_or (1); } else { @@ -13183,7 +13272,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu) a given gmp_mpz given an attribute. */ static void -get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr) +get_mpz_for_rational (dwarf2_cu *cu, gdb_mpz *value, attribute *attr) { /* GCC will sometimes emit a 16-byte constant value as a DWARF location expression that pushes an implicit value. */ @@ -13217,10 +13306,11 @@ get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE, true); } - else if (attr->form_is_unsigned ()) - *value = gdb_mpz (attr->as_unsigned ()); else - *value = gdb_mpz (attr->constant_value (1)); + { + /* Rational constants for Ada are always unsigned. */ + *value = gdb_mpz (attr->unsigned_constant ().value_or (1)); + } } /* Assuming DIE is a rational DW_TAG_constant, read the DIE's @@ -13249,8 +13339,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu, if (num_attr == nullptr || denom_attr == nullptr) return; - get_mpz (cu, numerator, num_attr); - get_mpz (cu, denominator, denom_attr); + get_mpz_for_rational (cu, numerator, num_attr); + get_mpz_for_rational (cu, denominator, denom_attr); } /* Same as get_dwarf2_rational_constant, but extracting an unsigned @@ -13399,14 +13489,14 @@ finish_fixed_point_type (struct type *type, const char *suffix, } else if (attr->name == DW_AT_binary_scale) { - LONGEST scale_exp = attr->constant_value (0); + LONGEST scale_exp = attr->signed_constant ().value_or (0); gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom; num_or_denom <<= std::abs (scale_exp); } else if (attr->name == DW_AT_decimal_scale) { - LONGEST scale_exp = attr->constant_value (0); + LONGEST scale_exp = attr->signed_constant ().value_or (0); gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom; num_or_denom = gdb_mpz::pow (10, std::abs (scale_exp)); @@ -13606,7 +13696,6 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type; struct attribute *attr; ULONGEST encoding = 0; - int bits = 0; const char *name; attr = dwarf2_attr (die, DW_AT_encoding, cu); @@ -13616,9 +13705,33 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) if (value.has_value ()) encoding = *value; } + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + std::optional<ULONGEST> byte_size; + if (attr != nullptr) + byte_size = attr->unsigned_constant (); + attr = dwarf2_attr (die, DW_AT_bit_size, cu); + std::optional<ULONGEST> bit_size; if (attr != nullptr) - bits = attr->constant_value (0) * TARGET_CHAR_BIT; + bit_size = attr->unsigned_constant (); + + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + std::optional<ULONGEST> bit_offset; + if (attr != nullptr) + bit_offset = attr->unsigned_constant (); + + int bits = 0; + if (byte_size.has_value ()) + bits = TARGET_CHAR_BIT * *byte_size; + else if (bit_size.has_value ()) + bits = align_up (*bit_size, 8); + else + { + /* No size, so arrange for an error type. */ + complaint (_("DW_TAG_base_type has neither bit- nor byte-size")); + encoding = (ULONGEST) -1; + } + name = dwarf2_full_name (nullptr, die, cu); if (!name) complaint (_("DW_AT_name missing from DW_TAG_base_type")); @@ -13764,29 +13877,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) type->set_endianity_is_not_default (not_default); - if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT) + /* If both a byte size and bit size were provided, then that means + that not every bit in the object contributes to the value. */ + if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT + && byte_size.has_value () + && bit_size.has_value ()) { - attr = dwarf2_attr (die, DW_AT_bit_size, cu); - if (attr != nullptr && attr->form_is_constant ()) + /* DWARF says: If this attribute is omitted a default data bit + offset of zero is assumed. */ + ULONGEST offset = bit_offset.value_or (0); + + /* Only use the attributes if they make sense together. */ + if (*bit_size + offset <= 8 * type->length ()) { - unsigned real_bit_size = attr->constant_value (0); - if (real_bit_size >= 0 && real_bit_size <= 8 * type->length ()) - { - attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); - /* Only use the attributes if they make sense together. */ - if (attr == nullptr - || (attr->form_is_constant () - && attr->constant_value (0) >= 0 - && (attr->constant_value (0) + real_bit_size - <= 8 * type->length ()))) - { - TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size - = real_bit_size; - if (attr != nullptr) - TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset - = attr->constant_value (0); - } - } + TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size = *bit_size; + TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset = offset; } } @@ -13927,17 +14032,13 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, case DW_AT_data_member_location: case DW_AT_data_bit_offset: { - LONGEST offset; - - if (!handle_member_location (target_die, target_cu, &offset)) + baton = find_field_create_baton (cu, target_die); + if (baton == nullptr) return 0; - baton = XOBNEW (obstack, struct dwarf2_property_baton); baton->property_type = read_type_die (target_die->parent, - target_cu); - baton->offset_info.offset = offset; - baton->offset_info.type = die_type (target_die, target_cu); - prop->set_addr_offset (baton); + target_cu); + prop->set_field (baton); break; } } @@ -14097,8 +14198,13 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) LONGEST bias = 0; struct attribute *bias_attr = dwarf2_attr (die, DW_AT_GNU_bias, cu); - if (bias_attr != nullptr && bias_attr->form_is_constant ()) - bias = bias_attr->constant_value (0); + if (bias_attr != nullptr) + { + if (base_type->is_unsigned ()) + bias = (LONGEST) bias_attr->unsigned_constant ().value_or (0); + else + bias = bias_attr->signed_constant ().value_or (0); + } /* Normally, the DWARF producers are expected to use a signed constant form (Eg. DW_FORM_sdata) to express negative bounds. @@ -14185,7 +14291,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr != nullptr) - range_type->set_length (attr->constant_value (0)); + range_type->set_length (attr->unsigned_constant ().value_or (0)); maybe_set_alignment (cu, die, range_type); @@ -14866,7 +14972,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form, { dwarf2_per_objfile *per_objfile = m_cu->per_objfile; struct objfile *objfile = per_objfile->objfile; - struct comp_unit_head *cu_header = &m_cu->header; + unit_head *cu_header = &m_cu->header; unsigned int bytes_read; struct dwarf_block *blk; @@ -15174,8 +15280,7 @@ read_indirect_string_at_offset (dwarf2_per_objfile *per_objfile, static const char * read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *abfd, - const gdb_byte *buf, - const struct comp_unit_head *cu_header, + const gdb_byte *buf, const unit_head *cu_header, unsigned int *bytes_read_ptr) { LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr); @@ -15199,7 +15304,7 @@ dwarf2_per_objfile::read_line_string (const gdb_byte *buf, const char * dwarf2_per_objfile::read_line_string (const gdb_byte *buf, - const struct comp_unit_head *cu_header, + const unit_head *cu_header, unsigned int *bytes_read_ptr) { bfd *abfd = objfile->obfd.get (); @@ -15332,9 +15437,16 @@ read_str_index (struct dwarf2_cu *cu, " in CU at offset %s [in module %s]"), form_name, str_section->get_name (), sect_offset_str (cu->header.sect_off), objf_name); - info_ptr = (str_offsets_section->buffer - + str_offsets_base - + str_index * offset_size); + + ULONGEST str_offsets_offset = str_offsets_base + str_index * offset_size; + if (str_offsets_offset >= str_offsets_section->size) + error (_(DWARF_ERROR_PREFIX + "Offset from %s pointing outside of %s section in CU at offset %s" + " [in module %s]"), + form_name, str_offsets_section->get_name (), + sect_offset_str (cu->header.sect_off), objf_name); + info_ptr = str_offsets_section->buffer + str_offsets_offset; + if (offset_size == 4) str_offset = bfd_get_32 (abfd, info_ptr); else @@ -16531,7 +16643,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu) { struct objfile *objfile = cu->per_objfile->objfile; - struct comp_unit_head *cu_header = &cu->header; + unit_head *cu_header = &cu->header; /* NOTE drow/2003-01-30: There used to be a comment and some special code here to turn a symbol with DW_AT_external and a @@ -16547,7 +16659,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym, variable has been optimized away. */ if (attr->form_is_block () && attr->as_block ()->size == 0) { - sym->set_aclass_index (LOC_OPTIMIZED_OUT); + sym->set_loc_class_index (LOC_OPTIMIZED_OUT); return; } @@ -16577,7 +16689,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym, else tem = read_addr_index_from_leb128 (cu, block->data + 1, &dummy); sym->set_value_address ((CORE_ADDR) tem); - sym->set_aclass_index (LOC_STATIC); + sym->set_loc_class_index (LOC_STATIC); fixup_symbol_section (sym, objfile); sym->set_value_address (sym->value_address () @@ -16614,7 +16726,7 @@ add_ada_export_symbol (struct symbol *orig, const char *new_name, = new (&cu->per_objfile->objfile->objfile_obstack) symbol (*orig); copy->set_linkage_name (new_name); SYMBOL_LOCATION_BATON (copy) = (void *) orig_name; - copy->set_aclass_index (copy->aclass () == LOC_BLOCK + copy->set_loc_class_index (copy->loc_class () == LOC_BLOCK ? ada_block_index : ada_imported_index); add_symbol_to_list (copy, list_to_add); @@ -16714,7 +16826,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* Default assumptions. Use the passed type or decode it from the die. */ sym->set_domain (UNDEF_DOMAIN); - sym->set_aclass_index (LOC_OPTIMIZED_OUT); + sym->set_loc_class_index (LOC_OPTIMIZED_OUT); if (type != NULL) sym->set_type (type); else @@ -16764,10 +16876,10 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, CORE_ADDR addr = per_objfile->relocate (attr->as_address ()); sym->set_section_index (SECT_OFF_TEXT (objfile)); sym->set_value_address (addr); - sym->set_aclass_index (LOC_LABEL); + sym->set_loc_class_index (LOC_LABEL); } else - sym->set_aclass_index (LOC_OPTIMIZED_OUT); + sym->set_loc_class_index (LOC_OPTIMIZED_OUT); sym->set_type (builtin_type (objfile)->builtin_core_addr); sym->set_domain (LABEL_DOMAIN); list_to_add = cu->list_in_scope; @@ -16776,7 +16888,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by finish_block. */ sym->set_domain (FUNCTION_DOMAIN); - sym->set_aclass_index (LOC_BLOCK); + sym->set_loc_class_index (LOC_BLOCK); /* DW_TAG_entry_point provides an additional entry_point to an existing sub_program. Therefore, we inherit the "external" attribute from the sub_program to which the entry_point @@ -16791,7 +16903,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by finish_block. */ sym->set_domain (FUNCTION_DOMAIN); - sym->set_aclass_index (LOC_BLOCK); + sym->set_loc_class_index (LOC_BLOCK); attr2 = dwarf2_attr (die, DW_AT_external, cu); if ((attr2 != nullptr && attr2->as_boolean ()) || cu->lang () == language_ada @@ -16820,7 +16932,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* For Import, create a symbol using the source name, and have it refer to the linkage name. */ SYMBOL_LOCATION_BATON (sym) = (void *) linkagename; - sym->set_aclass_index (ada_block_index); + sym->set_loc_class_index (ada_block_index); } else { @@ -16836,7 +16948,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by finish_block. */ sym->set_domain (FUNCTION_DOMAIN); - sym->set_aclass_index (LOC_BLOCK); + sym->set_loc_class_index (LOC_BLOCK); sym->set_is_inlined (1); list_to_add = cu->list_in_scope; break; @@ -16888,7 +17000,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, && die->parent->tag == DW_TAG_common_block) attr2 = NULL; - if (sym->aclass () == LOC_STATIC + if (sym->loc_class () == LOC_STATIC && sym->value_address () == 0 && !per_objfile->per_bfd->has_section_at_zero) { @@ -16899,7 +17011,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, } else if (attr2 != nullptr && attr2->as_boolean ()) { - if (sym->aclass () == LOC_STATIC + if (sym->loc_class () == LOC_STATIC && (objfile->flags & OBJF_MAINLINE) == 0 && per_objfile->per_bfd->can_copy) { @@ -16968,7 +17080,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, ? cu->get_builder ()->get_global_symbols () : cu->list_in_scope); SYMBOL_LOCATION_BATON (sym) = (void *) linkagename; - sym->set_aclass_index (ada_imported_index); + sym->set_loc_class_index (ada_imported_index); } else if (attr2 != nullptr && attr2->as_boolean () && dwarf2_attr (die, DW_AT_type, cu) != NULL) @@ -16981,12 +17093,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, ? cu->get_builder ()->get_global_symbols () : cu->list_in_scope); - sym->set_aclass_index (LOC_UNRESOLVED); + sym->set_loc_class_index (LOC_UNRESOLVED); } else if (!die_is_declaration (die, cu)) { /* Use the default LOC_OPTIMIZED_OUT class. */ - gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT); + gdb_assert (sym->loc_class () == LOC_OPTIMIZED_OUT); if (!suppress_add) list_to_add = cu->list_in_scope; } @@ -17042,13 +17154,13 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, there's a special hack for C++ in the matching code, so we don't need to enter a separate typedef for the tag. */ - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); sym->set_domain (STRUCT_DOMAIN); } else { /* Other languages don't have a tag namespace. */ - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); sym->set_domain (TYPE_DOMAIN); } @@ -17093,7 +17205,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, case DW_TAG_base_type: case DW_TAG_subrange_type: case DW_TAG_generic_subrange: - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); sym->set_domain (TYPE_DOMAIN); list_to_add = cu->list_in_scope; break; @@ -17117,21 +17229,21 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, case DW_TAG_imported_declaration: case DW_TAG_namespace: sym->set_domain (TYPE_DOMAIN); - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); list_to_add = cu->get_builder ()->get_global_symbols (); break; case DW_TAG_module: - sym->set_aclass_index (LOC_TYPEDEF); + sym->set_loc_class_index (LOC_TYPEDEF); sym->set_domain (MODULE_DOMAIN); list_to_add = cu->get_builder ()->get_global_symbols (); break; case DW_TAG_common_block: - sym->set_aclass_index (LOC_COMMON_BLOCK); + sym->set_loc_class_index (LOC_COMMON_BLOCK); sym->set_domain (COMMON_BLOCK_DOMAIN); list_to_add = cu->list_in_scope; break; case DW_TAG_namelist: - sym->set_aclass_index (LOC_STATIC); + sym->set_loc_class_index (LOC_STATIC); sym->set_domain (VAR_DOMAIN); list_to_add = cu->list_in_scope; break; @@ -17164,40 +17276,6 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, return (sym); } -/* Given an attr with a DW_FORM_dataN value in host byte order, - zero-extend it as appropriate for the symbol's type. The DWARF - standard (v4) is not entirely clear about the meaning of using - DW_FORM_dataN for a constant with a signed type, where the type is - wider than the data. The conclusion of a discussion on the DWARF - list was that this is unspecified. We choose to always zero-extend - because that is the interpretation long in use by GCC. */ - -static gdb_byte * -dwarf2_const_value_data (const struct attribute *attr, struct obstack *obstack, - struct dwarf2_cu *cu, LONGEST *value, int bits) -{ - struct objfile *objfile = cu->per_objfile->objfile; - enum bfd_endian byte_order = bfd_big_endian (objfile->obfd.get ()) ? - BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; - LONGEST l = attr->constant_value (0); - - if (bits < sizeof (*value) * 8) - { - l &= ((LONGEST) 1 << bits) - 1; - *value = l; - } - else if (bits == sizeof (*value) * 8) - *value = l; - else - { - gdb_byte *bytes = (gdb_byte *) obstack_alloc (obstack, bits / 8); - store_unsigned_integer (bytes, bits / 8, byte_order, l); - return bytes; - } - - return NULL; -} - /* Read a constant value from an attribute. Either set *VALUE, or if the value does not fit in *VALUE, set *BYTES - either already allocated on the objfile obstack, or newly allocated on OBSTACK, @@ -17213,7 +17291,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct objfile *objfile = per_objfile->objfile; - struct comp_unit_head *cu_header = &cu->header; + unit_head *cu_header = &cu->header; struct dwarf_block *blk; enum bfd_endian byte_order = (bfd_big_endian (objfile->obfd.get ()) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE); @@ -17237,7 +17315,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, /* Symbols of this form are reasonably rare, so we just piggyback on the existing location code rather than writing a new implementation of symbol_computed_ops. */ - *baton = XOBNEW (obstack, struct dwarf2_locexpr_baton); + *baton = OBSTACK_ZALLOC (obstack, struct dwarf2_locexpr_baton); (*baton)->per_objfile = per_objfile; (*baton)->per_cu = cu->per_cu; gdb_assert ((*baton)->per_cu); @@ -17281,25 +17359,13 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, converted to host endianness, so we just need to sign- or zero-extend it as appropriate. */ case DW_FORM_data1: - *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 8); - break; case DW_FORM_data2: - *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 16); - break; case DW_FORM_data4: - *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 32); - break; case DW_FORM_data8: - *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 64); - break; - case DW_FORM_sdata: case DW_FORM_implicit_const: - *value = attr->as_signed (); - break; - case DW_FORM_udata: - *value = attr->as_unsigned (); + *value = attr->confused_constant ().value_or (0); break; default: @@ -17330,17 +17396,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym, if (baton != NULL) { SYMBOL_LOCATION_BATON (sym) = baton; - sym->set_aclass_index (dwarf2_locexpr_index); + sym->set_loc_class_index (dwarf2_locexpr_index); } else if (bytes != NULL) { sym->set_value_bytes (bytes); - sym->set_aclass_index (LOC_CONST_BYTES); + sym->set_loc_class_index (LOC_CONST_BYTES); } else { sym->set_value_longest (value); - sym->set_aclass_index (LOC_CONST); + sym->set_loc_class_index (LOC_CONST); } } @@ -17466,9 +17532,10 @@ lookup_die_type (struct die_info *die, const struct attribute *attr, if (attr->form_is_alt ()) { + const auto §ion = get_section_for_ref (*attr, cu); sect_offset sect_off = attr->get_ref_die_offset (); dwarf2_per_cu *per_cu - = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile->per_bfd); + = dwarf2_find_containing_unit ({ §ion, sect_off }, per_objfile); this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile); } @@ -18169,14 +18236,13 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr, return die; } -/* Follow reference OFFSET. - On entry *REF_CU is the CU of the source die referencing OFFSET. +/* Follow reference TARGET. + On entry *REF_CU is the CU of the source die referencing TARGET. On exit *REF_CU is the CU of the result. - Returns NULL if OFFSET is invalid. */ + Returns nullptr if TARGET is invalid. */ -static struct die_info * -follow_die_offset (sect_offset sect_off, int offset_in_dwz, - struct dwarf2_cu **ref_cu) +static die_info * +follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu) { dwarf2_cu *source_cu = *ref_cu; dwarf2_cu *target_cu = source_cu; @@ -18188,23 +18254,23 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, " "source CU contains target offset: %d", sect_offset_str (source_cu->per_cu->sect_off), - sect_offset_str (sect_off), - source_cu->header.offset_in_cu_p (sect_off)); + sect_offset_str (target.offset), + (target.section == &source_cu->section () + && source_cu->header.offset_in_unit_p (target.offset))); if (source_cu->per_cu->is_debug_types) { /* .debug_types CUs cannot reference anything outside their CU. If they need to, they have to reference a signatured type via DW_FORM_ref_sig8. */ - if (!source_cu->header.offset_in_cu_p (sect_off)) + if (!source_cu->header.offset_in_unit_p (target.offset)) return NULL; } - else if (offset_in_dwz != source_cu->per_cu->is_dwz - || !source_cu->header.offset_in_cu_p (sect_off)) + else if (target.section != &source_cu->section () + || !source_cu->header.offset_in_unit_p (target.offset)) { dwarf2_per_cu *target_per_cu - = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, - per_objfile->per_bfd); + = dwarf2_find_containing_unit (target, per_objfile); dwarf_read_debug_printf_v ("target CU offset: %s, " "target CU DIEs loaded: %d", @@ -18226,14 +18292,13 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, error (_(DWARF_ERROR_PREFIX "cannot follow reference to DIE at %s" " [in module %s]"), - sect_offset_str (sect_off), + sect_offset_str (target.offset), objfile_name (per_objfile->objfile)); } *ref_cu = target_cu; - auto it = target_cu->die_hash.find (sect_off); - return it != target_cu->die_hash.end () ? *it : nullptr; + return target_cu->find_die (target.offset); } /* Follow reference attribute ATTR of SRC_DIE. @@ -18245,8 +18310,7 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr, struct dwarf2_cu **ref_cu) { sect_offset sect_off = attr->get_ref_die_offset (); - struct dwarf2_cu *cu = *ref_cu; - struct die_info *die; + struct dwarf2_cu *src_cu = *ref_cu; if (!attr->form_is_alt () && src_die->sect_off == sect_off) { @@ -18254,14 +18318,13 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr, return src_die; } - die = follow_die_offset (sect_off, - attr->form_is_alt () || cu->per_cu->is_dwz, - ref_cu); - if (!die) + const dwarf2_section_info §ion = get_section_for_ref (*attr, src_cu); + die_info *die = follow_die_offset ({ §ion, sect_off }, ref_cu); + if (die == nullptr) error (_(DWARF_ERROR_PREFIX "Cannot find DIE at %s referenced from DIE at %s [in module %s]"), sect_offset_str (sect_off), sect_offset_str (src_die->sect_off), - objfile_name (cu->per_objfile->objfile)); + objfile_name (src_cu->per_objfile->objfile)); return die; } @@ -18274,7 +18337,6 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu, gdb::function_view<CORE_ADDR ()> get_frame_pc, bool resolve_abstract_p) { - struct die_info *die; struct attribute *attr; struct dwarf2_locexpr_baton retval; struct objfile *objfile = per_objfile->objfile; @@ -18292,8 +18354,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu, sect_offset_str (sect_off), objfile_name (objfile)); } - die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); - if (!die) + die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu); + if (die == nullptr) error (_(DWARF_ERROR_PREFIX "Cannot find DIE at %s referenced [in module %s]"), sect_offset_str (sect_off), objfile_name (objfile)); @@ -18309,8 +18371,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu, : per_objfile->per_bfd->abstract_to_concrete[die->sect_off]) { struct dwarf2_cu *cand_cu = cu; - struct die_info *cand - = follow_die_offset (cand_off, per_cu->is_dwz, &cand_cu); + die_info *cand + = follow_die_offset ({ &cu->section (), cand_off }, &cand_cu); if (!cand || !cand->parent || cand->parent->tag != DW_TAG_subprogram) @@ -18412,7 +18474,6 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off, obstack *obstack, LONGEST *len) { - struct die_info *die; struct attribute *attr; const gdb_byte *result = NULL; struct type *type; @@ -18433,7 +18494,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off, sect_offset_str (sect_off), objfile_name (objfile)); } - die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); + die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu); if (!die) error (_(DWARF_ERROR_PREFIX "Cannot find DIE at %s referenced [in module %s]"), @@ -18492,47 +18553,19 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off, symbol's value "represented as it would be on the target architecture." By the time we get here, it's already been converted to host endianness, so we just need to sign- or - zero-extend it as appropriate. */ + zero-extend it as appropriate. + + Both GCC and LLVM agree that these are always signed, though. */ case DW_FORM_data1: - type = die_type (die, cu); - result = dwarf2_const_value_data (attr, obstack, cu, &value, 8); - if (result == NULL) - result = write_constant_as_bytes (obstack, byte_order, - type, value, len); - break; case DW_FORM_data2: - type = die_type (die, cu); - result = dwarf2_const_value_data (attr, obstack, cu, &value, 16); - if (result == NULL) - result = write_constant_as_bytes (obstack, byte_order, - type, value, len); - break; case DW_FORM_data4: - type = die_type (die, cu); - result = dwarf2_const_value_data (attr, obstack, cu, &value, 32); - if (result == NULL) - result = write_constant_as_bytes (obstack, byte_order, - type, value, len); - break; case DW_FORM_data8: - type = die_type (die, cu); - result = dwarf2_const_value_data (attr, obstack, cu, &value, 64); - if (result == NULL) - result = write_constant_as_bytes (obstack, byte_order, - type, value, len); - break; - case DW_FORM_sdata: case DW_FORM_implicit_const: - type = die_type (die, cu); - result = write_constant_as_bytes (obstack, byte_order, - type, attr->as_signed (), len); - break; - case DW_FORM_udata: type = die_type (die, cu); - result = write_constant_as_bytes (obstack, byte_order, - type, attr->as_unsigned (), len); + value = attr->confused_constant ().value_or (0); + result = write_constant_as_bytes (obstack, byte_order, type, value, len); break; default: @@ -18551,8 +18584,6 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile, const char **var_name) { - struct die_info *die; - dwarf2_cu *cu = per_objfile->get_cu (per_cu); if (cu == nullptr) cu = load_cu (per_cu, per_objfile, false); @@ -18560,7 +18591,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu, if (cu == nullptr) return nullptr; - die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); + die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu); if (!die) return NULL; @@ -18609,8 +18640,8 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type, gdb_assert (sig_cu != NULL); gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0); - if (auto die_it = sig_cu->die_hash.find (sig_type->type_offset_in_section); - die_it != sig_cu->die_hash.end ()) + if (die_info *die = sig_cu->find_die (sig_type->type_offset_in_section); + die != nullptr) { /* For .gdb_index version 7 keep track of included TUs. http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */ @@ -18619,7 +18650,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type, (*ref_cu)->per_cu->imported_symtabs.push_back (sig_cu->per_cu); *ref_cu = sig_cu; - return *die_it; + return die; } return NULL; @@ -18946,7 +18977,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu, case DW_OP_deref: /* If we're not the last op, then we definitely can't encode - this using GDB's address_class enum. This is valid for partial + this using GDB's location_class enum. This is valid for partial global symbols, although the variable's address will be bogus in the psymtab. */ if (i < size) @@ -19188,7 +19219,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, complaint (_("Location list used without " "specifying the CU base address.")); - sym->set_aclass_index ((is_block + sym->set_loc_class_index ((is_block ? dwarf2_loclist_block_index : dwarf2_loclist_index)); SYMBOL_LOCATION_BATON (sym) = baton; @@ -19197,7 +19228,8 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, { struct dwarf2_locexpr_baton *baton; - baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); + baton = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_locexpr_baton); baton->per_objfile = per_objfile; baton->per_cu = cu->per_cu; gdb_assert (baton->per_cu); @@ -19220,7 +19252,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, baton->size = 0; } - sym->set_aclass_index ((is_block + sym->set_loc_class_index ((is_block ? dwarf2_locexpr_block_index : dwarf2_locexpr_index)); SYMBOL_LOCATION_BATON (sym) = baton; @@ -19229,7 +19261,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, /* See read.h. */ -const comp_unit_head * +const unit_head * dwarf2_per_cu::get_header () const { if (!m_header_read_in) @@ -19237,8 +19269,7 @@ dwarf2_per_cu::get_header () const const gdb_byte *info_ptr = this->section->buffer + to_underlying (this->sect_off); - read_comp_unit_head (&m_header, info_ptr, this->section, - rcuh_kind::COMPILE); + read_unit_head (&m_header, info_ptr, this->section, ruh_kind::COMPILE); m_header_read_in = true; } @@ -19267,7 +19298,7 @@ dwarf2_per_cu::offset_size () const int dwarf2_per_cu::ref_addr_size () const { - const comp_unit_head *header = this->get_header (); + const unit_head *header = this->get_header (); if (header->version == 2) return header->addr_size; @@ -19310,69 +19341,115 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile) true, language_minimal, nullptr); } -/* A helper function for dwarf2_find_containing_comp_unit that returns - the index of the result, and that searches a vector. It will - return a result even if the offset in question does not actually - occur in any CU. This is separate so that it can be unit - tested. */ +/* Return the unit from ALL_UNITS that potentially contains TARGET. -static int -dwarf2_find_containing_comp_unit - (sect_offset sect_off, - unsigned int offset_in_dwz, - const std::vector<dwarf2_per_cu_up> &all_units) + Since the unit lengths may not be known yet, this function doesn't check that + TARGET.OFFSET actually falls within the range of the returned unit. The + caller is responsible for this. + + If no units possibly match TARGET, return nullptr. */ + +static dwarf2_per_cu * +dwarf2_find_containing_unit (const section_and_offset &target, + const std::vector<dwarf2_per_cu_up> &all_units) { - int low, high; + auto it = std::lower_bound (all_units.begin (), all_units.end (), target, + [] (const dwarf2_per_cu_up &per_cu, + const section_and_offset &key) + { + return all_units_less_than (*per_cu, key); + }); - low = 0; - high = all_units.size () - 1; - while (high > low) + if (it == all_units.begin ()) { - int mid = low + (high - low) / 2; - dwarf2_per_cu *mid_cu = all_units[mid].get (); - - if (mid_cu->is_dwz > offset_in_dwz - || (mid_cu->is_dwz == offset_in_dwz - && mid_cu->sect_off + mid_cu->length () > sect_off)) - high = mid; + /* TARGET falls before the first unit of the first section, or is an + exact match with the first. */ + if ((*it)->section == target.section && (*it)->sect_off == target.offset) + return it->get (); else - low = mid + 1; + return nullptr; } - gdb_assert (low == high); - return low; + + if (it != all_units.end () + && (*it)->section == target.section + && (*it)->sect_off == target.offset) + { + /* TARGET is an exact match with the start of *IT, so *IT is what we're + looking for. */ + return it->get (); + } + + /* Otherwise, the match is the one just before, as long as it matches the + section we're looking for. */ + --it; + + if ((*it)->section == target.section) + return it->get (); + + return nullptr; } /* See read.h. */ dwarf2_per_cu * -dwarf2_find_containing_comp_unit (sect_offset sect_off, - unsigned int offset_in_dwz, - dwarf2_per_bfd *per_bfd) +dwarf2_find_containing_unit (const section_and_offset &target, + dwarf2_per_objfile *per_objfile) { - int low = dwarf2_find_containing_comp_unit - (sect_off, offset_in_dwz, per_bfd->all_units); - dwarf2_per_cu *this_cu = per_bfd->all_units[low].get (); - - if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off) + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + dwarf2_per_cu *per_cu + = dwarf2_find_containing_unit (target, per_bfd->all_units); + auto error_out = [&target, per_bfd] () { - if (low == 0 || this_cu->is_dwz != offset_in_dwz) - error (_(DWARF_ERROR_PREFIX - "could not find CU containing offset %s [in module %s]"), - sect_offset_str (sect_off), - per_bfd->filename ()); + error (_(DWARF_ERROR_PREFIX + "could not find unit containing offset %s [in module %s]"), + sect_offset_str (target.offset), per_bfd->filename ()); + }; - gdb_assert (per_bfd->all_units[low-1]->sect_off - <= sect_off); - return per_bfd->all_units[low - 1].get (); - } - else - { - if (low == per_bfd->all_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 ()); - return this_cu; - } + if (per_cu == nullptr) + error_out (); + + gdb_assert (per_cu->section == target.section); + + /* Some producers of dwarf2_per_cu objects (thinking of the .gdb_index reader) + do not set the length ahead of time. The length is needed to check if + the target is truly within PER_CU's range, so compute it now. Constructing + the cutu_reader object has the side-effect of setting PER_CU's length. + Even though it should happen too often, it could be replaced with + something more lightweight that has the same effect. */ + if (!per_cu->length_is_set ()) + cutu_reader (*per_cu, *per_objfile, nullptr, nullptr, false, + language_minimal); + + /* Now we can check if the target section offset is within PER_CU's range. */ + if (target.offset < per_cu->sect_off + || target.offset >= per_cu->sect_off + per_cu->length ()) + error_out (); + + return per_cu; +} + +/* See read.h. */ + +dwarf2_per_cu * +dwarf2_find_unit (const section_and_offset &start, dwarf2_per_bfd *per_bfd) +{ + auto it = std::lower_bound (per_bfd->all_units.begin (), + per_bfd->all_units.end (), start, + [] (const dwarf2_per_cu_up &per_cu, + const section_and_offset &key) + { + return all_units_less_than (*per_cu, key); + }); + + if (it == per_bfd->all_units.end ()) + return nullptr; + + dwarf2_per_cu *per_cu = it->get (); + + if (per_cu->section != start.section || per_cu->sect_off != start.offset) + return nullptr; + + return per_cu; } #if GDB_SELF_TEST @@ -19383,59 +19460,55 @@ namespace find_containing_comp_unit { static void run_test () { - char dummy_per_bfd; - char dummy_section; - - const auto create_dummy_per_cu = [&] (sect_offset sect_off, - unsigned int length, - bool is_dwz) - { - auto per_bfd = reinterpret_cast<dwarf2_per_bfd *> (&dummy_per_bfd); - auto section = reinterpret_cast<dwarf2_section_info *> (&dummy_section); + auto dummy_per_bfd = reinterpret_cast<dwarf2_per_bfd *> (0x3000); + auto &main_section = *reinterpret_cast<dwarf2_section_info *> (0x4000); + auto &dwz_section = *reinterpret_cast<dwarf2_section_info *> (0x5000); + std::vector<dwarf2_per_cu_up> units; - return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, section, sect_off, - length, is_dwz)); + /* Create one dummy unit, append it to UNITS, return a non-owning + reference. */ + auto create_dummy_per_unit = [&] (dwarf2_section_info §ion, + unsigned int sect_off, bool is_dwz) + -> dwarf2_per_cu & + { + /* Omit the length, because dwarf2_find_containing_unit does not consider + it. */ + return *units.emplace_back (new dwarf2_per_cu (dummy_per_bfd, §ion, + sect_offset (sect_off), + 0, is_dwz)); }; - /* Units in the main file. */ - dwarf2_per_cu_up one = create_dummy_per_cu (sect_offset (0), 5, false); - dwarf2_per_cu *one_ptr = one.get (); - dwarf2_per_cu_up two - = create_dummy_per_cu (sect_offset (one->length ()), 7, false); - dwarf2_per_cu *two_ptr = two.get (); - - /* Units in the supplementary (dwz) file. */ - dwarf2_per_cu_up three = create_dummy_per_cu (sect_offset (0), 5, true); - dwarf2_per_cu *three_ptr = three.get (); - dwarf2_per_cu_up four - = create_dummy_per_cu (sect_offset (three->length ()), 7, true); - dwarf2_per_cu *four_ptr = four.get (); - - std::vector<dwarf2_per_cu_up> units; - units.push_back (std::move (one)); - units.push_back (std::move (two)); - units.push_back (std::move (three)); - units.push_back (std::move (four)); - - int result; + /* Create 2 units in the main file and 2 units in the supplementary (dwz) + file. */ + auto &main1 = create_dummy_per_unit (main_section, 10, false); + auto &main2 = create_dummy_per_unit (main_section, 20, false); + auto &dwz1 = create_dummy_per_unit (dwz_section, 10, false); + auto &dwz2 = create_dummy_per_unit (dwz_section, 20, false); + + /* Check that looking up a unit at all offsets in the range [START,END[ in + section SECTION finds EXPECTED. */ + auto check_range = [&units] (dwarf2_section_info §ion, unsigned int start, + unsigned int end, dwarf2_per_cu *expected) + { + for (unsigned int sect_off = start; sect_off < end; ++sect_off) + { + section_and_offset target { §ion, sect_offset (sect_off) }; + dwarf2_per_cu *result = dwarf2_find_containing_unit (target, units); - result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units); - SELF_CHECK (units[result].get () == one_ptr); - result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units); - SELF_CHECK (units[result].get () == one_ptr); - result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units); - SELF_CHECK (units[result].get () == two_ptr); + SELF_CHECK (result == expected); + } + }; - result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units); - SELF_CHECK (units[result].get () == three_ptr); - result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units); - SELF_CHECK (units[result].get () == three_ptr); - result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units); - SELF_CHECK (units[result].get () == four_ptr); -} + check_range (main_section, 0, 10, nullptr); + check_range (main_section, 10, 20, &main1); + check_range (main_section, 20, 30, &main2); + check_range (dwz_section, 0, 10, nullptr); + check_range (dwz_section, 10, 20, &dwz1); + check_range (dwz_section, 20, 30, &dwz2); } -} +} /* namespace find_containing_comp_unit */ +} /* namespace selftests */ #endif /* GDB_SELF_TEST */ @@ -19730,9 +19803,7 @@ show_check_physname (struct ui_file *file, int from_tty, value); } -void _initialize_dwarf2_read (); -void -_initialize_dwarf2_read () +INIT_GDB_FILE (dwarf2_read) { add_setshow_prefix_cmd ("dwarf", class_maintenance, _("\ diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index f3e043c..74ec420 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -20,9 +20,12 @@ #ifndef GDB_DWARF2_READ_H #define GDB_DWARF2_READ_H +#if CXX_STD_THREAD +#include <mutex> +#endif #include <queue> #include "dwarf2/abbrev.h" -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/unit-head.h" #include "dwarf2/file-and-dir.h" #include "dwarf2/index-cache.h" #include "dwarf2/mapped-index.h" @@ -44,7 +47,6 @@ struct tu_stats int nr_symtab_sharers = 0; int nr_stmt_less_type_units = 0; int nr_all_type_units_reallocs = 0; - int nr_tus = 0; }; struct abbrev_table_cache; @@ -233,14 +235,14 @@ public: /* Backlink to the owner of this. */ dwarf2_per_bfd *per_bfd; - /* DWARF header of this CU. Note that dwarf2_cu reads its own version of the - header, which may differ from this one, since it may pass rcuh_kind::TYPE - to read_comp_unit_head, whereas for dwarf2_per_cu we always pass - rcuh_kind::COMPILE. + /* DWARF header of this unit. Note that dwarf2_cu reads its own version of + the header, which may differ from this one, since it may pass + rch_kind::TYPE to read_unit_head, whereas for dwarf2_per_cu we always pass + ruh_kind::COMPILE. Don't access this field directly, use the get_header method instead. It should be private, but we can't make it private at the moment. */ - mutable comp_unit_head m_header; + mutable unit_head m_header; /* The file and directory for this CU. This is cached so that we don't need to re-examine the DWO in some situations. This may be @@ -271,7 +273,7 @@ public: std::vector<dwarf2_per_cu *> imported_symtabs; /* Get the header of this per_cu, reading it if necessary. */ - const comp_unit_head *get_header () const; + const unit_head *get_header () const; /* Return the address size given in the compilation unit header for this CU. */ @@ -293,6 +295,10 @@ public: return m_length; } + /* Return true if the length of this CU has been set. */ + bool length_is_set () const + { return m_length != 0; } + void set_length (unsigned int length, bool strict_p = true) { if (m_length == 0) @@ -512,26 +518,12 @@ struct dwarf2_per_bfd const char *filename () const { return bfd_get_filename (this->obfd); } - /* Return the CU given its index. */ - dwarf2_per_cu *get_cu (int index) const + /* Return the unit given its index. */ + dwarf2_per_cu *get_unit (int index) const { return this->all_units[index].get (); } - /* Return the CU given its index in the CU table in the index. */ - dwarf2_per_cu *get_index_cu (int index) const - { - if (this->all_comp_units_index_cus.empty ()) - return get_cu (index); - - return this->all_comp_units_index_cus[index]; - } - - dwarf2_per_cu *get_index_tu (int index) const - { - return this->all_comp_units_index_tus[index]; - } - /* Return the separate '.dwz' debug file. If there is no .gnu_debugaltlink or .debug_sup section in the file, then the result depends on REQUIRE: if REQUIRE is true, error out; if @@ -616,13 +608,9 @@ public: the target compilation unit of a particular reference. */ std::vector<dwarf2_per_cu_up> all_units; - /* The all_units vector contains both CUs and TUs. Provide views on the - vector that are limited to either the CU part or the TU part. */ - gdb::array_view<dwarf2_per_cu_up> all_comp_units; - gdb::array_view<dwarf2_per_cu_up> all_type_units; - - std::vector<dwarf2_per_cu *> all_comp_units_index_cus; - std::vector<dwarf2_per_cu *> all_comp_units_index_tus; + /* Number of compilation and type units in the ALL_UNITS vector. */ + unsigned int num_comp_units = 0; + unsigned int num_type_units = 0; /* Set of signatured_types, used to look up by signature. */ signatured_type_set signatured_types; @@ -634,6 +622,11 @@ public: /* Set of dwo_file objects. */ dwo_file_up_set dwo_files; +#if CXX_STD_THREAD + /* Mutex to synchronize access to DWO_FILES. */ + std::mutex dwo_files_lock; +#endif + /* The DWP file if there is one, or NULL. */ dwp_file_up dwp_file; @@ -680,6 +673,36 @@ public: std::string captured_debug_dir; }; +/* Scoped object to remove all units from PER_BFD and clear other associated + fields in case of failure. */ + +struct scoped_remove_all_units +{ + explicit scoped_remove_all_units (dwarf2_per_bfd &per_bfd) + : m_per_bfd (&per_bfd) + {} + + DISABLE_COPY_AND_ASSIGN (scoped_remove_all_units); + + ~scoped_remove_all_units () + { + if (m_per_bfd == nullptr) + return; + + m_per_bfd->all_units.clear (); + m_per_bfd->num_comp_units = 0; + m_per_bfd->num_type_units = 0; + } + + /* Disable this object. Call this to keep the units of M_PER_BFD on the + success path. */ + void disable () { m_per_bfd = nullptr; } + +private: + /* This is nullptr if the object is disabled. */ + dwarf2_per_bfd *m_per_bfd; +}; + /* An iterator for all_units that is based on index. This approach makes it possible to iterate over all_units safely, when some caller in the loop may add new units. */ @@ -702,7 +725,7 @@ public: dwarf2_per_cu *operator* () const { - return m_per_bfd->get_cu (m_index); + return m_per_bfd->get_unit (m_index); } bool operator== (const all_units_iterator &other) const @@ -812,7 +835,7 @@ struct dwarf2_per_objfile BUF is assumed to be in a compilation unit described by CU_HEADER. Return *BYTES_READ_PTR count of bytes read from BUF. */ const char *read_line_string (const gdb_byte *buf, - const struct comp_unit_head *cu_header, + const struct unit_head *unit_header, unsigned int *bytes_read_ptr); /* Return pointer to string at .debug_line_str offset as read from BUF. @@ -934,8 +957,6 @@ public: DISABLE_COPY_AND_ASSIGN (cutu_reader); - cutu_reader (cutu_reader &&) = default; - /* Return true if either: - the unit is empty (just a header without any DIE) @@ -1031,19 +1052,11 @@ private: dwo_file_up open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir); - void locate_dwo_sections (struct objfile *objfile, bfd *abfd, asection *sectp, - struct dwo_sections *dwo_sections); - - void create_dwo_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file); + void locate_dwo_sections (objfile *objfile, dwo_file &dwo_file); - void create_dwo_debug_types_hash_table - (dwarf2_per_bfd *per_bfd, dwo_file *dwo_file, - gdb::array_view<dwarf2_section_info> type_sections); - - void create_dwo_debug_type_hash_table (dwarf2_per_bfd *per_bfd, - dwo_file *dwo_file, - dwarf2_section_info *section, - rcuh_kind section_kind); + void create_dwo_unit_hash_tables (dwo_file &dwo_file, dwarf2_cu &skeleton_cu, + dwarf2_section_info §ion, + ruh_kind section_kind); dwo_unit *lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, ULONGEST signature, @@ -1234,7 +1247,7 @@ extern void dw_expand_symtabs_matching_file_matcher extern const char *read_indirect_string_at_offset (dwarf2_per_objfile *per_objfile, LONGEST str_offset); -/* Initialize the views on all_units. */ +/* Finalize the all_units vector. */ extern void finalize_all_units (dwarf2_per_bfd *per_bfd); @@ -1279,14 +1292,17 @@ extern pc_bounds_kind dwarf2_get_pc_bounds (die_info *die, dwarf2_cu *cu, addrmap_mutable *map, void *datum); -/* Locate the .debug_info compilation unit from CU's objfile which contains - the DIE at OFFSET. Raises an error on failure. */ +/* Locate the unit in PER_OBJFILE which contains the DIE at TARGET. Raises an + error on failure. */ + +extern dwarf2_per_cu *dwarf2_find_containing_unit + (const section_and_offset &target, dwarf2_per_objfile *per_objfile); -extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off, - unsigned int - offset_in_dwz, - dwarf2_per_bfd - *per_bfd); +/* Locate the unit starting at START in PER_BFD. Return nullptr if not + found. */ + +extern dwarf2_per_cu *dwarf2_find_unit (const section_and_offset &start, + dwarf2_per_bfd *per_bfd); /* Decode simple location descriptions. @@ -1329,4 +1345,10 @@ extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return, extern file_and_directory &find_file_and_directory (die_info *die, dwarf2_cu *cu); + +/* Return the section that ATTR, an attribute with ref form, references. */ + +extern const dwarf2_section_info &get_section_for_ref + (const attribute &attr, dwarf2_cu *cu); + #endif /* GDB_DWARF2_READ_H */ diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h index b9d3c31..fbdb025 100644 --- a/gdb/dwarf2/section.h +++ b/gdb/dwarf2/section.h @@ -43,6 +43,8 @@ the real section this "virtual" section is contained in, and BUFFER,SIZE describe the virtual section. */ +#include "dwarf2/types.h" + struct dwarf2_section_info { /* Return the name of this section. */ @@ -112,4 +114,14 @@ struct dwarf2_section_info bool is_virtual; }; +using dwarf2_section_info_up = std::unique_ptr<dwarf2_section_info>; + +/* A pair-like structure to represent an offset into a section. */ + +struct section_and_offset +{ + const dwarf2_section_info *section; + sect_offset offset; +}; + #endif /* GDB_DWARF2_SECTION_H */ diff --git a/gdb/dwarf2/comp-unit-head.c b/gdb/dwarf2/unit-head.c index a35d664..0c7614f 100644 --- a/gdb/dwarf2/comp-unit-head.c +++ b/gdb/dwarf2/unit-head.c @@ -24,118 +24,117 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/unit-head.h" #include "dwarf2/leb.h" #include "dwarf2/section.h" #include "dwarf2/stringify.h" #include "dwarf2/error.h" -/* See comp-unit-head.h. */ +/* See unit-head.h. */ const gdb_byte * -read_comp_unit_head (struct comp_unit_head *cu_header, - const gdb_byte *info_ptr, - struct dwarf2_section_info *section, - rcuh_kind section_kind) +read_unit_head (struct unit_head *header, const gdb_byte *info_ptr, + struct dwarf2_section_info *section, ruh_kind section_kind) { int signed_addr; unsigned int bytes_read; const char *filename = section->get_file_name (); bfd *abfd = section->get_bfd_owner (); - cu_header->set_length (read_initial_length (abfd, info_ptr, &bytes_read)); - cu_header->initial_length_size = bytes_read; - cu_header->offset_size = (bytes_read == 4) ? 4 : 8; + header->set_length (read_initial_length (abfd, info_ptr, &bytes_read)); + header->initial_length_size = bytes_read; + header->offset_size = (bytes_read == 4) ? 4 : 8; info_ptr += bytes_read; unsigned version = read_2_bytes (abfd, info_ptr); if (version < 2 || version > 5) error (_(DWARF_ERROR_PREFIX - "wrong version in compilation unit header " + "wrong version in unit header " "(is %d, should be 2, 3, 4 or 5) [in module %s]"), version, filename); - cu_header->version = version; + header->version = version; info_ptr += 2; - if (cu_header->version < 5) + if (header->version < 5) switch (section_kind) { - case rcuh_kind::COMPILE: - cu_header->unit_type = DW_UT_compile; + case ruh_kind::COMPILE: + header->unit_type = DW_UT_compile; break; - case rcuh_kind::TYPE: - cu_header->unit_type = DW_UT_type; + case ruh_kind::TYPE: + header->unit_type = DW_UT_type; break; default: - internal_error (_("read_comp_unit_head: invalid section_kind")); + internal_error (_("read_unit_head: invalid section_kind")); } else { - cu_header->unit_type = static_cast<enum dwarf_unit_type> - (read_1_byte (abfd, info_ptr)); + header->unit_type + = static_cast<enum dwarf_unit_type> (read_1_byte (abfd, info_ptr)); info_ptr += 1; - switch (cu_header->unit_type) + switch (header->unit_type) { case DW_UT_compile: case DW_UT_partial: case DW_UT_skeleton: case DW_UT_split_compile: - if (section_kind != rcuh_kind::COMPILE) + if (section_kind != ruh_kind::COMPILE) error (_(DWARF_ERROR_PREFIX - "wrong unit_type in compilation unit header " + "wrong unit_type in unit header " "(is %s, should be %s) [in module %s]"), - dwarf_unit_type_name (cu_header->unit_type), + dwarf_unit_type_name (header->unit_type), dwarf_unit_type_name (DW_UT_type), filename); break; case DW_UT_type: case DW_UT_split_type: - section_kind = rcuh_kind::TYPE; + section_kind = ruh_kind::TYPE; break; default: error (_(DWARF_ERROR_PREFIX - "wrong unit_type in compilation unit header " + "wrong unit_type in unit header " "(is %#04x, should be one of: %s, %s, %s, %s or %s) " "[in module %s]"), - cu_header->unit_type, dwarf_unit_type_name (DW_UT_compile), + header->unit_type, dwarf_unit_type_name (DW_UT_compile), dwarf_unit_type_name (DW_UT_skeleton), dwarf_unit_type_name (DW_UT_split_compile), dwarf_unit_type_name (DW_UT_type), dwarf_unit_type_name (DW_UT_split_type), filename); } - cu_header->addr_size = read_1_byte (abfd, info_ptr); + header->addr_size = read_1_byte (abfd, info_ptr); info_ptr += 1; } - cu_header->abbrev_sect_off - = (sect_offset) cu_header->read_offset (abfd, info_ptr, &bytes_read); + header->abbrev_sect_off + = (sect_offset) header->read_offset (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; - if (cu_header->version < 5) + if (header->version < 5) { - cu_header->addr_size = read_1_byte (abfd, info_ptr); + header->addr_size = read_1_byte (abfd, info_ptr); info_ptr += 1; } signed_addr = bfd_get_sign_extend_vma (abfd); if (signed_addr < 0) - internal_error (_("read_comp_unit_head: dwarf from non elf file")); - cu_header->signed_addr_p = signed_addr; + internal_error (_("read_unit_head: dwarf from non elf file")); + header->signed_addr_p = signed_addr; - bool header_has_signature = section_kind == rcuh_kind::TYPE - || cu_header->unit_type == DW_UT_skeleton - || cu_header->unit_type == DW_UT_split_compile; + bool header_has_signature = + (section_kind == ruh_kind::TYPE + || header->unit_type == DW_UT_skeleton + || header->unit_type == DW_UT_split_compile); if (header_has_signature) { - cu_header->signature = read_8_bytes (abfd, info_ptr); + header->signature = read_8_bytes (abfd, info_ptr); info_ptr += 8; } - if (section_kind == rcuh_kind::TYPE) + if (section_kind == ruh_kind::TYPE) { LONGEST type_offset; - type_offset = cu_header->read_offset (abfd, info_ptr, &bytes_read); + type_offset = header->read_offset (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; - cu_header->type_cu_offset_in_tu = (cu_offset) type_offset; - if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset) + header->type_offset_in_tu = (cu_offset) type_offset; + if (to_underlying (header->type_offset_in_tu) != type_offset) error (_(DWARF_ERROR_PREFIX - "Too big type_offset in compilation unit " + "Too big type_offset in unit " "header (is %s) [in module %s]"), plongest (type_offset), filename); } @@ -143,60 +142,56 @@ read_comp_unit_head (struct comp_unit_head *cu_header, return info_ptr; } -/* Subroutine of read_and_check_comp_unit_head and - read_and_check_type_unit_head to simplify them. +/* Subroutine of read_and_check_unit_head to to simplify it. Perform various error checking on the header. */ static void -error_check_comp_unit_head (comp_unit_head *header, - dwarf2_section_info *section, - dwarf2_section_info *abbrev_section) +error_check_unit_head (unit_head *header, dwarf2_section_info *section, + dwarf2_section_info *abbrev_section) { const char *filename = section->get_file_name (); if (to_underlying (header->abbrev_sect_off) >= abbrev_section->size) error (_(DWARF_ERROR_PREFIX - "bad offset (%s) in compilation unit header " + "bad offset (%s) in unit header " "(offset %s + 6) [in module %s]"), sect_offset_str (header->abbrev_sect_off), - sect_offset_str (header->sect_off), - filename); + sect_offset_str (header->sect_off), filename); /* Cast to ULONGEST to use 64-bit arithmetic when possible to avoid potential 32-bit overflow. */ if (((ULONGEST) header->sect_off + header->get_length_with_initial ()) > section->size) error (_(DWARF_ERROR_PREFIX - "bad length (0x%x) in compilation unit header " + "bad length (0x%x) in unit header " "(offset %s + 0) [in module %s]"), header->get_length_without_initial (), sect_offset_str (header->sect_off), filename); } -/* See comp-unit-head.h. */ +/* See unit-head.h. */ const gdb_byte * -read_and_check_comp_unit_head (comp_unit_head *header, - dwarf2_section_info *section, - dwarf2_section_info *abbrev_section, - const gdb_byte *info_ptr, rcuh_kind section_kind) +read_and_check_unit_head (unit_head *header, dwarf2_section_info *section, + dwarf2_section_info *abbrev_section, + const gdb_byte *info_ptr, ruh_kind section_kind) { - const gdb_byte *beg_of_comp_unit = info_ptr; + const gdb_byte *beg_of_unit = info_ptr; - header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer); + header->sect_off = (sect_offset) (beg_of_unit - section->buffer); - info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind); + info_ptr = read_unit_head (header, info_ptr, section, section_kind); - header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit); + header->first_die_offset_in_unit = (cu_offset) (info_ptr - beg_of_unit); - error_check_comp_unit_head (header, section, abbrev_section); + error_check_unit_head (header, section, abbrev_section); return info_ptr; } unrelocated_addr -comp_unit_head::read_address (bfd *abfd, const gdb_byte *buf, - unsigned int *bytes_read) const +unit_head::read_address (bfd *abfd, const gdb_byte *buf, + unsigned int *bytes_read) const { ULONGEST retval = 0; diff --git a/gdb/dwarf2/comp-unit-head.h b/gdb/dwarf2/unit-head.h index ea09153..6272888 100644 --- a/gdb/dwarf2/comp-unit-head.h +++ b/gdb/dwarf2/unit-head.h @@ -24,18 +24,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef GDB_DWARF2_COMP_UNIT_HEAD_H -#define GDB_DWARF2_COMP_UNIT_HEAD_H +#ifndef GDB_DWARF2_UNIT_HEAD_H +#define GDB_DWARF2_UNIT_HEAD_H #include "dwarf2.h" #include "dwarf2/leb.h" #include "dwarf2/types.h" struct dwarf2_per_objfile; +struct dwarf2_section_info; -/* The data in a compilation unit header, after target2host - translation, looks like this. */ -struct comp_unit_head +/* The data in a unit header, after target2host translation, looks like + this. */ +struct unit_head { private: unsigned int m_length = 0; @@ -53,16 +54,16 @@ public: enum dwarf_unit_type unit_type {}; - /* Offset to first die in this cu from the start of the cu. - This will be the first byte following the compilation unit header. */ - cu_offset first_die_cu_offset {}; + /* Offset to first die in this unit from the start of the unit. + This will be the first byte following the unit header. */ + cu_offset first_die_offset_in_unit {}; - /* Offset to the first byte of this compilation unit header in the - .debug_info section, for resolving relative reference dies. */ + /* Offset to the first byte of this unit header in the containing section, + for resolving relative reference dies. */ sect_offset sect_off {}; /* For types, offset in the type's DIE of the type defined by this TU. */ - cu_offset type_cu_offset_in_tu {}; + cu_offset type_offset_in_tu {}; /* 64-bit signature of this unit. For type units, it denotes the signature of the type (DW_UT_type in DWARF 4, additionally DW_UT_split_type in DWARF 5). @@ -75,22 +76,22 @@ public: m_length = length; } - /* Return the total length of the CU described by this header, including the + /* Return the total length of the unit described by this header, including the initial length field. */ unsigned int get_length_with_initial () const { return m_length + initial_length_size; } - /* Return the total length of the CU described by this header, excluding the + /* Return the total length of the unit described by this header, excluding the initial length field. */ unsigned int get_length_without_initial () const { return m_length; } - /* Return TRUE if OFF is within this CU. */ - bool offset_in_cu_p (sect_offset off) const + /* Return TRUE if OFF is within this unit. */ + bool offset_in_unit_p (sect_offset off) const { sect_offset bottom = sect_off; sect_offset top = sect_off + get_length_with_initial (); @@ -98,7 +99,7 @@ public: } /* Read an offset from the data stream. The size of the offset is - given by cu_header->offset_size. */ + given by unit_head::offset_size. */ LONGEST read_offset (bfd *abfd, const gdb_byte *buf, unsigned int *bytes_read) const { @@ -112,25 +113,24 @@ public: unsigned int *bytes_read) const; }; -/* Expected enum dwarf_unit_type for read_comp_unit_head. */ -enum class rcuh_kind { COMPILE, TYPE }; +/* Expected enum dwarf_unit_type for read_unit_head. */ +enum class ruh_kind { COMPILE, TYPE }; -/* Read in the comp unit header information from the debug_info at info_ptr. - Use rcuh_kind::COMPILE as the default type if not known by the caller. - NOTE: This leaves members offset, first_die_offset to be filled in +/* Read in the unit header information from the debug_info at info_ptr. + Use ruh_kind::COMPILE as the default type if not known by the caller. + NOTE: This leaves members sect_off, first_die_unit_offset to be filled in by the caller. */ -extern const gdb_byte *read_comp_unit_head - (struct comp_unit_head *cu_header, - const gdb_byte *info_ptr, - struct dwarf2_section_info *section, - rcuh_kind section_kind); +extern const gdb_byte *read_unit_head (unit_head *header, + const gdb_byte *info_ptr, + dwarf2_section_info *section, + ruh_kind section_kind); -/* Read in a CU/TU header and perform some basic error checking. +/* Read in a unit header and perform some basic error checking. The contents of the header are stored in HEADER. The result is a pointer to the start of the first DIE. */ -extern const gdb_byte *read_and_check_comp_unit_head - (comp_unit_head *header, dwarf2_section_info *section, +extern const gdb_byte *read_and_check_unit_head + (unit_head *header, dwarf2_section_info *section, dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr, - rcuh_kind section_kind); + ruh_kind section_kind); -#endif /* GDB_DWARF2_COMP_UNIT_HEAD_H */ +#endif /* GDB_DWARF2_UNIT_HEAD_H */ |