Simon Marchi [Thu, 7 May 2026 19:23:12 +0000 (15:23 -0400)]
binutils/configure: look for msgpack-c.pc (in addition to msgpack.pc)
msgpack.pc was renamed to msgpack-c.pc in this commit [1]. This means
that we now find both in the wild. For example Debian Bookworm has
msgpack.pc [2] while Debian Trixie has msgpack-c.pc [3].
Update the check in configure.ac to check for both. Nothing in the code
needs to change.
Alice Carlotti [Thu, 7 May 2026 06:08:53 +0000 (07:08 +0100)]
aarch64: Add new qualifier AARCH64_OPND_QLF_UNUSED
Replace QLF_NIL with QLF_UNUSED for qualifier sequence list padding.
This splits apart distinct qualifier meanings, and simplifies detection
of empty qualifier sequences.
Alice Carlotti [Thu, 29 Jan 2026 12:44:10 +0000 (12:44 +0000)]
aarch64: Add new qualifier ARCH64_OPND_QLF_UNKNOWN
Some uses of AARCH64_OPND_QLF_NIL actually represent an unknown operand
qualifier. The F_STRICT flag was added to disable the wild card
behaviour for most SVE instructions, but this just makes the code less
consistent and more confusing.
Add a new qualifer to indicate that the real qualifier is currently
unknown, and use this in any place where we need the wildcard behaviour
(and in a few other places where UNKNOWN is more descriptive than NIL).
For consistency (and as an extra check during development), change the
default qualifier value during parsing to AARCH64_OPND_QLF_ERR, and add
explicit qualifier assignments to each non-failure code path.
Alice Carlotti [Thu, 29 Jan 2026 12:10:43 +0000 (12:10 +0000)]
aarch64: Return QLF_ERR for error conditions
In vectype_to_qualifier and get_qualifier_from_partial_encoding, return
AARCH64_OPND_QLF_ERR instead of AARCH64_OPND_QLF_NIL to indicate an
error condition.
Alice Carlotti [Thu, 29 Jan 2026 12:14:33 +0000 (12:14 +0000)]
aarch64: Add QLF_ERR to aarch64_opnd_qualifiers
Add an entry to aarch64_opnd_qualifiers for AARCH64_OPND_QLF_ERR. This
should never be used (otherwise we would previously have had
out-of-bounds memory accesses), but it makes the array length match the
enum length, and might be slightly more robust.
Alice Carlotti [Thu, 29 Jan 2026 16:32:19 +0000 (16:32 +0000)]
aarch64: Append explicit NILs to qualifier sequences
For some opcodes, the NIL qualifier on the final operand was set
implicitly via empty initialisation of the unspecified entries in the
list of qualifier sequences. Make this assignment explicit, to avoid
depending on the numerical value of AARCH64_OPND_QLF_NIL.
Alice Carlotti [Fri, 1 May 2026 16:25:13 +0000 (17:25 +0100)]
aarch64: Make FPIMM0 qualifiers consistent
Two entries in the opcode table used QLF_S_H for the FPIMM0 operand
instead of the QLF_NIL operand used elsewhere. There is no good reason
for this inconsistency, so change them to use QLF_NIL as well.
Alice Carlotti [Fri, 30 Jan 2026 12:13:06 +0000 (12:13 +0000)]
aarch64: Fix qualifier sequences for cinc/cinv/cneg
The three-operand cinc/cinv/cneg instructions were incorrectly specified
with the same qualifier sequences as the four-operand variants, which
resulted in their third operand having an incorrect qualifier specified.
This works fine while AARCH64_OPND_QLF_NIL is treated as a wildcard, but
will break when that behaviour is removed.
Alice Carlotti [Thu, 29 Jan 2026 12:17:24 +0000 (12:17 +0000)]
aarch64: Fix ldst_lo12_determine_real_reloc_type
Add fallback handling for an invalid choice of opd0_qlf, instead of
hitting an assert when trying to use X registers in byte or half
instructions.
Additionally, simplify the code by inlining the relevant parts of
aarch64_get_expected_qualifer, and by deducing the array index directly
from the qualifier enum values (instead of looking up the element size
and computing its log).
This makes aarch64_get_expected_qualifier unused, so remove it.
Alice Carlotti [Fri, 30 Jan 2026 17:11:29 +0000 (17:11 +0000)]
aarch64: Add F_REQUIRES_SP and eliminate QLF_SP and QLF_WSP
Add a new opcode flag F_REQUIRES_SP and use that to enforce the
requirement for at least one SP operand in the mov (to/from SP) opcode.
This requirement was the only reason for the existence of the QLF_SP and
QLF_WSP qualifiers. Delete them, and remove the confusing code that
would switch between SP and non-SP qualifiers in the middle of qualifier
matching.
Alice Carlotti [Fri, 30 Jan 2026 12:04:06 +0000 (12:04 +0000)]
aarch64: Fix use of wrong zero enum value
aarch64_get_expected_qualifier was incorrectly comparing an
aarch64_opnd_qualifier_t against AARCH64_OPND_NIL instead of
AARCH64_OPND_QLF_NIL (these are the zero values of two different enums).
A previous patch incorrectly addressed the type mismatch by casting the
qualifier to (enum aarch64_opnd).
Fix it properly by removing the cast and updating the comparison to use
AARCH64_OPND_QLF_NIL.
Andrew Burgess [Fri, 8 May 2026 14:13:16 +0000 (15:13 +0100)]
gdb: use value::embedded_offset in check_pieced_synthetic_pointer
This commit builds on the previous two commits. You should go and
read them both for context.
Looking at the users of value::bits_synthetic_pointer, all callers but
two are now passing either the offset of a field within the value, or
hard-coded zero as they want to ask about the entire value.
The two exceptions are in coerce_pieced_ref (in dwarf2/expr.c) and in
value_addr (in valops.c) where we still pass value::embedded_offset.
The problem is that some of the other callers, where we currently pass
just a field offset, might also have a non-zero embedded offset,
specifically, the call in cp_print_value_fields is in this category.
In cp_print_value_fields we are printing fields from a value which is
potentially a base class contained within an instance of a derived
class, this will be represented by a non-zero embedded_offset, which
is currently not taken into account.
Additionally, the two callers that currently pass the
value::embedded_offset don't scale the embedded offset from bytes to
bits.
The failure to scale from bytes to bits is interesting, I originally
tried to create some tests that exposed this, but constantly failed.
It turns out, that in both these locations, in all code paths that I
could find, the value::embedded_offset will always be zero. For
example in coerce_pieced_ref, a reference cannot be a base class, and
so we never expect to see a non-zero embedded_offset in this case.
Similarly, in value_addr, the use of value::bits_synthetic_pointer is
within a block that only applies to reference types, which means the
embedded_offset will be zero.
Now within check_pieced_synthetic_pointer we already add the
value::offset into the bit_offset which is passed in. Remember, after
the previous two commits, the incoming bit_offset is (almost) always
the offset of a field within the value. The almost here is the two
cases mentioned above.
I propose that within check_pieced_synthetic_pointer we should take
into account both value::offset and value::embedded_offset. Then the
two cases that currently pass value::embedded_offset can be changed to
just pass zero.
With this done, and the previous two commits, we now have a consistent
model. value::bits_synthetic_pointer expects the (bit) offset of a
field within the value to check. In many cases this will be zero
meaning we want to check from the start of the value, but in some
cases it can be non-zero.
Then within value::bits_synthetic_pointer implementations, like
check_pieced_synthetic_pointer, we will take the value::offset and
value::embedded_offset into account, remembering to scale them from
bytes to bits.
I have also changed indirect_pieced_value to also take the
embedded_offset into account. I have done this for consistency rather
than necessity. I believe that the embedded_offset will always be
zero within indirect_pieced_value. The indirect_pieced_value function
is only called from value_ind (in valops.c), and only operates on
TYPE_CODE_PTR types (checked for in indirect_pieced_value). As a
TYPE_CODE_PTR cannot be the base class for a derived type, then we
don't expect to ever see a TYPE_CODE_PTR value with a non-zero
embedded_offset. But, having indirect_pieced_value take the embedded
offset into account is simple enough, and future proofs the code.
In both check_pieced_synthetic_pointer and indirect_pieced_value I
have changed uses of '8' to 'TARGET_CHAR_BIT', I was already touching
some of these lines, and I think TARGET_CHAR_BIT is clearer, but one
line in indirect_pieced_value was just updated to use TARGET_CHAR_BIT,
this is done for consistency.
The gdb.dwarf2/multi-piece-inherited-bitfield.exp test fails without
this patch, this exposes the case where the embedded_offset is
non-zero and we were previously failing to take this into account.
The gdb.dwarf2/multi-piece-primitive-field.exp test was something I
wrote while trying to exercise the coerce_pieced_ref code path some
more. It is an inheritance based version of the existing test, I was
wondering if this would result in a value with a non-zero
embedded_offset, but due to how the fields are extracted from the
aggregate prior to calling coerce_pieced_ref the embedded_offset is
always zero in this function.
Andrew Burgess [Fri, 8 May 2026 20:25:11 +0000 (21:25 +0100)]
gdb: remove embedded_offset argument that is always 0
For the background and motivation for this patch you should read the
previous commit.
The goal of this commit started as similar to the previous one; rename
the embedded_offset argument to generic_val_print_ref. To do this I
started tracing back which values are passed into this function so I
could make sure the new argument name matched the usage.
But it turns out that the only value that is ever passed to this
function is zero.
I believe that, like the last commit, the embedded_offset is actually
representing the offset of a field within a value. However, in all of
the use cases, the "field" being accessed is the entire value, hence
why we always pass 0, we are asking about the whole value starting
from the very beginning.
Given this, I couldn't bring myself to rename the argument. Let's just
remove it. It turns out that there's a bunch of functions in
valprint.c that take an argument called embedded_offset, which are
always zero.
This commit removes the argument, and updates the code to assume zero.
There should be no user visible changes after this commit.
This passes the result from value::embedded_offset as the first argument.
Though it's not clear from value.h, the number returned by
value::embedded_offset is a byte offset.
The value::bits_synthetic_pointer call can end up calling
check_pieced_synthetic_pointer, with the first argument to
value::bits_synthetic_pointer becoming the second argument to
check_pieced_synthetic_pointer. The second argument to
check_pieced_synthetic_pointer is called BIT_OFFSET, a value in bits.
Looking at how this argument is used confirms that it is expected to be
a value in bits, not bytes.
The fix should be easy, multiply the embedded offset by
TARGET_CHAR_BIT, but I think things are a little more complex than
this.
I started looking at how value::bits_synthetic_pointer is used, there
are only 7 uses, and they can be grouped as follows:
gdb/dwarf2/expr.c
gdb/valops.c
These call value::embedded_offset directly within the call to
value::bits_synthetic_pointer.
gdb/opencl-lang.c
This function is used as a wrapper that implements a
lval_funcs::check_synthetic_pointer callback, it adjusts the
arguments and then calls value::bits_synthetic_pointer. As such we'd
not expect to see embedded offset mentioned here as that would (we
assume) be handled by the caller.
gdb/valprint.c (in generic_val_print_ref)
This call passes an argument called 'embedded_offset', but the
function generic_val_print_ref is only used in one place, and the
embedded_offset is always passed as zero.
gdb/valprint.c (in valprint_check_validity)
This call also passes an argument called 'embedded_offset'. This
function is used in two places. In common_val_print the
embedded_offset is always passed as zero, but in
valprint_check_validity (in cp-valprint.c) the embedded_offset being
passed is the offset of a field within the value, not the value's
embedded_offset within some larger value.
gdb/cp-valprint.c
gdb/p-valprint.c
As with the call to valprint_check_validity in cp-valprint.c, these
two direct calls to value::bits_synthetic_pointer pass the offset of a
field within the value, rather than the value's embedded_offset.
What I see in the above is some confusion. In some places we are
passing the value::embedded_offset, while in other places we are
passing the offset of a field within the value itself.
If we consider the direct call to value::bits_synthetic_pointer in
gdb/cp-valprint.c, where a field offset is passed, then it should be
possible, that if we can create an object with a non-zero
embedded_offset (which isn't accounted for in this code path), then we
should see some bugs in GDB, and indeed, this is what I do see.
My plan for fixing this is to have the offset passed to
value::bits_synthetic_pointer always be a field offset within the value,
the value::embedded_offset will then be handled directly within the
various value::bits_synthetic_pointer implementations.
This commit is a small refactor in preparation for this fix.
I believe part of the confusion here is that we have functions that
take arguments called embedded_offset, when the value they should
accept is no longer the embedded offset.
So in this commit I propose renaming the embedded_offset argument to
field_byte_offset in valprint_check_validity. This is purely a
mechanical rename, there should be no user visible changes after this
commit.
The problem is that coerce_pieced_ref makes the following claim:
/* gdb represents synthetic pointers as pieced values with a single
piece. */
gdb_assert (closure != NULL);
gdb_assert (closure->pieces.size () == 1);
But this is not really true. If an aggregate type contains a synthetic
pointer, then it is possible that the aggregate type will have a
computed location consisting of multiple pieces. When GDB prints the
fields of that aggregate type these fields are extracted by calling
value::primitive_field. Within value::primitive_field the location of
the field is set by calling value::set_component_location.
When the parent value that holds the field has a computed location, the
field value gains a reference to the parent value's closure, this can be
seen in copy_pieced_value_closure in dwarf2/expr.c.
What this means is that, if the aggregate value has a multi-piece
computed location, then the synthetic pointer field will also have a
reference to that same multi-piece computed location, even if there is
really only a single piece that describes the synthetic pointer itself.
Some parts of GDB are already aware of this. If we look at
check_pieced_synthetic_pointer which implements the
value::bits_synthetic_pointer function, you'll see that this function
searches through all of the pieces to find the piece that covers the
value we are looking for, it then checks if that piece is an implicit
pointer location. But back in coerce_pieced_ref, after calling
value::bits_synthetic_pointer, we still make the assertion that there
will be just a single piece.
Fix this by copying the search through all pieces logic into
coerce_pieced_ref (see note on efficiency below). We now search through
all the pieces looking for a piece that describes the location of the
synthetic pointer, and we then use that piece to form the pointer's
value.
There are some assertions in the new code, these align with how
check_pieced_synthetic_pointer operates.
In addition, there is an error for the case where multiple pieces are
used to describe the location of a synthetic pointer. This case is
technically allowed by check_pieced_synthetic_pointer, but supporting
this would require changes to indirect_synthetic_pointer, so I propose
leaving that until we see such a case in the wild.
On efficiency, you'll notice that check_pieced_synthetic_pointer
performs a search through all the location pieces, and
coerce_pieced_ref also has to search through the pieces. It would be
nice if this could be avoided in order to avoid multiple searches.
Currently though coerce_pieced_ref calls
value->bits_synthetic_pointer, which is an API that should be agnostic
to the underlying implementation, i.e. shouldn't need to know that the
implementation is computed, so passing pieces back would be harder.
Maybe coerce_pieced_ref could avoid the value::bits_synthetic_pointer
call, and instead call check_pieced_synthetic_pointer directly, or
some related helper function, and could get the pieces back that way.
But this breaks the cleanly structured API that we currently have.
For now I'm leaving things as they are. My assumption is that the
number of pieces used to represent a value is pretty low, so the
search is actually pretty cheap.
There's a new test that uses the DWARF assembler to create a
representative example of a multi-piece aggregate that contains a
synthetic pointer member variable. This test triggers the assertion
before this commit.
Matthieu Longo [Mon, 30 Mar 2026 16:08:03 +0000 (17:08 +0100)]
gdb/python: work around missing symbols not yet part of Python limited API
Most Python API usages in GDB can be migrated to the limited API, except
the following:
- PEP-741's configuration structures and functions, which use opaque
types. They were originally intended to be part of the Python limited
API, but some Python core maintainers opposed their inclusion at the
time.
- PyOS_ReadlineFunctionPointer, a global variable storing a function
used to override PyOS_StdioReadline(). The signature has remained
unchanged for a long time.
- PyRun_InteractiveLoop, used to read and execute Python statements when
embedding an interactive interpreter. Its signature has also remained
stable for a long time.
Since no limited API alternatives exist for these, and given their long
history of ABI stability, one approach is to expose them in a GDB header
and rely on their continued stability. While this is not without risk,
it seems acceptable given the arguments above. This would remove the
remaining obstacles preventing GDB from being agnostic to the Python
version available at runtime.
That said, issues should be opened on CPython issue tracker to request
that these functions be included in the limited API in future versions.
Last but not least, GDB does not need to officially support the Python
limited API. The '--enable-py-limited-api' option can remain experimental,
with appropriate forewarnings about its limitations and guarantees.
This patch adds a new header, python-limited-api-missing.h, which
exposes symbols not yet part of the Python limited API.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
Matthieu Longo [Tue, 24 Mar 2026 13:29:01 +0000 (13:29 +0000)]
gdb/python: migrate Python initialization to use the new config API (PEP 741)
GDB currently initializes CPython using the PyConfig C API introduced in
Python 3.8 (PEP 597). From an ABI stability perspective, this API has a
major drawback: it exposes a plain structure whose fields may be added or
removed between Python versions. As a result, it was excluded from the
Python limited API.
Python 3.14 introduced a new configuration API (PEP 741) that avoids
exposing plain structures and instead, operates via opaque pointers.
This design makes it much more suitable for inclusion in the Python
limited API. Indeed, this was the original intent of the PEP-741 author.
However, CPython maintainers ultimately decided otherwise.
Since GDB aims at using the CPython stable API to avoid rebuilding for
each Python version, the absence of a configuration API in the limited
C API constitutes a blocker. Nevertheless, this can be worked around by
using PEP-741 configuration API, whose design is compatible with the
limited C API. It is relatively safe to assume that this API will stay
around for some time.
In this perspective, this patch adds support for using the PEP-741 config
API starting from Python 3.14. When Py_LIMITED_API is defined, the
required functions are exposed as external symbols via a workaround header.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
Jan Beulich [Fri, 15 May 2026 07:48:19 +0000 (09:48 +0200)]
RISC-V: make EFI app testcase consistent
Along the lines of what 43720b0cdd2a ("RISC-V: avoid ld crashes due to
bogus use by testcases") did, options passed to the assembler want to fit
those passed to the linker.
8 byte alignment is required for ldr relocation. Addresses are placed in IAT.
The size of the chunk on AArch64 is 8 bytes.
If IAT is not aligned to 8 bytes, the relocation issue appears.
This patch fixes this issue by aligning IAT to 8 bytes for PE32+.
binutils/ChangeLog:
* dlltool.c (make_head): Apply alignment to IAT.
(make_delay_head): Apply alignment to Delay IAT.
(main): Adjust 8 byte alignment for PE32+.
Jan Beulich [Fri, 15 May 2026 07:46:15 +0000 (09:46 +0200)]
RISC-V: improve .insn documentation
First of all, the "type" form of .insn does not permit (not even
optionally) a comma after the type, much like for ordinary insns a comma
is not permitted between insn mnemonic and first operand. The example
given actually properly shows that already.
While there, also update the .word related text: Mapping symbols have been
in use for quite some time.
Markus Metzger [Mon, 11 May 2026 08:53:21 +0000 (08:53 +0000)]
gdb: use all_threads() in for_each_thread()
In for_each_thread(), we use all_threads_safe(), which allows deleting the
thread. This it not needed in the cases where it is currently used and it
causes the iterator to get corrupted when threads are deleted in a nested
all_threads_safe() iteration.
One such scenario is as follows:
- remote debugging in non-stop mode
- one thread has hit a breakpoint
- one thread exited but GDB does not know about it, yet
- resume with 'continue -a'
- the continue command uses for_each_thread() to proceed threads individually
- the stopped thread starts an inline step-over (displaced stepping disabled)
- update_thread_list() learns about the exit and deletes the thread
- the safe iterator's m_next still points to the deleted thread
Alan Modra [Sun, 10 May 2026 23:51:27 +0000 (09:21 +0930)]
_bfd_elf_create_got_section .rela.got
_bfd_elf_create_got_section creates .rela.got or .rel.got before it
creates .got. This normally isn't a problem, but in some tests that
use a script to map uninteresting sections to a .junk section, if it
happens to be the first section so mapped then .junk becomes RELA
rather than the usual PROGBITS. Using a linker created dynobj makes
this more likely as the linker created bfd is put first on
link_info.input_bfds.
Alan Modra [Sun, 10 May 2026 23:50:52 +0000 (09:20 +0930)]
hppa64: get_opd in elf64_hppa_mark_exported_functions
late_size_sections is too late to be creating a dynamic section, as it
won't be mapped to an output section. So don't pretend that this will
do anything useful, and instead omit the traversal if opd_sec is NULL.
This bug showed up when using a linker-created dynobj.
* elf64-hppa.c (elf64_hppa_mark_exported_functions): Don't
attempt to create .opd here.
(elf64_hppa_late_size_sections): Only mark exported functions
for space in .opd if .opd exists.
(elf64_hppa_finalize_dynreloc): Make the test for a discared
other_rel_sec robust.
Alan Modra [Sun, 10 May 2026 23:50:29 +0000 (09:20 +0930)]
alpha: handle discarded got section
This fixes testsuite failures I noticed when changing dynobj to be
linker created, but I think the bug could be triggered by suitably
crafted linker scripts without any dynobj changes.
* elf64-alpha.c (elf64_alpha_final_link): Don't attempt to
write out a got section that has been discarded.
Alan Modra [Sun, 10 May 2026 23:48:29 +0000 (09:18 +0930)]
frv: elf32_frvfdpic_late_size_sections
This function runs passes over frvfdpic_relocs_info if dynobj is set,
which is OK since the two variables are both non-NULL or both NULL in
the current linker. That may change in the future, so test
frvfdpic_relocs_info directly rather than dynobj.
* elf32-frv.c (elf32_frvfdpic_late_size_sections): Omit dynobj
test. Instead test frvfdpic_relocs_info.
Alan Modra [Sun, 10 May 2026 23:47:52 +0000 (09:17 +0930)]
cris: dynobj mach
A comment in cris check_relocs bemoans not being able to access the
output bfd in adjust_dynamic_symbol. A little over three years after
the comment was written, commit f13a99db51c0 gave that access. So
let's make use of it and remove a restriction.
* elf32-cris.c (elf_cris_adjust_dynamic_symbol): Get mach from
output bfd, not dynobj.
(cris_elf_check_relocs): Remove dynobj mach check.
Alan Modra [Sun, 10 May 2026 23:47:42 +0000 (09:17 +0930)]
arm: delay setting of plt header and entry size
elf32_arm_create_dynamic_sections was used to set plt_header_size and
plt_entry_size. This necessitated a hack for using_thumb_only() as
the output file attributes used by that function are not set until
lang_check calls bfd_merge_private_bfd_data. Now the earliest use of
plt_header_size and plt_entry_size is in elf32_arm_late_size_sections,
called from bfd_elf_size_dynamic_sections. So this patch moves the
initialisation of these variables to elf32_arm_late_size_sections.
Initialising them there is after lang_check runs, and also guarantees
they are initialised for all later uses too.
The patch also moves initialisation of htab->stub_bfd earlier, and
calls to add_glue_sections_to_bfd and get_bfd_for_interworking from
ld/armelf.em to bfd/elf32-arm.c. I removed an abort in
elf32_arm_create_dynamic_sections too. It really doesn't improve
confidence that much to check that a function you have just called to
create dynamic sections has done its job.
PR 16017
bfd/
* elf32-arm.c (elf32_arm_plt_needs_thumb_stub_p): Formatting.
(elf32_arm_create_dynamic_sections): Remove abort. Move
initialisation of plt_header_size and plt_entry_size to..
(elf32_arm_late_size_sections): ..here.
(bfd_elf32_arm_add_glue_sections_to_bfd),
(bfd_elf32_arm_get_bfd_for_interworking): Make static.
(bfd_elf32_arm_set_target_params): Add stub_bfd param. Remove
output_bfd param. Make params const. Init globals->stub_bfd.
Set flags and EI_CLASS for stub_bfd. Call
add_glue_sections_to_bfd and get_bfd_for_interworking.
* elf32-arm.h (bfd_elf32_arm_add_glue_sections_to_bfd),
(bfd_elf32_arm_get_bfd_for_interworking): Delete declarations.
(bfd_elf32_arm_set_target_params): Update prototype.
ld/
* emultempl/armelf.em (arm_elf_create_output_section_statements):
Don't set stub bfd flags here, or call
add_glue_sections_to_bfd and get_bfd_for_interworking. Pass
stub bfd to set_target_params.
Simon Marchi [Mon, 11 May 2026 15:40:33 +0000 (11:40 -0400)]
gdb/dwarf: read foreign type units
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:
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>
Simon Marchi [Mon, 11 May 2026 15:40:32 +0000 (11:40 -0400)]
gdb/dwarf: add more context to complaints in mapped_debug_names_reader::scan_one_entry
I realize that complaints are not often enabled and shown, but if we
emit them, I think they should include enough context to help a user who
wishes to dig in the problem to pinpoint where the problem happened
exactly. For this reason, change the complaints in
mapped_debug_names_reader::scan_one_entry to include precisions
regarding which index entry is problematic exactly.
I am not attached to the particular format. I thought that because this
is extra contextual information, I would put it in the square brackets
at the end (which only shows the module name currently). However, it
would be nice to converge towards a format that we could replicate
elsewhere in the DWARF reader, so feel free to chime in.
I factored out the formatting to a separate function, because I will be
adding more of these in a subsequent patch, and it's easier to have the
formatting centralized.
I have not touched the "Unsupported .debug_names form" warning. If that
comes up, we probably don't care about the specific index entry, we just
need to implement support for that form.
Change-Id: Id68a0ae406a3ca620408576b81f893f05c7e3df2 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 11 May 2026 15:40:31 +0000 (11:40 -0400)]
gdb/dwarf: add debug output in read-debug-names.c
Add a bunch of debug prints in read-debug-names.c to dump what we are
reading. Some of if was helpful to me when debugging my changes to the
.debug_names reader and writer.
The debug prints are activated by "set debug dwarf-read" (I didn't feel
like we needed a separate knob for that). There are two levels of
verbosity. At level 1, we print everything that happens once, like the
header, counts, offsets of important parts of the index, etc. At
levels > 1, we print information about each abbrev, CU/TU and index
entry.
The output is made such that it is easy look at the output of readelf of
llvm-dwarfdump on the side and confirm that GDB is reading the index
right.
[dwarf-read] build_and_check_cu_list_from_debug_names: building CU list from .debug_names (56 CUs)
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 0: offset 0x0
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 1: offset 0x1bac
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 2: offset 0x4262
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 3: offset 0x4ff0
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 4: offset 0x59e9
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 5: offset 0x67af
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 6: offset 0x8e1a
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 7: offset 0xa5cc
[dwarf-read] build_and_check_cu_list_from_debug_names: CU 8: offset 0xcd39
Some entries:
[dwarf-read] scan_all_names: start: scanning 3418 names from .debug_names
[dwarf-read] scan_entries: scanning entries for name 1: "(anonymous namespace)" (entry pool offset 0x0)
[dwarf-read] scan_one_entry: entry pool offset 0x0: abbrev 1, tag DW_TAG_namespace
[dwarf-read] scan_one_entry: DW_IDX_compile_unit (DW_FORM_udata): 55
[dwarf-read] scan_one_entry: DW_IDX_die_offset (DW_FORM_ref_addr): 0x7d06b
[dwarf-read] scan_one_entry: DW_IDX_GNU_language (DW_FORM_udata): 33
[dwarf-read] scan_one_entry: DW_IDX_parent (DW_FORM_data4): 38201
[dwarf-read] scan_one_entry: -> die_offset 0x7d06b, per_cu offset 0x5af0e
[dwarf-read] scan_one_entry: entry pool offset 0xb: end of entries (abbrev 0)
[dwarf-read] scan_entries: scanning entries for name 2: "AUTO_SEEK_STREAM_STATE_PACKET_BEGAN" (entry pool offset 0xc)
[dwarf-read] scan_one_entry: entry pool offset 0xc: abbrev 2, tag DW_TAG_enumerator
[dwarf-read] scan_one_entry: DW_IDX_compile_unit (DW_FORM_udata): 17
[dwarf-read] scan_one_entry: DW_IDX_die_offset (DW_FORM_ref_addr): 0x1beea
[dwarf-read] scan_one_entry: DW_IDX_GNU_language (DW_FORM_udata): 29
[dwarf-read] scan_one_entry: DW_IDX_GNU_internal (DW_FORM_flag_present): 1
[dwarf-read] scan_one_entry: -> die_offset 0x1beea, per_cu offset 0x1a28e
[dwarf-read] scan_one_entry: entry pool offset 0x13: end of entries (abbrev 0)
Change-Id: I4a40bfb73fa7feccb5038814a7d1a1bcd4f6231b Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 11 May 2026 15:40:30 +0000 (11:40 -0400)]
gdb/dwarf: generate foreign type units in .debug_names
The DWARF 5 .debug_names index makes the distinction between local type
units and foreign type units. Local type units are those present
directly in the main file. Foreign type units are those present in .dwo
files. GDB only knows how to produce local type units today, which
leads to invalid indexes whenever there are type units in .dwo files.
To observe this, run test gdb.dwarf2/fission-with-type-unit.exp with
board cc-with-debug-names. The test passes, but we see this in the log:
(gdb) file
/home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/fission-with-type-unit^M
Reading symbols from
/home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/fission-with-type-unit...^M
warning: Section .debug_names has incorrect entry in TU table,
ignoring .debug_names.^M
These are the units involved in this test. The first and last CUs are
dummy CUs added by the DWARF assembler, they are not important.
- CU at offset 0x0 of .debug_info in fission-with-type-unit -- dummy
- CU at offset 0xc of .debug_info in fission-with-type-unit
- CU at offset 0x25 of .debug_info in fission-with-type-unit -- dummy
- TU at offset 0x0 of .debug_info.dwo in fission-with-type-unit-dw.dwo
The TU table claims that there is a TU at offset 0 in the main file
(fission-with-type-unit). This is wrong: the TU is in
fission-with-type-unit-dw.dwo. It should be listed in the Foreign TU
table instead.
This patch therefore teaches GDB to use the foreign TU table for TUs in
.dwo files.
A note about foreign type units and skeletons: in the early history of
split DWARF and type units, gcc 4.x used to create skeletons for type
units in .dwo files, but subsequent versions don't. DWARF 5 doesn't
have support for type unit skeletons at all. So skeletons for type
units are mostly a historical curiosity at this point, the norm is to
not have them. But if for some reason a type unit in a .dwo file had a
matching skeleton in the main file, then it would be ok for that TU to
be listed in the "TU table". The offset would be that of the skeleton.
While the list of CUs and local TUs contain the offset within the
.debug_info section where to find the unit, the foreign TU list only
contains the 8-byte signature of the types. With just that, a reader
wouldn't be able to easily locate a .dwo that contain the type with a
given signature.
To help with this, index entries for foreign type units may also include
a reference to a compilation unit that can be followed in order to find
a .dwo file containing the type. This patch implements it.
Implementation details
----------------------
The first change is the addition of the dwo_unit::per_cu field, which
allows going from the dwo_unit to the dwarf2_per_cu structure (which
describes the skeleton) that was used to lookup this dwo_unit. This
fields starts at nullptr, and it gets set in lookup_dwo_cutu whenever we
look up the dwo_unit for a given dwarf2_per_cu. This will come handy
later. I made this field an std::atomic, because I think it would be
possible to craft a weird test case that would make two indexer threads
try to set the field on the same dwo_unit. During normal operation, we
expect the field for each dwo_unit representing a CU to be written
exactly once.
In index-write.c, change the get_unit_lists function in
dwarf2/index-write.c to segregate local and foreign type units. Then,
update write_debug_names to emit the list of foreign TUs in the
.debug_names header. This consists of a list of type signatures.
In debug_names::build, for foreign type units, emit a
DW_IDX_compile_unit field. This is the reference to the CU that can be
used to locate the .dwo file containing that type unit. To obtain the
value for this field, look up a CU in the same dwo_file that has its
dwo_unit::per_cu field set (typically there will be exactly one CU, and
the field will be set).
With this patch, the index for the test case above looks like:
We can see that the TU is correctly placed in the foreign TU list, and
that the index entry (the last line) points to the TU at index 0, but
also to the CU at index 1, which is indeed the CU that the reader can
follow to find the type unit.
With this patch, GDB still rejects the index:
(gdb) file /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/fission-with-type-unit
Reading symbols from /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/fission-with-type-unit...
warning: Section .debug_names in /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/fission-with-type-unit has unsupported 1 foreign TUs, ignoring .debug_names.
But at least, we don't produce a bogus index anymore, that's already an
improvement. A following patch in this series implements the reading
side
Change-Id: I311fd7b4ca57d9ff6d64ae08df805c6635961eed Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 11 May 2026 15:40:29 +0000 (11:40 -0400)]
gdb/dwarf: add dwo_file::find_tus
Add this little helper to make finding a TU a bit simpler. I always
find the STL way of doing things cryptic, so I think that hiding it in
small helper methods makes the code clearer.
A subsequent patch will add more uses of it
Change-Id: Ibfb20d0e44c65d2ff729f3e0980ec4435f223aef Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 11 May 2026 15:40:28 +0000 (11:40 -0400)]
gdb/dwarf: move dwarf2_cu::section to cu.c
Following the previous patch that moves the dwo_unit structure from
dwarf2/read.c to dwarf2/dwo.h, dwarf2_cu::section has no reason to be
implemented in dwarf2/read.c anymore. Move it to dwarf2/cu.c.
Change-Id: I67e2bb42d878ac18e4bf3460d75f1394477a46ce Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 11 May 2026 15:40:27 +0000 (11:40 -0400)]
gdb/dwarf: move dwo_unit and dwo_file to dwo.h
Move these types and some related things to a new dwo.h header file. My
goal is to allow index-write.c to see these types, in a later patch. I
initially moved them to read.h, but Tom suggested in review that read.h
was getting a bit too large.
Change-Id: Ia32e0643f95561d3a1bfb67d501c8e20f5682f0e Approved-By: Tom Tromey <tom@tromey.com>
Pedro Alves [Mon, 23 Mar 2026 21:54:12 +0000 (21:54 +0000)]
gcore: handle known-all-zeroes hole mappings
This commit improves core generation on Linux. The issue this
addresses became apparent when dumping core of HIP programs on AMD
GPUs, but it's strictly a CPU-side issue.
The AMD GPU runtime used by HIP (and other languages) programs creates
these big mappings in every program, the size of GPU VRAM. E.g., on
gfx942 with 256GB VRAM, we end up with 256GB of such mappings:
GDB's gcore, not knowing the mappings contain only zeroes, reads all
their contents from inferior memory, all 256GB of it. On gfx942, that
makes the gcore command take around 1 minute when dumping a small HIP
program.
GDB's gcore currently generates load segments of these mappings like
this:
The fact that GDB makes CONTENTS/LOAD segments makes it so that the
resulting core files are much larger than what the Linux kernel
produces (note "File off" column), even though it's mostly apparent
size as gdb knows how to produce sparse cores:
$ ls -als --hu core/*
440M -rw------- 1 pedalves pedalves 474M Mar 24 08:14 core/kernel.core
51M -rw-rw-r-- 1 pedalves pedalves 257G Mar 24 08:16 core/gdb-before.core
^^^^ real ^^^^ apparent
This commit teaches linux-tdep.c to identify anonymous mappings that
have no backing data from /proc/pid/smaps (which we already parse), so
that the gcore code can skip reading inferior memory for them, and
their load segments can be emitted with no CONTENTS/LOAD.
The skip-reading-inferior-memory part speeds up core dumping of small
HIP inferiors on gfx942 GPUs by a large factor. E.g.:
With:
$ time rocgdb --batch -q small-test-program \
-ex "with breakpoint pending on -- b gpu_code" \
-ex "r" \
-ex "gcore" \
-ex "k"
On gfx942, before the patch:
real 1m6.518s
user 0m5.984s
sys 1m0.218s
On gfx942, after the patch:
real 0m4.456s
user 0m2.219s
sys 0m1.829s
And the fact that we no longer emit segments with CONTENTS/LOAD makes
the resulting gdb-generated cores's apparent size be much smaller,
closer to kernel-generated core file's:
$ ls -als --hu core/*
440M -rw------- 1 pedalves pedalves 474M Mar 24 08:14 core/kernel.core
51M -rw-rw-r-- 1 pedalves pedalves 257G Mar 24 08:16 core/gdb-before.core
52M -rw-rw-r-- 1 pedalves pedalves 642M Mar 24 09:12 core/gdb-after.core
This commit also adds a new testcase that exercises both the scenario
in question (without relying on the HIP runtime), and the converse of
making sure that we don't skip dumping anonymous private PROT_NONE
mappings with backing data, by mistake.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Change-Id: I2cf21409af36266094bcff5614770605fab4030e
commit-id: d3d471d8
Tom de Vries [Mon, 11 May 2026 09:50:13 +0000 (11:50 +0200)]
[gdb/testsuite] Fix gdb.dap/corefile.exp with Tcl 9.0
With test-case gdb.dap/corefile.exp and Tcl 9.0 I run into:
...
ERROR: tcl error sourcing gdb/testsuite/gdb.dap/corefile.exp.
ERROR: tcl error code TCL LOOKUP VARNAME reg_name
ERROR: can't read "reg_name": no such variable
while executing
"s \$$reg_name"
(in namespace eval "::ton::2json" script line 1)
invoked from within
"namespace eval ton::2json $obj"
...
Fix this by making clear that reg_name is a variable in the global namespace.
The comment of store_integer seems slightly outdated and does not refer to
the variants that take an array view. Update the comment and add comments
to the various instantiations.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
The Debian maintainer of babeltrace (Michael, in CC) is working
towards removing the version 1 package from the archive in favour of
version 2. This makes sense as version 1 is unsupported and projects
should move to version 2.
While digging through the archives I found PR buid/27142 (from
Matthias, also in Cc) which was filed 5 years ago requesting GDB to
support babeltrace v2. At the time Simon started a thread on gdb@
suggesting that we should actually remove the support for CTF (Common
Trace Format) altogether, since it's a niche feature (CTF) within a
niche feature (tracepoints) and apparently GDB itself records CTF data
in an unconventional way that might break other tools. You can see
the thread here:
Long story short, the consensus seems to be that CTF support is ripe
to be removed, so that's what this patch does. I think I covered all
places that referred to either CTF or babeltrace; I recompiled GDB
here and things are still working as expected. I ran the tests I
touched and there are some failures, but they're unrelated to CTF and
I could reproduce them in a pristine tree as well.
I've been a bit distant from the community so I don't know whether we
have a specific procedure to remove features from GDB. I remember
that when we removed support for an architecture, we used to deprecate
it in release N and then proceed with the removal on release N+1. Not
sure if this is applicable here, but let me know.
Either way, I intend to disable support for babeltrace on Debian's GDB
soon.
WDYT?
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27142 Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Simon Marchi <simon.marchi@efficios.com>
so update `is_elf_format' accordingly, complementing commit d85e70a35bff
("Add support for the haiku operating system.") and fixing regressions:
aarch64-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
aarch64-haiku -FAIL: GNU attributes v2: no support for directive .gnu_subsection
arm-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
m68k-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
mipsel-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
powerpc-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
sparc64-haiku -FAIL: GNU attributes v1/v2: no support for directive .gnu_attribute
sparc64-haiku -FAIL: sparc relax CALL (a.out)
while widely broadening coverage, e.g. with `i486-haiku' we now get:
=== binutils Summary ===
# of expected passes 230
# of untested testcases 18
# of unsupported tests 21
=== gas Summary ===
# of expected passes 1066
# of unsupported tests 16
=== ld Summary ===
# of expected passes 595
# of expected failures 2
# of untested testcases 26
# of unsupported tests 215
vs:
=== binutils Summary ===
# of expected passes 77
# of untested testcases 13
# of unsupported tests 11
=== gas Summary ===
# of expected passes 806
# of unsupported tests 4
=== ld Summary ===
# of expected passes 188
# of expected failures 2
# of untested testcases 16
# of unsupported tests 62
The following regressions yet need to be addressed:
i386/Haiku/GAS/testsuite: Suppress SVR4 comment character test
Exclude the SVR4 comment character test on Haiku targets, as `/' is not
a comment character there (cf. gas/config/te-haiku.h), so as to prevent
a regression caused by enabling ELF tests with Haiku targets:
Aarch64/Haiku/binutils/testsuite: Suppress PEI test
There is no PEI BFD target included by default with the Haiku target
configuration, so exclude the EFI test, preventing a regression caused
by enabling ELF tests with Haiku targets:
aarch64-haiku +FAIL: Check if efi app format is recognized
Simon Marchi [Mon, 10 Nov 2025 21:19:40 +0000 (16:19 -0500)]
gdb: refuse to produce .gdb_index when skeletonless type units are present
Running test gdb.dwarf2/fission-with-type-unit.exp with the
cc-with-gdb-index target board fails with:
(gdb) maint expand-symtabs
/home/simark/src/binutils-gdb/gdb/dwarf2/read.c:3064: internal-error: cutu_reader: Assertion `sig_type->signature == cu->header.signature' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
FAIL: gdb.dwarf2/fission-with-type-unit.exp: maint expand-symtabs (GDB internal error)
This is a consequence of .gdb_index not supporting skeletonless type
units in .dwo files. That is, type units in .dwo files that don't have
a corresponding skeleton (or stub) in the main file.
For context: in DWARF 4, gcc 4.x used to create skeletons for type units
in .dwo files, but subsequent versions don't. DWARF 5 doesn't have
support for type unit skeletons at all. So skeletons for type units are
mostly a historical curiosity at this point, the norm is to not have
them.
Here's what leads up to the crash. First, this is what is in the main
file's .debug_info section (the first and last CUs are dummy CUs added
by the testsuite):
After loading the above in GDB, here is what is in GDB's mind (contents
of dwarf2_per_bfd::all_units):
- CU at offset 0x0 of .debug_info in fission-with-type-unit -- dummy
- CU at offset 0xc of .debug_info in fission-with-type-unit
- CU at offset 0x25 of .debug_info in fission-with-type-unit -- dummy
- TU at offset 0x0 of .debug_info.dwo in fission-with-type-unit-dw.dwo
This is correct. Then, this is the generated .gdb_index:
Shortcut table:
Language of main: unknown: 0
Name of main: <unknown>
The TU table says that there exists a TU at offset 0. Unfortunately,
there is no way for a reader of that index to know that this TU is
really in a .dwo file, not in the main file. So when GDB loads this
index back (creating dwarf2_per_bfd::all_units from .gdb_index this
time, rather than walking the debug info), this is what is in its mind:
- CU at offset 0x0 of .debug_info in fission-with-type-unit -- dummy
- TU at offset 0x0 of .debug_info in fission-with-type-unit
- CU at offset 0xc of .debug_info in fission-with-type-unit
- CU at offset 0x25 of .debug_info in fission-with-type-unit -- dummy
GDB now incorrectly believes there's a TU at offset 0 of .debug_info in
the main file, which is wrong. When trying to expand that TU with
"maint expand-symtabs", we're not really reading the TU, so we hit the
assert checking that the signature in the TU header matches what was
given by the index.
The .debug_names format has a way to list the TUs found in the .dwo
files, called the "foreign TU list" (see section 6.1.1.2 "Structure of
the Name Index" of DWARF 5). That list only includes the signature of
the type, and there is some capability to figure out which .dwo file
contains that type unit. The .gdb_index format does not have something
like that. We could try to retrofit such a feature in the .gdb_index
format, but I think we prefer to put our efforts on the standard
.debug_names format.
To avoid producing a misleading index like shown above, I propose to
make GDB refuse to produce an index if there exists a skeletonless type
unit. This patch implements that by looking at section of all
signatured_types. If the containing section ends with .dwo, then this
is a skeletonless type unit.
As a reminder: if a unit has a skeleton, the dwarf2_per_cu section will
point at the skeleton section, in the main file. If the unit does not
have a skeleton, the dwarf2_per_cu section will point at the section in
the .dwo file. All .dwo section names end with ".dwo".
Add a "endswith" utils function to help with that.
With this patch, running the gdb.dwarf/fission-with-type-unit.exp leads
to a compilation failure:
gdb compile failed, Error while writing index for `/home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/.tmp/fission-with-type-unit': Found skeletonless type units, unable to produce .gdb_index. Consider using .debug_names instead.
... which makes the test "untested".
Add a new test, gdb.dwarf2/gdb-index-skeletonless-tu.exp, to verify the new error path.
Change-Id: I1e2e0204c9c2b48763aa99ce63521ae4a5262b22 Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
GDB: testsuite: threads: Don't return value from top-level (manual)
This patch manually changes "return -1" statements that weren't caught
by the sed command.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as for loops,
with_test_prefix, foreach_with_prefix, gdb_test_multiple.
I also fixed a couple cases of "return 0" from top-level that also
weren't caught by sed, and even a couple cases of "return 1" from
top-level.
GDB: testsuite: threads: Don't return 0 from top-level (sed)
This patch is a bit different than the others. I noticed that
gdb.threads has many cases of "return 0" from the top level, so this
patch is purely the result of running:
$ sed -i 's/^ return 0/ return/' *.exp*
inside gdb/testsuite/gdb.threads.
There were a number of false positives so not all sed changes were
incorporated.
GDB: testsuite: reverse: Don't return value from top-level (manual)
This patch manually changes "return -1" statements that weren't caught
by the sed command. It also changes a few "return 0" statements.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as with_test_prefix,
foreach_with_prefix, with_timeout_factor, gdb_test_multiple.
GDB: testsuite: MI: Don't return value from top-level (manual)
This patch manually changes "return -1" statements that weren't caught
by the sed command. It also changes a couple of "return 0" statements.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as with_test_prefix,
foreach_with_prefix, gdb_expect.
GDB: testsuite: Python: Don't return value from top-level (manual)
This patch manually changes "return -1" and "return 0" statements that
weren't caught by the sed command.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as save_vars,
with_test_prefix, foreach, gdb_test_multiple.
In a couple of cases the whole if block was in a single line:
if { condition } { return -1 }
In those cases the formatting was changed to the multi-line style we
tend to use.
GDB: testsuite: DWARF: Don't return -1 from top-level (manual)
This patch manually changes "return -1" statements that weren't caught
by the sed command.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as save_vars,
with_test_prefix, foreach, gdb_test_multiple.
Some weren't changed because they didn't meet the criteria above, or
weren't trivial to check.
GDB: testsuite: C++: Don't return value from top-level (manual)
This patch manually changes "return -1" and "return 0" statements that
weren't caught by the sed command.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside block such as save_vars,
with_test_prefix, foreach, gdb_test_multiple.
Some weren't changed because they didn't meet the criteria above, or
weren't trivial to check.
GDB: testsuite: base: Don't return value from top-level (manual)
This patch manually changes "return -1" and "return 0" statements that
weren't caught by the sed command.
These return statements fall into one of these criteria:
- misaligned line, which is then fixed by this patch;
- return at top level but inside a block such as save_vars,
with_test_prefix, foreach, gdb_test_multiple.
Some weren't changed because they didn't meet the criteria above, or
weren't trivial to check.
There was also one return statement with an unnecessary semi-colon at
the end, which was removed.