From: Guinevere Larsen <guinevere@redhat.com>
To: Simon Marchi <simon.marchi@efficios.com>, gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: Re: [PATCH v3 7/7] gdb/dwarf: read foreign type units
Date: Tue, 19 May 2026 16:42:24 -0300 [thread overview]
Message-ID: <88ae1a52-4417-47d9-a01e-57365e436454@redhat.com> (raw)
In-Reply-To: <20260511154053.142576-8-simon.marchi@efficios.com>
[-- Attachment #1: Type: text/plain, Size: 35787 bytes --]
Hi Simon!
This commit seems to have made the
gdb.dwarf2/debug-names-bad-cu-index.exp have some racy cases. I've
attached a log of the failed run in this email to help you figure out
what could be going on.
On 5/11/26 12:40 PM, Simon Marchi wrote:
> In DWARF 5, foreign type units are type units present in .dwo files.
> Type units in .dwo files don't have a matching skeleton in the main
> file. When an .debug_names index is present, it can't include those
> type units in the regular type unit list, since that list specifies
> offsets in the main file. They are instead listed in the foreign TU
> list, which is basically just a list of type signatures.
>
> In order to help the debugger locate these units (i.e. find the .dwo
> file containing them), individual index entries referencing foreign type
> units may also include a reference to a compile unit that the debugger
> can follow to find the appropriate .dwo file.
>
> This patch implements reading the .debug_names foreign TU list and using
> these "hint" CUs to locate foreign type units. I use the term "hint"
> throughout the code, but I don't mind another name if someone has a
> better idea.
>
> The first part is to read the actual foreign TU list from the
> .debug_names index and create signatured_type objects out of them. This
> is done in the new function create_foreign_type_units_from_debug_names.
> Append the newly created signatured_type to the
> mapped_debug_names_reader::foreign_type_units vector, which will be used
> later to resolve DW_IDX_type_unit indices. Populate the
> dwarf2_per_bfd::signatured_types set, which contains signatured_types
> indexed by signature. And finally, transfer ownership of the object to
> the dwarf2_per_bfd::all_units vector.
>
> Previously, all dwarf2_per_cu (including signatured_type) objects were
> created with a non-nullptr section. With foreign type units, we don't
> know the section at creation time. We also don't know the offset into
> section nor the size of the unit. Therefore, add a
> dwarf2_per_bfd::allocate_signatured_type overload that takes just the
> signature. Remove the "section != nullptr" assert from the
> dwarf2_per_cu constructor, but add it to the other allocate_* methods.
>
> Since the new create_foreign_type_units_from_debug_names function adds
> items to the dwarf2_per_bfd::all_units vector, the vector needs to be
> sorted after create_foreign_type_units_from_debug_names runs. Remove
> the finalize_all_units call from create_all_units, making the callers
> responsible to call it.
>
> The next step is to read the hint CU attributes when scanning the index
> entries. Rework mapped_debug_names_reader::scan_one_entry to remember
> which kind of unit references it saw for the entry (comp, type and/or
> foreign type) and then figure out what this means. The logic is:
>
> - Did the entry reference a foreign type unit? If so, it's a foreign
> type unit. Does it also reference a hint CU? If not, drop the
> entry, there's nothing useful we can do with it.
>
> - Otherwise, did the entry reference a (non-foreign) type unit? Then
> it's a regular type unit. If so, it shouldn't also have a
> DW_IDX_compile_unit.
>
> - Otherwise, did the entry reference a comp unit? If so, it's a comp
> unit.
>
> - Otherwise, we don't know what unit the entry references, it's an
> error.
>
> Since the .debug_name index attaches hint CU attributes to individual
> index entries, my initial implementation added the hint CU information
> to the cooked_index_entry structure. I am not sure why DWARF 5 chose to
> do it this way, as opposed to attaching one hint per foreign TU. Does
> this mean that two type units with the same signature could be different
> and, for a specific index entry, it would be important to find one
> specific instance of the type unit over the others? I have no idea.
>
> However, I know that the current GDB DWARF reader is not able to load
> multiple type units with the same signature but different content. Once
> it loads one type unit with a given signature, all subsequent references
> to that signature will use that loaded type unit. I therefore chose to
> have the .debug_names reader record just one hint CU per foreign TU.
> This avoids growing the cooked_index_entry structure for nothing, and
> having to pass through this information through multiple layers.
>
> The next step is to locate the .dwo file containing the foreign TUs when
> we need them. This sometimes makes use of the hint CU, but not always.
> I identified these 3 code paths:
>
> 1. When the type unit gets expanded directly, for instance if you use
> "ptype" and there is a direct match into the type unit. This case
> is handled in load_full_type_unit, calling a new function
> fill_in_sig_entry_from_per_cu_hint. This one uses the hint recorded
> by the .debug_names reader. When a cooked index entry exists and
> refers to a foreign TU for which the section is not yet known, we
> know that there exists a hint, otherwise we wouldn't have created
> the entry in the first place.
>
> 2. The second one is when the type unit is referenced by some other
> unit. This case is handled in follow_die_sig_1, calling another new
> function fill_in_sig_entry_from_dwo_file. In this case, we know
> which unit is referring to the TU, so we use that unit's dwo file to
> fill in the details. As explained in the comment, this is sometimes
> just an optimization, but sometimes also necessary, if the TU
> does not have a hint, due to it not containing any indexed name.
>
> 3. Similarly, in dwarf2_base_index_functions::expand_all_symtabs, we
> might have to handle foreign type units for which we don't have a
> hint. I initially implemented something in two passes, to go dig in
> the dwo_file structures to find those TUs, but ended up choosing to
> just skip them, for the reasons explained in the comment there.
>
> Setting a dwarf2_per_cu's section a posteriori breaks the assumed
> ordering of the dwarf2_per_bfd::all_units vector. After setting the
> section, re-sort the vector.
>
> Add a target board to exercise this new code. This board builds with:
>
> - type units (-fdebug-types-section)
> - split DWARF (-gsplit-dwarf)
> - .debug_names index (created by GDB)
>
> I ran the whole testsuite with this board file and it's not perfect, but
> the results are comparable to the dwarf5-fission-debug-types board, for
> instance.
>
> There is one known failure that I am unable to get to the bottom of. It
> seems orthogonal to my change though, more like an indexer or symbol
> reader issue. There are maybe more of this kind, but this is one
> example:
>
> FAIL: gdb.ada/tick_length_array_enum_idx.exp: ptype variable_table'length (GDB internal error)
>
> /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:1839: internal-error: search_one: Assertion `symtab != nullptr' failed.
>
> The problem appears to be that a cooked index lookup for symbol
> variable_table says that a given TU should contain a match. But then
> trying to expand the TU makes dw2_instantiate_symtab yield a nullptr
> compunit_symtab, I think because the symbol reader found nothing
> interesting symbol-wise. And then the assert in search_one triggers.
>
> The issue seems sensitive to some aspects of the environment (gnat
> version?). I am able to reproduce the issue on Arch Linux (gnat 15)
> with:
>
> $ make check TESTS="gdb.ada/tick_length_array_enum_idx.exp" RUNTESTFLAGS="--target_board=dwarf5-fission-debug-types-debug-names"
>
> But it doesn't reproduce on Debian 13 (gnat 14), Ubuntu 24.04 (gnat
> 13) or Fedora Rawhide (gnat 16).
>
> Change-Id: I0d4ccc1cbbce3a337794341744d24091e8549d7f
> Approved-By: Tom Tromey <tom@tromey.com>
> ---
> gdb/dwarf2/read-debug-names.c | 212 ++++++++++++++----
> gdb/dwarf2/read.c | 167 +++++++++++++-
> gdb/dwarf2/read.h | 37 ++-
> gdb/dwarf2/types.h | 2 +
> ...dwarf5-fission-debug-types-debug-names.exp | 29 +++
> 5 files changed, 392 insertions(+), 55 deletions(-)
> create mode 100644 gdb/testsuite/boards/dwarf5-fission-debug-types-debug-names.exp
>
> diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
> index 487e2ea87edb..a062c1ad2562 100644
> --- a/gdb/dwarf2/read-debug-names.c
> +++ b/gdb/dwarf2/read-debug-names.c
> @@ -88,9 +88,13 @@ struct mapped_debug_names_reader
>
> uint8_t offset_size = 0;
> uint32_t cu_count = 0;
> - uint32_t tu_count = 0, bucket_count = 0, name_count = 0;
> + uint32_t tu_count = 0;
> + uint32_t foreign_tu_count = 0;
> + uint32_t bucket_count = 0;
> + uint32_t name_count = 0;
> const gdb_byte *cu_table_reordered = nullptr;
> const gdb_byte *tu_table_reordered = nullptr;
> + const gdb_byte *foreign_tu_table_reordered = nullptr;
> const uint32_t *bucket_table_reordered = nullptr;
> const uint32_t *hash_table_reordered = nullptr;
> const gdb_byte *name_table_string_offs_reordered = nullptr;
> @@ -122,7 +126,11 @@ struct mapped_debug_names_reader
>
> /* 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;
> + std::vector<signatured_type *> type_units;
> +
> + /* List of foreign TUs in the same order as found in the index (DWARF 5
> + section 6.1.1.4.4). */
> + std::vector<signatured_type *> foreign_type_units;
>
> /* Even though the scanning of .debug_names and creation of the
> cooked index entries is done serially, we create multiple shards
> @@ -217,7 +225,10 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
> cooked_index_flag flags = 0;
> sect_offset die_offset {};
> enum language lang = language_unknown;
> - dwarf2_per_cu *per_cu = nullptr;
> + dwarf2_per_cu *comp_unit = nullptr;
> + signatured_type *type_unit = nullptr;
> + signatured_type *foreign_type_unit = nullptr;
> +
> for (const auto &attr : indexval.attr_vec)
> {
> ULONGEST ull;
> @@ -282,7 +293,6 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
> {
> case DW_IDX_compile_unit:
> {
> - /* Don't crash on bad data. */
> if (ull >= this->comp_units.size ())
> {
> complain_about_index_entry
> @@ -292,13 +302,17 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
> continue;
> }
>
> - per_cu = this->comp_units[ull];
> + comp_unit = this->comp_units[ull];
> break;
> }
> case DW_IDX_type_unit:
> {
> - /* Don't crash on bad data. */
> - if (ull >= this->type_units.size ())
> + if (ull < this->type_units.size ())
> + type_unit = this->type_units[ull];
> + else if (auto foreign_idx = ull - this->type_units.size ();
> + foreign_idx < this->foreign_type_units.size ())
> + foreign_type_unit = this->foreign_type_units[foreign_idx];
> + else
> {
> complain_about_index_entry
> (abfd, name, offset_in_entry_pool,
> @@ -307,15 +321,10 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
> continue;
> }
>
> - per_cu = this->type_units[ull];
> 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 == nullptr)
> - per_cu = this->comp_units[0];
> break;
> case DW_IDX_parent:
> parent = ull;
> @@ -339,27 +348,117 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
> }
> }
>
> - /* Skip if we couldn't find a valid CU/TU index. */
> - if (per_cu != nullptr)
> + /* From DWARF 5 section 6.1.1.3 ("Per-CU versus Per-Module Indexes"):
> +
> + In a per-CU index, the CU list may have only a single entry, and index
> + entries may omit the CU attribute. */
> + if (comp_unit == nullptr
> + && type_unit == nullptr
> + && foreign_type_unit == nullptr)
> {
> - dwarf_read_debug_printf_v
> - (" -> die_offset %s, per_cu offset %s",
> - sect_offset_str (die_offset),
> - sect_offset_str (per_cu->sect_off ()));
> + if (this->comp_units.size () != 1)
> + {
> + complain_about_index_entry
> + (abfd, name, offset_in_entry_pool,
> + _(".debug_names entry is missing CU index, but index has %zu CUs "
> + "(expecting 1)"),
> + this->comp_units.size ());
> + return entry;
> + }
>
> - *result
> - = indices[next_shard].add (die_offset, (dwarf_tag) indexval.dwarf_tag,
> - flags, lang, name, nullptr, per_cu);
> -
> - ++next_shard;
> - if (next_shard == indices.size ())
> - next_shard = 0;
> -
> - entry_pool_offsets_to_entries.emplace (offset_in_entry_pool, *result);
> + comp_unit = this->comp_units[0];
> }
> - else
> - dwarf_read_debug_printf_v (" -> no valid CU/TU, skipping");
>
> + /* Figure out which unit this entry refers to. */
> + dwarf2_per_cu *actual_unit;
> +
> + if (foreign_type_unit != nullptr)
> + {
> + if (type_unit != nullptr)
> + {
> + complain_about_index_entry
> + (abfd, name, offset_in_entry_pool,
> + _(".debug_names entry refers to two TUs"));
> + return entry;
> + }
> +
> + /* Implement this part of DWARF 5 section 6.1.1.2 ("Structure of the Name
> + Index"):
> +
> + When an index entry refers to a foreign type unit, it may have
> + attributes for both CU and (foreign) TU. For such entries, the CU
> + attribute gives the consumer a reference to the CU that may be used
> + to locate a split DWARF object file that contains the type unit. */
> + if (comp_unit == nullptr)
> + {
> + /* If a foreign type unit does not say which compile unit to follow
> + to find it, it's pretty much useless. */
> + complain_about_index_entry
> + (abfd, name, offset_in_entry_pool,
> + _(".debug_names entry refers to foreign type unit but "
> + "no compile unit"));
> + return entry;
> + }
> +
> + actual_unit = foreign_type_unit;
> +
> + /* .debug_names attaches one "hint" CU per index entry, insinuating that
> + for some names / index entries, it is important which .dwo we choose to
> + locate the TU. Even if it's important, the DWARF reader is not
> + currently able to load multiple versions of the same TU. So just
> + record one hint CU for each foreign TU. */
> + if (foreign_type_unit->hint_per_cu == nullptr)
> + {
> + foreign_type_unit->hint_per_cu = comp_unit;
> + dwarf_read_debug_printf_v
> + (" hint CU for foreign type unit with signature %s: "
> + "unit offset %s",
> + hex_string (foreign_type_unit->signature),
> + sect_offset_str (comp_unit->sect_off ()));
> + }
> + }
> + else if (type_unit != nullptr)
> + {
> + if (comp_unit != nullptr)
> + {
> + complain_about_index_entry
> + (abfd, name, offset_in_entry_pool,
> + _(".debug_names entry refers to both a CU and a TU"));
> + return entry;
> + }
> +
> + actual_unit = type_unit;
> + }
> + else if (comp_unit != nullptr)
> + actual_unit = comp_unit;
> + else
> + {
> + complain_about_index_entry
> + (abfd, name, offset_in_entry_pool,
> + _(".debug_names entry is missing a CU or TU reference"));
> + return entry;
> + }
> +
> + gdb_assert (actual_unit != nullptr);
> +
> + if (foreign_type_unit != nullptr)
> + dwarf_read_debug_printf_v (" -> signature %s, DIE offset: %s",
> + hex_string (foreign_type_unit->signature),
> + sect_offset_str (die_offset));
> + else
> + dwarf_read_debug_printf_v (" -> unit offset %s, DIE offset %s",
> + sect_offset_str (actual_unit->sect_off ()),
> + sect_offset_str (die_offset));
> +
> + *result = indices[next_shard].add (die_offset,
> + (dwarf_tag) indexval.dwarf_tag, flags,
> + lang, name, nullptr, actual_unit);
> +
> + ++next_shard;
> + if (next_shard == indices.size ())
> + next_shard = 0;
> +
> + entry_pool_offsets_to_entries.emplace (offset_in_entry_pool, *result);
> return entry;
> }
>
> @@ -553,7 +652,7 @@ build_and_check_tu_list_from_debug_names (dwarf2_per_objfile *per_objfile,
> return false;
> }
>
> - map.type_units.emplace_back (per_cu);
> + map.type_units.emplace_back (per_cu->as_signatured_type ());
> }
>
> return true;
> @@ -665,22 +764,12 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
>
> /* foreign_type_unit_count - The number of TUs in the foreign TU
> list. */
> - uint32_t foreign_tu_count = read_4_bytes (abfd, addr);
> + map.foreign_tu_count = read_4_bytes (abfd, addr);
> addr += 4;
>
> dwarf_read_debug_printf ("cu_count: %u, tu_count: %u, "
> "foreign_tu_count: %u",
> - map.cu_count, map.tu_count, foreign_tu_count);
> -
> - if (foreign_tu_count != 0)
> - {
> - warning (_("Section .debug_names in %ps has unsupported %lu foreign TUs, "
> - "ignoring .debug_names."),
> - styled_string (file_name_style.style (),
> - filename),
> - static_cast<unsigned long> (foreign_tu_count));
> - return false;
> - }
> + map.cu_count, map.tu_count, map.foreign_tu_count);
>
> /* bucket_count - The number of hash buckets in the hash lookup
> table. */
> @@ -761,6 +850,10 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
> map.tu_table_reordered = addr;
> addr += map.tu_count * map.offset_size;
>
> + /* List of foreign TUs */
> + map.foreign_tu_table_reordered = addr;
> + addr += map.foreign_tu_count * sizeof (std::uint64_t);
> +
> /* Hash Lookup Table */
> map.bucket_table_reordered = reinterpret_cast<const uint32_t *> (addr);
> addr += map.bucket_count * 4;
> @@ -918,6 +1011,35 @@ 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);
> }
>
> +/* Create signatured_type objects for the foreign TU list in MAP. */
> +
> +static void
> +create_foreign_type_units_from_debug_names (dwarf2_per_bfd *per_bfd,
> + mapped_debug_names_reader &map)
> +{
> + for (uint32_t i = 0; i < map.foreign_tu_count; ++i)
> + {
> + /* The list of foreign TUs is a list of 64-bit (DW_FORM_ref_sig8) type
> + signatures representing type units placed in .dwo files. All we know
> + about them for now is the signature. */
> + const gdb_byte *ptr
> + = map.foreign_tu_table_reordered + i * sizeof (std::uint64_t);
> + std::uint64_t sig
> + = extract_unsigned_integer (ptr, sizeof (std::uint64_t),
> + map.dwarf5_byte_order);
> +
> + dwarf_read_debug_printf_v (" Foreign TU %u (%u): signature %s", i,
> + i + map.tu_count, hex_string (sig));
> +
> + signatured_type_up sig_type
> + = per_bfd->allocate_signatured_type (sig);
> +
> + map.foreign_type_units.emplace_back (sig_type.get ());
> + per_bfd->signatured_types.emplace (sig_type.get ());
> + per_bfd->all_units.emplace_back (sig_type.release ());
> + }
> +}
> +
> /* See read-debug-names.h. */
>
> bool
> @@ -975,6 +1097,12 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
> return false;
> }
>
> + create_foreign_type_units_from_debug_names (per_objfile->per_bfd, map);
> +
> + /* create_foreign_type_units_from_debug_names may add more entries to the
> + ALL_UNITS vector, so it must be called before finalize_all_units. */
> + finalize_all_units (per_objfile->per_bfd);
> +
> per_bfd->debug_aranges.read (per_objfile->objfile);
>
> /* There is a single address map for the whole index (coming from
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index d061bc22b12d..4d8923d3ca7a 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -695,6 +695,13 @@ static struct die_info *follow_die_ref (struct die_info *,
> const struct attribute *,
> struct dwarf2_cu **);
>
> +static void fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
> + signatured_type *sig_entry,
> + dwo_unit *dwo_entry);
> +
> +static void fill_in_sig_entry_from_per_cu_hint
> + (dwarf2_per_objfile &per_objfile, signatured_type &sig_type);
> +
> static struct die_info *follow_die_sig (struct die_info *,
> const struct attribute *,
> struct dwarf2_cu **);
> @@ -1415,6 +1422,7 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section,
> sect_offset sect_off, unsigned int length,
> bool is_dwz)
> {
> + gdb_assert (section != nullptr);
> dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off,
> length, is_dwz));
> result->index = all_units.size ();
> @@ -1431,6 +1439,7 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
> bool is_dwz,
> ULONGEST signature)
> {
> + gdb_assert (section != nullptr);
> auto result
> = std::make_unique<signatured_type> (this, section, sect_off, length,
> is_dwz, signature);
> @@ -1439,6 +1448,20 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
> return result;
> }
>
> +/* See read.h. */
> +
> +signatured_type_up
> +dwarf2_per_bfd::allocate_signatured_type (ULONGEST signature)
> +{
> + auto result
> + = std::make_unique<signatured_type> (this, nullptr,
> + invalid_sect_offset,
> + 0, false, signature);
> + result->index = all_units.size ();
> + this->num_type_units++;
> + return result;
> +}
> +
> /* Subroutine of dw2_get_file_names_reader to simplify it.
> Return the file name for the given file_entry.
> CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
> @@ -1722,6 +1745,20 @@ dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
>
> for (dwarf2_per_cu *per_cu : all_units_range (per_objfile->per_bfd))
> {
> + /* If a .debug_names index contains a foreign TU but no index entry
> + references it, the TU won't have a hint CU. This is a problem, because
> + we won't be able to locate it. Skip them, for the following reasons:
> +
> + - If they don't contain anything worthy of a named index entry, they
> + are unlikely to contain anything interesting, symbol-wise.
> + - They are likely to be referred to by some other unit (otherwise,
> + why does it exist?), so will get expanded anyway. */
> + if (signatured_type *sig_type = per_cu->as_signatured_type ();
> + (sig_type != nullptr
> + && sig_type->section () == nullptr
> + && sig_type->hint_per_cu == nullptr))
> + continue;
> +
> /* We don't want to directly expand a partial CU, because if we
> read it with the wrong language, then assertion failures can
> be triggered later on. See PR symtab/23010. So, tell
> @@ -2223,8 +2260,7 @@ add_type_unit (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section,
> return emplace_ret.first;
> }
>
> -/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
> - Fill in SIG_ENTRY with DWO_ENTRY. */
> +/* Fill in the missing details in SIG_ENTRY from DWO_ENTRY. */
>
> static void
> fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
> @@ -2680,6 +2716,10 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
> {
> struct objfile *objfile = per_objfile.objfile;
> struct dwarf2_section_info *section = this_cu.section ();
> +
> + /* Any foreign TU must have been located before getting here. */
> + gdb_assert (section != nullptr);
> +
> bfd *abfd = section->get_bfd_owner ();
> const gdb_byte *begin_info_ptr;
> struct dwarf2_section_info *abbrev_section;
> @@ -3278,6 +3318,7 @@ cooked_index_worker_debug_info::do_reading ()
> dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
>
> create_all_units (m_per_objfile);
> + finalize_all_units (m_per_objfile->per_bfd);
> process_type_units (m_per_objfile, &m_index_storage);
>
> if (!per_bfd->debug_aranges.empty ())
> @@ -3358,6 +3399,19 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
>
> /* See read.h. */
>
> +void
> +dwarf2_per_bfd::sort_all_units ()
> +{
> + std::sort (this->all_units.begin (), this->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. */
> +
> void
> finalize_all_units (dwarf2_per_bfd *per_bfd)
> {
> @@ -3365,14 +3419,7 @@ finalize_all_units (dwarf2_per_bfd *per_bfd)
> gdb_assert (per_bfd->all_units.size ()
> == per_bfd->num_comp_units + per_bfd->num_type_units);
>
> - /* Ensure that the all_units vector is in the expected order for
> - dwarf2_find_containing_unit to be able to perform a binary search. */
> - std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
> - [] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b)
> - {
> - return all_units_less_than (*a, { b->section (),
> - b->sect_off () });
> - });
> + per_bfd->sort_all_units ();
> }
>
> /* See read.h. */
> @@ -3410,7 +3457,6 @@ 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 ();
> }
>
> @@ -17104,6 +17150,77 @@ dwarf2_get_die_type (cu_offset die_offset, dwarf2_per_cu *per_cu,
> return get_die_type_at_offset (die_offset_sect, per_cu, per_objfile);
> }
>
> +/* Fill in the missing details in SIG_TYPE from DWO_FILE.
> +
> + Error out if there isn't a type unit with the appropriate signature in
> + DWO_FILE. */
> +
> +static void
> +fill_in_sig_entry_from_dwo_file (dwarf2_per_objfile &per_objfile,
> + signatured_type &sig_type, dwo_file &dwo_file)
> +{
> + gdb_assert (sig_type.section () == nullptr);
> +
> + dwo_unit *dwo_tu = dwo_file.find_tu (sig_type.signature);
> + if (dwo_tu == nullptr)
> + error (_(DWARF_ERROR_PREFIX
> + "Unable to locate type unit with signature %s in DWO file %s "
> + "[in module %s]"),
> + hex_string (sig_type.signature), dwo_file.dwo_name.c_str (),
> + objfile_name (per_objfile.objfile));
> +
> + fill_in_sig_entry_from_dwo_entry (&per_objfile, &sig_type, dwo_tu);
> + sig_type.set_section (dwo_tu->section);
> + sig_type.set_sect_off (dwo_tu->sect_off);
> + sig_type.set_length (dwo_tu->length);
> +
> + /* Setting SIG_TYPE's section invalidates the ALL_UNITS vector order,
> + re-sort it. */
> + per_objfile.per_bfd->sort_all_units ();
> +}
> +
> +/* Fill in the missing details in SIG_TYPE from its hint CU.
> +
> + Error out if we're unable to locate the .dwo file using the hint CU. */
> +
> +static void
> +fill_in_sig_entry_from_per_cu_hint (dwarf2_per_objfile &per_objfile,
> + signatured_type &sig_type)
> +{
> + gdb_assert (sig_type.section () == nullptr);
> + gdb_assert (sig_type.hint_per_cu != nullptr);
> +
> + dwarf2_per_cu *hint_per_cu = sig_type.hint_per_cu;
> + dwo_unit *dwo_unit;
> +
> + /* If a dwarf2_cu already exists for HINT_PER_CU, no need to build another
> + one. */
> + if (dwarf2_cu *hint_cu = per_objfile.get_cu (hint_per_cu);
> + hint_cu != nullptr)
> + dwo_unit = hint_cu->dwo_unit;
> + else
> + {
> + /* Constructing this cutu_reader will look for the .dwo file, creating
> + the dwo_file if necessary. */
> + abbrev_table_cache abbrev_table_cache;
> + cutu_reader reader (*hint_per_cu, per_objfile, nullptr, true,
> + std::nullopt, abbrev_table_cache);
> +
> + /* dwo_unit is owned by the per_bfd, which outlives the reader. */
> + dwo_unit = reader.cu ()->dwo_unit;
> + }
> +
> + if (dwo_unit == nullptr)
> + error (_(DWARF_ERROR_PREFIX
> + "Hint compilation unit for foreign type unit with signature %s is "
> + "not in a DWO file [in module %s]"),
> + hex_string (sig_type.signature),
> + objfile_name (per_objfile.objfile));
> +
> + fill_in_sig_entry_from_dwo_file (per_objfile, sig_type,
> + *dwo_unit->dwo_file);
> +}
> +
> /* Follow type unit SIG_TYPE referenced by SRC_DIE.
> On entry *REF_CU is the CU of SRC_DIE.
> On exit *REF_CU is the CU of the result.
> @@ -17119,6 +17236,28 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
> we can get here for DW_AT_imported_declaration where we need
> the DIE not the type. */
>
> + /* If SIG_TYPE's section is not set, it means it's a .debug_names foreign
> + type unit for which we don't know the containing file or section yet.
> + Use the referencing CU as the hint: we know there must exist a TU with
> + the correct signature in its .dwo file, and that .dwo is already open,
> + might as well use it.
> +
> + But this is not only an optimization. If a .debug_names foreign unit
> + does not have any index entry referencing it, then we don't have any
> + "hint CU" for it. The only hint we have is the referencing CU. */
> + if (sig_type->section () == nullptr)
> + {
> + if ((*ref_cu)->dwo_unit == nullptr)
> + error (_(DWARF_ERROR_PREFIX
> + "Unit referencing foreign type unit with signature %s is "
> + "not from a DWO file [in module %s]"),
> + hex_string (sig_type->signature),
> + objfile_name (per_objfile->objfile));
> +
> + fill_in_sig_entry_from_dwo_file (*per_objfile, *sig_type,
> + *(*ref_cu)->dwo_unit->dwo_file);
> + }
> +
> dwarf2_cu *sig_cu = ensure_loaded_type_unit (sig_type, per_objfile);
>
> if (sig_cu == nullptr)
> @@ -17299,6 +17438,12 @@ load_full_type_unit (signatured_type *sig_type,
> gdb_assert (sig_type->is_debug_types ());
> gdb_assert (per_objfile->get_cu (sig_type) == nullptr);
>
> + /* If the section is not set, this is a .debug_names foreign type unit for
> + which we don't know the containing file nor section yet. For these, we
> + must have a "hint" CU to follow to find the file and section. */
> + if (sig_type->section () == nullptr)
> + fill_in_sig_entry_from_per_cu_hint (*per_objfile, *sig_type);
> +
> abbrev_table_cache abbrev_table_cache;
> cutu_reader reader (*sig_type, *per_objfile, nullptr, false,
> std::nullopt, abbrev_table_cache);
> diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
> index a0811fe0d377..12dc6224d8c0 100644
> --- a/gdb/dwarf2/read.h
> +++ b/gdb/dwarf2/read.h
> @@ -110,7 +110,6 @@ struct dwarf2_per_cu
> m_per_bfd (per_bfd)
> {
> gdb_assert (per_bfd != nullptr);
> - gdb_assert (section != nullptr);
> }
>
> private:
> @@ -285,9 +284,24 @@ struct dwarf2_per_cu
> dwarf2_section_info *section () const
> { return m_section; }
>
> + /* Set the section of this unit. */
> + void set_section (dwarf2_section_info *section)
> + {
> + gdb_assert (section != nullptr);
> + gdb_assert (m_section == nullptr);
> + m_section = section;
> + }
> +
> sect_offset sect_off () const
> { return m_sect_off; }
>
> + /* Set the section offset of this unit. */
> + void set_sect_off (sect_offset sect_off)
> + {
> + gdb_assert (m_sect_off == invalid_sect_offset);
> + m_sect_off = sect_off;
> + }
> +
> bool is_dwz () const
> { return m_is_dwz; }
>
> @@ -482,6 +496,12 @@ struct signatured_type : public dwarf2_per_cu
> /* Containing DWO unit.
> This field is valid iff per_cu.reading_dwo_directly. */
> struct dwo_unit *dwo_unit = nullptr;
> +
> + /* When using a .debug_names index, the section is not initially known for
> + foreign type units (aka skeletonless type units). This is a reference to
> + a CU that can be used to locate the .dwo file and section containing the
> + type unit. */
> + dwarf2_per_cu *hint_per_cu = nullptr;
> };
>
> using signatured_type_up = std::unique_ptr<signatured_type>;
> @@ -576,6 +596,10 @@ struct dwarf2_per_bfd
> return this->all_units[index].get ();
> }
>
> + /* Ensure that the all_units vector is in the expected order for
> + dwarf2_find_containing_unit to be able to perform a binary search. */
> + void sort_all_units ();
> +
> /* 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
> @@ -610,6 +634,12 @@ struct dwarf2_per_bfd
> bool is_dwz,
> ULONGEST signature);
>
> + /* A convenience function to allocate a signatured_type. The
> + returned object has its "index" field set properly.
> +
> + This one is used when only the signature is known at creation time. */
> + signatured_type_up allocate_signatured_type (ULONGEST signature);
> +
> /* Map all the DWARF section data needed when scanning
> .debug_info. */
> void map_info_sections (struct objfile *objfile);
> @@ -1334,7 +1364,10 @@ extern const char *read_indirect_string_at_offset
>
> extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
>
> -/* Create a list of all compilation units in OBJFILE. */
> +/* Create a list of all compilation units in OBJFILE.
> +
> + After it is done creating all units, the caller is responsible for calling
> + finalize_all_units. */
>
> extern void create_all_units (dwarf2_per_objfile *per_objfile);
>
> diff --git a/gdb/dwarf2/types.h b/gdb/dwarf2/types.h
> index 169b0fd08678..cb8ce33940ca 100644
> --- a/gdb/dwarf2/types.h
> +++ b/gdb/dwarf2/types.h
> @@ -31,6 +31,8 @@ DEFINE_OFFSET_TYPE (cu_offset, unsigned int);
> section. */
> DEFINE_OFFSET_TYPE (sect_offset, uint64_t);
>
> +constexpr auto invalid_sect_offset = static_cast<sect_offset> (-1);
> +
> static inline const char *
> sect_offset_str (sect_offset offset)
> {
> diff --git a/gdb/testsuite/boards/dwarf5-fission-debug-types-debug-names.exp b/gdb/testsuite/boards/dwarf5-fission-debug-types-debug-names.exp
> new file mode 100644
> index 000000000000..be8bebed1a43
> --- /dev/null
> +++ b/gdb/testsuite/boards/dwarf5-fission-debug-types-debug-names.exp
> @@ -0,0 +1,29 @@
> +# Copyright 2026 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +# A board that compiles with DWARF 5, split DWARF (fission) and type units,
> +# and generates a .debug_names index using GDB.
> +#
> +# Example usage:
> +# bash$ make check \
> +# RUNTESTFLAGS='--target_board=dwarf5-fission-debug-types-debug-names'
> +
> +set CC_WITH_TWEAKS_FLAGS "-n"
> +load_board_description "cc-with-tweaks"
> +
> +set_board_info debug_flags \
> + [join { "-gdwarf-5" \
> + "-gsplit-dwarf" \
> + "-fdebug-types-section" }]
--
Cheers,
Guinevere Larsen
It/she
[-- Attachment #2: gdb.log --]
[-- Type: text/x-log, Size: 13909 bytes --]
Test run by gwenthekween on Tue May 19 16:25:14 2026
Native configuration is x86_64-pc-linux-gnu
=== gdb tests ===
Schedule of variations:
unix
Running target unix
Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
Using /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
Running /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/debug-names-bad-cu-index.exp ...
Executing on build: rm -rf /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index (timeout = 300)
builtin_spawn -ignore SIGHUP rm -rf /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index
gdb_do_cache: universal_compile_options_c ( )
Executing on host: gcc -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/ccopts.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/ccopts.c (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/ccopts.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/ccopts.c
gdb_do_cache: get_compiler_info_1 ( c )
get_compiler_info: gcc-15-2-1
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
Executing on host: gcc -fno-stack-protector /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/_start.c -fdiagnostics-color=never -g -nostartfiles -lm -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/func_addr.x (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/_start.c -fdiagnostics-color=never -g -nostartfiles -lm -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/func_addr.x
Starting logfile: /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/gdb.in.1
builtin_spawn /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../gdb/gdb -nw -nx -q -iex set height 0 -iex set width 0 -data-directory /home/gwenthekween/Documents/downstream-build/gdb/data-directory -iex set interactive-mode on
(gdb) set height 0
(gdb) set width 0
(gdb) kill
The program is not being run.
(gdb) file /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/func_addr.x
Reading symbols from /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/func_addr.x...
(gdb) p _start_label - _start
$1 = 4
(gdb) disassemble _start
Dump of assembler code for function _start:
0x0000000000400330 <+0>: push %rbp
0x0000000000400331 <+1>: mov %rsp,%rbp
0x0000000000400334 <+4>: mov $0x0,%edi
0x0000000000400339 <+9>: call 0x400320 <exit@plt>
End of assembler dump.
(gdb) with print asm-demangle on -- x/2i _start+9
0x400339 <_start+9>: call 0x400320 <exit@plt>
0x40033e: Cannot access memory at address 0x40033e
(gdb) gdb_do_cache: is_64_target ( )
gdb_do_cache: universal_compile_options_c ( )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
Executing on host: gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/is_64_target.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/is_64_target.c (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/is_64_target.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/temp/2515157/is_64_target.c
gdb_do_cache: is_64_target ( )
gdb_do_cache: is_64_target ( )
gdb_do_cache: is_64_target ( )
gdb_do_cache: universal_compile_options_c ( )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
Executing on host: gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index0.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names.S (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index0.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names.S
gdb_do_cache: universal_compile_options_c ( )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
Executing on host: gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index1.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/_start.c (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never -c -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index1.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/_start.c
gdb_do_cache: universal_compile_options_c ( )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
gdb_do_cache: get_compiler_info_1 ( c )
Executing on host: gcc -fno-stack-protector /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index0.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index1.o -fdiagnostics-color=never -nostartfiles -lm -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index0.o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index1.o -fdiagnostics-color=never -nostartfiles -lm -o /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index
Starting logfile: /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/gdb.in.2
builtin_spawn /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../gdb/gdb -nw -nx -q -iex set height 0 -iex set width 0 -data-directory /home/gwenthekween/Documents/downstream-build/gdb/data-directory -iex set interactive-mode on
(gdb) set height 0
(gdb) set width 0
(gdb) dir
Reinitialize source path to empty? (y or n) y
Source directories searched: $cdir:$cwd
(gdb) dir /home/gwenthekween/Documents/downstream-gdb/gdb/testsuite/gdb.dwarf2
Source directories searched: /home/gwenthekween/Documents/downstream-gdb/gdb/testsuite/gdb.dwarf2:$cdir:$cwd
(gdb) show complaints
Max number of complaints about incorrect symbols is 0.
(gdb) set complaints 1
(gdb) maint set dwarf synchronous on
(gdb) PASS: gdb.dwarf2/debug-names-bad-cu-index.exp: maint set dwarf synchronous on
kill
The program is not being run.
(gdb) file /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index
Reading symbols from /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index...
warning: Section .debug_names has incorrect entry in CU table, ignoring .debug_names.
(gdb) maint print objfiles debug-names-bad-cu-index
Object file /home/gwenthekween/Documents/downstream-build/gdb/testsuite/outputs/gdb.dwarf2/debug-names-bad-cu-index/debug-names-bad-cu-index: Objfile at 0x36afb9e0, bfd at 0x3693ace0, 11 minsyms
Cooked index in use:
entries:
[0] ((cooked_index_entry *) 0x7faaf8004400)
name: _start
canonical: _start
qualified: _start
DWARF tag: DW_TAG_subprogram
flags: 0x0 []
DIE offset: 0xd
CU index: 0
parent: ((cooked_index_entry *) 0)
[1] ((cooked_index_entry *) 0x7faaf4006820)
name: int
canonical: int
qualified: int
DWARF tag: DW_TAG_base_type
flags: 0x2 [IS_STATIC]
DIE offset: 0x3e
CU index: 1
parent: ((cooked_index_entry *) 0)
[2] ((cooked_index_entry *) 0x7faaf40067f0)
name: struct_with_int_member
canonical: struct_with_int_member
qualified: struct_with_int_member
DWARF tag: DW_TAG_structure_type
flags: 0x2 [IS_STATIC]
DIE offset: 0x18
CU index: 1
parent: ((cooked_index_entry *) 0)
[3] ((cooked_index_entry *) 0x36fc5250)
name: int
canonical: int
qualified: int
DWARF tag: DW_TAG_base_type
flags: 0x2 [IS_STATIC]
DIE offset: 0x3e
CU index: 1
parent: ((cooked_index_entry *) 0)
[4] ((cooked_index_entry *) 0x36fc5220)
name: struct_with_int_member
canonical: struct_with_int_member
qualified: struct_with_int_member
DWARF tag: DW_TAG_structure_type
flags: 0x2 [IS_STATIC]
DIE offset: 0x18
CU index: 1
parent: ((cooked_index_entry *) 0)
main: ((cooked_index_entry *) 0)
address maps:
[0] ((addrmap *) 0x7faae4004220)
[0x0] ((dwarf2_per_cu *) 0)
[1] ((addrmap *) 0x7faadc004220)
[0x0] ((dwarf2_per_cu *) 0)
[2] ((addrmap *) 0x7fab08004220)
[0x0] ((dwarf2_per_cu *) 0)
[3] ((addrmap *) 0x7faaec004220)
[0x0] ((dwarf2_per_cu *) 0)
[4] ((addrmap *) 0x7fab00004220)
[0x0] ((dwarf2_per_cu *) 0)
[5] ((addrmap *) 0x7faae8004220)
[0x0] ((dwarf2_per_cu *) 0)
[6] ((addrmap *) 0x7faaf8004430)
[0x0] ((dwarf2_per_cu *) 0)
[7] ((addrmap *) 0x7faaf4006850)
[0x0] ((dwarf2_per_cu *) 0)
[8] ((addrmap *) 0x36fc5280)
[0x0] ((dwarf2_per_cu *) 0)
[0x400330] ((dwarf2_per_cu *) 0x7faaf40040e0)
[0x40033e] ((dwarf2_per_cu *) 0)
(gdb) PASS: gdb.dwarf2/debug-names-bad-cu-index.exp: find index type
PASS: gdb.dwarf2/debug-names-bad-cu-index.exp: find index type, check type is valid
FAIL: gdb.dwarf2/debug-names-bad-cu-index.exp: .debug_names used
FAIL: gdb.dwarf2/debug-names-bad-cu-index.exp: saw complaint
set complaints 0
(gdb) testcase /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../../downstream-gdb/gdb/testsuite/gdb.dwarf2/debug-names-bad-cu-index.exp completed in 0 seconds
=== gdb Summary ===
# of expected passes 3
# of unexpected failures 2
Executing on host: /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../gdb/gdb -nw -nx -q -iex "set height 0" -iex "set width 0" -data-directory /home/gwenthekween/Documents/downstream-build/gdb/data-directory -iex "set interactive-mode on" --version (timeout = 300)
builtin_spawn -ignore SIGHUP /home/gwenthekween/Documents/downstream-build/gdb/testsuite/../../gdb/gdb -nw -nx -q -iex set height 0 -iex set width 0 -data-directory /home/gwenthekween/Documents/downstream-build/gdb/data-directory -iex set interactive-mode on --version
GNU gdb (GDB) 18.0.50.20260513-git
Copyright (C) 2026 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
/home/gwenthekween/Documents/downstream-build/gdb/gdb version 18.0.50.20260513-git -nw -nx -q -iex "set height 0" -iex "set width 0" -data-directory /home/gwenthekween/Documents/downstream-build/gdb/data-directory -iex "set interactive-mode on"
runtest completed at Tue May 19 16:25:14 2026
next prev parent reply other threads:[~2026-05-19 19:43 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-11 15:40 [PATCH v3 0/7] Handle foreign type units in .debug_names Simon Marchi
2026-05-11 15:40 ` [PATCH v3 1/7] gdb/dwarf: move dwo_unit and dwo_file to dwo.h Simon Marchi
2026-05-13 15:18 ` Tom Tromey
2026-05-13 17:30 ` Simon Marchi
2026-05-11 15:40 ` [PATCH v3 2/7] gdb/dwarf: move dwarf2_cu::section to cu.c Simon Marchi
2026-05-11 15:40 ` [PATCH v3 3/7] gdb/dwarf: add dwo_file::find_tus Simon Marchi
2026-05-11 15:40 ` [PATCH v3 4/7] gdb/dwarf: generate foreign type units in .debug_names Simon Marchi
2026-05-11 15:40 ` [PATCH v3 5/7] gdb/dwarf: add debug output in read-debug-names.c Simon Marchi
2026-05-11 15:40 ` [PATCH v3 6/7] gdb/dwarf: add more context to complaints in mapped_debug_names_reader::scan_one_entry Simon Marchi
2026-05-11 15:40 ` [PATCH v3 7/7] gdb/dwarf: read foreign type units Simon Marchi
2026-05-19 19:42 ` Guinevere Larsen [this message]
2026-05-19 20:10 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=88ae1a52-4417-47d9-a01e-57365e436454@redhat.com \
--to=guinevere@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox