aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r--gdb/dwarf2/attribute.c16
-rw-r--r--gdb/dwarf2/attribute.h19
-rw-r--r--gdb/dwarf2/call-site.h2
-rw-r--r--gdb/dwarf2/cooked-index-entry.c4
-rw-r--r--gdb/dwarf2/cooked-index-worker.c2
-rw-r--r--gdb/dwarf2/cooked-index-worker.h30
-rw-r--r--gdb/dwarf2/cooked-index.c7
-rw-r--r--gdb/dwarf2/cooked-indexer.c42
-rw-r--r--gdb/dwarf2/cooked-indexer.h4
-rw-r--r--gdb/dwarf2/cu.h7
-rw-r--r--gdb/dwarf2/dwz.c60
-rw-r--r--gdb/dwarf2/frame-tailcall.c4
-rw-r--r--gdb/dwarf2/frame.c4
-rw-r--r--gdb/dwarf2/frame.h61
-rw-r--r--gdb/dwarf2/index-cache.c4
-rw-r--r--gdb/dwarf2/index-write.c146
-rw-r--r--gdb/dwarf2/loc.c49
-rw-r--r--gdb/dwarf2/loc.h111
-rw-r--r--gdb/dwarf2/public.h25
-rw-r--r--gdb/dwarf2/read-debug-names.c158
-rw-r--r--gdb/dwarf2/read-gdb-index.c43
-rw-r--r--gdb/dwarf2/read.c1043
-rw-r--r--gdb/dwarf2/read.h71
-rw-r--r--gdb/dwarf2/section.h12
24 files changed, 1118 insertions, 806 deletions
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 8ff0353..d2b5364 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -216,6 +216,22 @@ attribute::signed_constant () const
/* 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
{
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index 31ff018..234de4e 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -123,6 +123,25 @@ struct attribute
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.
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 5d7fc46..09d80ef 100644
--- a/gdb/dwarf2/cooked-index-worker.c
+++ b/gdb/dwarf2/cooked-index-worker.c
@@ -246,7 +246,7 @@ void
cooked_index_worker::done_reading ()
{
{
- scoped_time_it time_it ("DWARF add 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 ());
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 2c7e31e..6209590 100644
--- a/gdb/dwarf2/cooked-index.c
+++ b/gdb/dwarf2/cooked-index.c
@@ -104,7 +104,8 @@ cooked_index::set_contents ()
const parent_map_map *parent_maps = m_state->get_parent_map_map ();
finalizers.add_task ([=] ()
{
- scoped_time_it time_it ("DWARF finalize worker");
+ scoped_time_it time_it ("DWARF finalize worker",
+ m_state->m_per_command_time);
this_shard->finalize (parent_maps);
});
}
@@ -326,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 c093984..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 &sect_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_unit_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. */
@@ -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 &sect_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 5338dfe..68010a0 100644
--- a/gdb/dwarf2/cu.h
+++ b/gdb/dwarf2/cu.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 &section () 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
@@ -369,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/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..97677c0 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 &section,
- bool is_dwz)
+build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd,
+ mapped_debug_names_reader &map,
+ dwarf2_section_info &section)
{
- 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,35 +729,43 @@ 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 ({ &section, 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
@@ -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;
}
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index 2029c3e..76317fe 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 ());
}
@@ -1419,14 +1426,14 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
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
@@ -1528,8 +1535,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)
{
@@ -1548,7 +1555,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);
@@ -1562,10 +1570,7 @@ dwarf2_read_gdb_index
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 0eb248f..ec8d376 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -289,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
@@ -316,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); }
};
@@ -330,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
@@ -599,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;
@@ -1322,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))
@@ -1680,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;
}
@@ -1696,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;
}
@@ -1891,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
@@ -2360,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
@@ -2403,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
@@ -2487,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 ())
@@ -2777,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;
@@ -3209,10 +3241,11 @@ private:
void print_tu_stats (dwarf2_per_objfile *per_objfile)
{
- struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
+ 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", tu_stats->nr_tus);
+ 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",
@@ -3362,7 +3395,7 @@ cooked_index_worker_debug_info::process_type_units
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
@@ -3389,7 +3422,7 @@ cooked_index_worker_debug_info::process_type_units
/* 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)
@@ -3422,7 +3455,10 @@ cooked_index_worker_debug_info::process_type_units
abbrev_table.get (), nullptr, false,
language_minimal);
if (!reader.is_dummy ())
- process_type_unit (&reader, storage);
+ storage->catch_error ([&] ()
+ {
+ process_type_unit (&reader, storage);
+ });
}
}
@@ -3458,13 +3494,16 @@ 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");
+ 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);
+ });
}
void
@@ -3483,14 +3522,10 @@ cooked_index_worker_debug_info::process_units (size_t task_number,
{
dwarf2_per_cu *per_cu = inner->get ();
- try
+ thread_storage.catch_error ([&] ()
{
process_unit (per_cu, m_per_objfile, &thread_storage);
- }
- catch (gdb_exception &except)
- {
- thread_storage.note_error (std::move (except));
- }
+ });
}
thread_storage.done_reading (complaint_handler.release ());
@@ -3568,7 +3603,7 @@ cooked_index_worker_debug_info::do_reading ()
gdb_assert (iter != last);
workers.add_task ([this, task_count, iter, last] ()
{
- scoped_time_it time_it ("DWARF indexing worker");
+ scoped_time_it time_it ("DWARF indexing worker", m_per_command_time);
process_units (task_count, iter, last);
});
@@ -3639,16 +3674,18 @@ 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);
+ /* 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. */
@@ -4904,6 +4941,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
@@ -4923,12 +4975,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 &section = 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 ({ &section, 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,
@@ -5853,7 +5904,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 ())));
}
@@ -6049,6 +6100,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)
{
@@ -6200,11 +6265,33 @@ 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;
}
+/* 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_unit_hash_tables (dwo_file &dwo_file,
dwarf2_cu &skeleton_cu,
@@ -6283,7 +6370,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
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;
@@ -6301,7 +6388,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
sect_offset_str (sect_off),
hex_string (dwo_unit->signature));
- auto [it, inserted] = dwo_file.cus.emplace (dwo_unit);
+ 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"),
@@ -6320,7 +6407,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
sect_offset_str (sect_off),
hex_string (dwo_unit->signature));
- auto [it, inserted] = dwo_file.tus.emplace (dwo_unit);
+ 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"),
@@ -6801,7 +6888,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,
@@ -6924,19 +7011,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. */
@@ -6994,7 +7079,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,
@@ -7129,19 +7214,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
@@ -7159,7 +7242,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,
@@ -7299,16 +7382,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
@@ -7339,9 +7419,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)
@@ -7355,7 +7441,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
@@ -7370,9 +7456,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)
@@ -7428,7 +7519,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));
@@ -7449,14 +7540,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;
}
@@ -7506,45 +7606,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->infos.emplace_back (dwarf2_section_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))
- 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
+ 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);
+ gdb_assert (!dw_sect->readin);
- 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);
+ }
}
}
@@ -7572,15 +7693,8 @@ 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);
- /* There is normally just one .debug_info.dwo section in a DWO file. But when
- building with -fdebug-types-section, gcc produces multiple .debug_info.dwo
- sections. One for each produced type unit and one for the compile unit.
- This is not expected, but we can easily enough deal with what gcc
- produces. This behavior has been observed with gcc 14.2.1. */
for (dwarf2_section_info &section : dwo_file->sections.infos)
create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::COMPILE);
@@ -7782,7 +7896,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;
@@ -7932,12 +8046,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)
@@ -7948,13 +8057,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)
@@ -8061,8 +8170,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. */
@@ -8738,7 +8847,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;
@@ -9861,69 +9971,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->unsigned_constant ().value_or (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))
+ if (bit_offset_attr != nullptr && bit_offset_attr->form_is_constant ())
{
- *offset = temp;
- }
- else
- dwarf2_complex_location_expr_complaint ();
+ has_bit_offset = true;
+ bit_offset = bit_offset_attr->confused_constant ().value_or (0);
- return 1;
- }
- else
- {
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != nullptr)
- {
- *offset = attr->unsigned_constant ().value_or (0);
- return 1;
- }
- }
+ const auto byte_size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
- return 0;
-}
-
-/* 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->unsigned_constant ().value_or (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:
@@ -9938,23 +10023,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. */
@@ -9962,28 +10064,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->unsigned_constant ().value_or (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;
@@ -10033,64 +10181,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->unsigned_constant ().value_or (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 ())
- {
- ULONGEST bit_offset = attr->unsigned_constant ().value_or (0);
- 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 () + bit_offset);
- }
- 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;
-
- 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->unsigned_constant ().value_or (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);
@@ -11269,6 +11360,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
@@ -12262,7 +12368,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);
@@ -13165,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. */
@@ -13199,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_strictly_unsigned ())
- *value = gdb_mpz (attr->as_unsigned ());
else
- *value = gdb_mpz (attr->signed_constant ().value_or (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
@@ -13231,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
@@ -13924,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;
}
}
@@ -15333,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
@@ -17165,29 +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 void
-dwarf2_const_value_data (const struct attribute *attr, LONGEST *value,
- int bits)
-{
- LONGEST l = attr->constant_value (0);
-
- if (bits < sizeof (*value) * 8)
- {
- l &= ((LONGEST) 1 << bits) - 1;
- *value = l;
- }
- else
- *value = l;
-}
-
/* 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,
@@ -17227,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);
@@ -17271,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:
- dwarf2_const_value_data (attr, value, 8);
- break;
case DW_FORM_data2:
- dwarf2_const_value_data (attr, value, 16);
- break;
case DW_FORM_data4:
- dwarf2_const_value_data (attr, value, 32);
- break;
case DW_FORM_data8:
- dwarf2_const_value_data (attr, 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:
@@ -17456,9 +17532,10 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
if (attr->form_is_alt ())
{
+ const auto &section = 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 ({ &section, sect_off }, per_objfile);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
@@ -18159,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;
@@ -18178,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_unit_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_unit_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_unit_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",
@@ -18216,13 +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;
- return target_cu->find_die (sect_off);
+ return target_cu->find_die (target.offset);
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -18234,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)
{
@@ -18243,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 &section = get_section_for_ref (*attr, src_cu);
+ die_info *die = follow_die_offset ({ &section, 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;
}
@@ -18263,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;
@@ -18281,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));
@@ -18298,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)
@@ -18401,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;
@@ -18422,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]"),
@@ -18481,39 +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);
- dwarf2_const_value_data (attr, &value, 8);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data2:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 16);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data4:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 32);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data8:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 64);
- 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:
@@ -18532,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);
@@ -18541,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;
@@ -19178,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);
@@ -19290,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
@@ -19363,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 &section,
+ 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, &section,
+ 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 &section, 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 { &section, 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 */
@@ -19710,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 5b4c8f6..4e3f8d7 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -20,6 +20,9 @@
#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/unit-head.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;
@@ -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;
@@ -702,7 +695,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
@@ -1029,8 +1022,7 @@ 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 locate_dwo_sections (objfile *objfile, dwo_file &dwo_file);
void create_dwo_unit_hash_tables (dwo_file &dwo_file, dwarf2_cu &skeleton_cu,
dwarf2_section_info &section,
@@ -1225,7 +1217,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);
@@ -1270,14 +1262,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);
+
+/* Locate the unit starting at START in PER_BFD. Return nullptr if not
+ found. */
-extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int
- offset_in_dwz,
- dwarf2_per_bfd
- *per_bfd);
+extern dwarf2_per_cu *dwarf2_find_unit (const section_and_offset &start,
+ dwarf2_per_bfd *per_bfd);
/* Decode simple location descriptions.
@@ -1320,4 +1315,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 */