diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c index 97677c04f64..ddf49356722 100644 --- a/gdb/dwarf2/read-debug-names.c +++ b/gdb/dwarf2/read-debug-names.c @@ -768,12 +768,12 @@ build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd, return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info); } -/* This does all the work for dwarf2_read_debug_names, but putting it - into a separate function makes some cleanup a bit simpler. */ +/* See read-debug-names.h. */ -static bool -do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) +bool +dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) { + scoped_remove_all_units remove_all_units (*per_objfile->per_bfd); mapped_debug_names_reader map; mapped_debug_names_reader dwz_map; struct objfile *objfile = per_objfile->objfile; @@ -850,17 +850,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) (per_objfile, std::move (map))); auto idx = std::make_unique (std::move (cidn)); per_bfd->start_reading (std::move (idx)); + remove_all_units.disable (); return true; } - -/* See read-debug-names.h. */ - -bool -dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) -{ - bool result = do_dwarf2_read_debug_names (per_objfile); - if (!result) - per_objfile->per_bfd->all_units.clear (); - return result; -} diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c index 7dfba732451..fc7b654be1a 100644 --- a/gdb/dwarf2/read-gdb-index.c +++ b/gdb/dwarf2/read-gdb-index.c @@ -1489,6 +1489,7 @@ dwarf2_read_gdb_index offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; struct objfile *objfile = per_objfile->objfile; dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + scoped_remove_all_units remove_all_units (*per_bfd); gdb::array_view main_index_contents = get_gdb_index_contents (objfile, per_bfd); @@ -1544,10 +1545,7 @@ dwarf2_read_gdb_index an index. */ if (per_bfd->infos.size () > 1 || per_bfd->types.size () > 1) - { - per_bfd->all_units.clear (); - return false; - } + return false; dwarf2_section_info *section = (per_bfd->types.size () == 1 @@ -1566,6 +1564,7 @@ dwarf2_read_gdb_index set_main_name_from_gdb_index (per_objfile, map.get ()); per_bfd->index_table = std::move (map); + remove_all_units.disable (); return true; } diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index c37da5949b0..7bd0850ee5b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -3679,6 +3679,10 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, void finalize_all_units (dwarf2_per_bfd *per_bfd) { + /* Sanity check. */ + gdb_assert (per_bfd->all_units.size () + == per_bfd->num_comp_units + per_bfd->num_type_units); + /* Ensure that the all_units vector is in the expected order for dwarf2_find_containing_unit to be able to perform a binary search. */ std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (), @@ -3694,6 +3698,7 @@ void create_all_units (dwarf2_per_objfile *per_objfile) { gdb_assert (per_objfile->per_bfd->all_units.empty ()); + scoped_remove_all_units remove_all_units (*per_objfile->per_bfd); signatured_type_set sig_types; @@ -3714,8 +3719,6 @@ create_all_units (dwarf2_per_objfile *per_objfile) if (!dwz->types.empty ()) { - per_objfile->per_bfd->all_units.clear (); - /* See enhancement PR symtab/30838. */ error (_(DWARF_ERROR_PREFIX ".debug_types section not supported in dwz file")); @@ -3725,6 +3728,7 @@ create_all_units (dwarf2_per_objfile *per_objfile) per_objfile->per_bfd->signatured_types = std::move (sig_types); finalize_all_units (per_objfile->per_bfd); + remove_all_units.disable (); } /* Return the initial uleb128 in the die at INFO_PTR. */ diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 4e3f8d7d7bc..74ec4204cad 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -673,6 +673,36 @@ public: std::string captured_debug_dir; }; +/* Scoped object to remove all units from PER_BFD and clear other associated + fields in case of failure. */ + +struct scoped_remove_all_units +{ + explicit scoped_remove_all_units (dwarf2_per_bfd &per_bfd) + : m_per_bfd (&per_bfd) + {} + + DISABLE_COPY_AND_ASSIGN (scoped_remove_all_units); + + ~scoped_remove_all_units () + { + if (m_per_bfd == nullptr) + return; + + m_per_bfd->all_units.clear (); + m_per_bfd->num_comp_units = 0; + m_per_bfd->num_type_units = 0; + } + + /* Disable this object. Call this to keep the units of M_PER_BFD on the + success path. */ + void disable () { m_per_bfd = nullptr; } + +private: + /* This is nullptr if the object is disabled. */ + dwarf2_per_bfd *m_per_bfd; +}; + /* An iterator for all_units that is based on index. This approach makes it possible to iterate over all_units safely, when some caller in the loop may add new units. */