gdb, linespec: avoid multiple locations with same PC
broke GDB's ability to list multiple source files using a 'list'
command. In GDB 16 and earlier something like 'list foo.c:10' could
print multiple results if there were multiple 'foo.c' files compiled
into the executable.
The above commit added a filter to add_sal_to_sals (linespec.c) such
that multiple sals in the same program space, but with the same pc
value, could not be added, only the first sal would actually be
recorded. The problem with this is that add_sal_to_sals is used from
decode_digits_list_mode (also linespec.c) where the pc value is forced
to zero. This force to zero makes sense I think as there might not be
any compiled code for the requested line (this is for 'list' after
all), so there might not be a valid pc to use.
I'm not a fan of using '0' as a special pc value, there are embedded
targets where 0 is a valid pc value, but given we're already using 0
here, I propose to just roll with it.
So, my proposal is that, if the pc is 0, add_sal_to_sals should always
add the sal. This fixes the decode_digits_list_mode, but should keep
the fix that c7a45b98a614 introduced.
Simon Marchi [Mon, 1 Dec 2025 19:56:54 +0000 (14:56 -0500)]
gdb/dwarf: clarify meaning dwarf2_per_cu::{m_section,m_sect_off,m_length} in presence of DWO file
The comments above these fields are almost accurate. If a unit in a DWO
file has a corresponding skeleton in the main file, these fields
describe the skeleton in the main file. However, it's missing the
detail that if the unit in the DWO file does not have a corresponding
skeleton in the main file, then the fields describe the unit in the DWO
file. Update the comments to reflect that.
Change-Id: I0681bc0d884f7e373b227416cbdef307d462ae71 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 1 Dec 2025 19:56:52 +0000 (14:56 -0500)]
gdb/dwarf: store addr/offset/ref_addr sizes in dwarf2_per_cu
In some specific circumstances, it is possible for GDB to read a type
unit from a .dwo file without ever reading in the section of the stub in
the main file. In that case, calling any of these methods:
will cause a crash, because they will try to read the unit header from
the not-read-in section buffer. See the previous patch for more
details.
The remaining calls to these methods are in the loc.c and expr.c
files. That is, in the location and expression machinery. It is
possible to set things up to cause them to trigger a crash, as shown by
the new test, when running it with the cc-with-gdb-index board:
$ make check TESTS="gdb.dwarf2/fission-type-unit-locexpr.exp" RUNTESTFLAGS="--target_board=cc-with-gdb-index"
Running /home/simark/src/binutils-gdb/gdb/testsuite/gdb.dwarf2/fission-type-unit-locexpr.exp ...
ERROR: GDB process no longer exists
The backtrace at the moment of the crash is:
#0 0x0000555566968b1f in bfd_getl32 (p=0x78) at /home/simark/src/binutils-gdb/bfd/libbfd.c:846
#1 0x00005555642e51b7 in read_initial_length (abfd=0x7d1ff1eb0e40, buf=0x78 <error: Cannot access memory at address 0x78>, bytes_read=0x7bfff09daca0, handle_nonstd=true)
at /home/simark/src/binutils-gdb/gdb/dwarf2/leb.c:92
#2 0x00005555647ca584 in read_unit_head (header=0x7d0ff1e06c70, info_ptr=0x78 <error: Cannot access memory at address 0x78>, section=0x7c3ff1dea7d0, section_kind=ruh_kind::COMPILE)
at /home/simark/src/binutils-gdb/gdb/dwarf2/unit-head.c:44
#3 0x000055556452df18 in dwarf2_per_cu::get_header (this=0x7d0ff1e06c40) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18531
#4 0x000055556452e10e in dwarf2_per_cu::addr_size (this=0x7d0ff1e06c40) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18544
#5 0x0000555564314ac3 in dwarf2_locexpr_baton_eval (dlbaton=0x7bfff0c9a508, frame=..., addr_stack=0x7bfff0b59150, valp=0x7bfff0c9a430, push_values=..., is_reference=0x7bfff0d33030)
at /home/simark/src/binutils-gdb/gdb/dwarf2/loc.c:1593
#6 0x0000555564315bd2 in dwarf2_evaluate_property (prop=0x7bfff0c9a450, initial_frame=..., addr_stack=0x7bfff0b59150, value=0x7bfff0c9a430, push_values=...) at /home/simark/src/binutils-gdb/gdb/dwarf2/loc.c:1668
#7 0x0000555564a14ee1 in resolve_dynamic_field (field=..., addr_stack=0x7bfff0b59150, frame=...) at /home/simark/src/binutils-gdb/gdb/gdbtypes.c:2758
#8 0x0000555564a15e24 in resolve_dynamic_struct (type=0x7e0ff1f02550, addr_stack=0x7bfff0b59150, frame=...) at /home/simark/src/binutils-gdb/gdb/gdbtypes.c:2839
#9 0x0000555564a17061 in resolve_dynamic_type_internal (type=0x7e0ff1f02550, addr_stack=0x7bfff0b59150, frame=..., top_level=true) at /home/simark/src/binutils-gdb/gdb/gdbtypes.c:2972
#10 0x0000555564a17899 in resolve_dynamic_type (type=0x7e0ff1f02550, valaddr=..., addr=0x4010, in_frame=0x7bfff0d32e60) at /home/simark/src/binutils-gdb/gdb/gdbtypes.c:3019
#11 0x000055556675fb34 in value_from_contents_and_address (type=0x7e0ff1f02550, valaddr=0x0, address=0x4010, frame=...) at /home/simark/src/binutils-gdb/gdb/value.c:3674
#12 0x00005555666ce911 in get_value_at (type=0x7e0ff1f02550, addr=0x4010, frame=..., lazy=1) at /home/simark/src/binutils-gdb/gdb/valops.c:992
#13 0x00005555666ceb89 in value_at_lazy (type=0x7e0ff1f02550, addr=0x4010, frame=...) at /home/simark/src/binutils-gdb/gdb/valops.c:1039
#14 0x000055556491909f in language_defn::read_var_value (this=0x5555725fce40 <minimal_language_defn>, var=0x7e0ff1f02500, var_block=0x7e0ff1f025d0, frame_param=...)
at /home/simark/src/binutils-gdb/gdb/findvar.c:504
#15 0x000055556491961b in read_var_value (var=0x7e0ff1f02500, var_block=0x7e0ff1f025d0, frame=...) at /home/simark/src/binutils-gdb/gdb/findvar.c:518
#16 0x00005555666d1861 in value_of_variable (var=0x7e0ff1f02500, b=0x7e0ff1f025d0) at /home/simark/src/binutils-gdb/gdb/valops.c:1384
#17 0x00005555647f7099 in evaluate_var_value (noside=EVAL_NORMAL, blk=0x7e0ff1f025d0, var=0x7e0ff1f02500) at /home/simark/src/binutils-gdb/gdb/eval.c:533
#18 0x00005555647f740c in expr::var_value_operation::evaluate (this=0x7c2ff1e3b690, expect_type=0x0, exp=0x7c2ff1e3aa00, noside=EVAL_NORMAL) at /home/simark/src/binutils-gdb/gdb/eval.c:559
#19 0x00005555647f3347 in expression::evaluate (this=0x7c2ff1e3aa00, expect_type=0x0, noside=EVAL_NORMAL) at /home/simark/src/binutils-gdb/gdb/eval.c:109
#20 0x000055556543ac2f in process_print_command_args (args=0x7fffffffe728 "global_var", print_opts=0x7bfff0be4a30, voidprint=true) at /home/simark/src/binutils-gdb/gdb/printcmd.c:1328
#21 0x000055556543ae65 in print_command_1 (args=0x7fffffffe728 "global_var", voidprint=1) at /home/simark/src/binutils-gdb/gdb/printcmd.c:1341
#22 0x000055556543b707 in print_command (exp=0x7fffffffe728 "global_var", from_tty=1) at /home/simark/src/binutils-gdb/gdb/printcmd.c:1408
The problem to solve is: in order to evaluate a location expression, we
need to know some information (the various sizes) found in the unit
header. In that context, it's not possible to get it from
dwarf2_cu::header, like the previous patch did: at the time the
expression is evaluated, the corresponding dwarf2_cu might have been
freed. We don't want to re-build a dwarf2_cu just for that, it would be
very inefficient. We could force reading in the dwarf2_per_cu::section
section (in the main file), but we never needed to read that section
before, so it would be better to avoid reading it unnecessarily.
My initial attempt was to store this information in baton objects
(dwarf2_locexpr_baton & co), so that it can be retrieved when the time
comes to evaluate the expressions. However, it quickly became obvious
that storing it there would be redundant and wasteful.
I instead opted to store this information directly inside dwarf2_per_cu,
making it easily available when evaluating expressions. These fields
initially have the value 0, and are set by cutu_reader whenever the
unit is parsed. The various getters (dwarf2_per_cu::addr_size & al) now
just return these fields.
Doing so allows removing anything related to reading the header from
dwarf2_per_cu, which I think is a nice simplification. This means that
nothing ever needs to read the header from just a dwarf2_per_cu.
It also happens to shrink the dwarf2_per_cu object size a bit, going
from:
(top-gdb) p sizeof(dwarf2_per_cu)
$1 = 176
to
(top-gdb) p sizeof(dwarf2_per_cu)
$1 = 120
I placed the new fields at this strange location in dwarf2_per_cu
because there happened to be a nice 3 bytes hole there (on Linux amd64
at least).
The new test set things up as described previously. Note that the crash
only occurs if using the cc-with-gdb-index board.
Change-Id: I50807a1bbb605f0f92606a9e61c026e3376a4fcf Approved-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 1 Dec 2025 19:56:51 +0000 (14:56 -0500)]
gdb/dwarf: when in dwarf2_cu, read addr_size from dwarf2_cu::header
This patch fixes a crash caused by GDB trying to read from a section not
read in. The bug happens in those specific circumstances:
- reading a type unit from .dwo
- that type unit has a stub in the main file
- there is a GDB index (.gdb_index) present
This crash is the cause of the following test failure, with the
cc-with-gdb-index target board:
$ make check TESTS="gdb.dwarf2/fission-reread.exp" RUNTESTFLAGS="--target_board=cc-with-gdb-index"
Running /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.dwarf2/fission-reread.exp ...
ERROR: GDB process no longer exists
For this last one, you need to interrupt the test (e.g. add a return)
before the test deletes the .dwo file.
The backtrace at the moment of the crash is:
#0 0x0000555566968f7f in bfd_getl32 (p=0x0) at /home/simark/src/binutils-gdb/bfd/libbfd.c:846
#1 0x00005555642e561d in read_initial_length (abfd=0x7d1ff1eb0e40, buf=0x0, bytes_read=0x7bfff0962fa0, handle_nonstd=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/leb.c:92
#2 0x00005555647ca9ea in read_unit_head (header=0x7d0ff1e068b0, info_ptr=0x0, section=0x7c3ff1dea7d0, section_kind=ruh_kind::COMPILE) at /home/simark/src/binutils-gdb/gdb/dwarf2/unit-head.c:44
#3 0x000055556452e37e in dwarf2_per_cu::get_header (this=0x7d0ff1e06880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18531
#4 0x000055556452e574 in dwarf2_per_cu::addr_size (this=0x7d0ff1e06880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18544
#5 0x000055556406af91 in dwarf2_cu::addr_type (this=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/cu.c:124
#6 0x0000555564534e48 in set_die_type (die=0x7e0ff1f23dd0, type=0x7e0ff1f027f0, cu=0x7d7ff1e20880, skip_data_location=false) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:19020
#7 0x00005555644dcc7b in read_structure_type (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:11239
#8 0x000055556451c834 in read_type_die_1 (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16878
#9 0x000055556451c5e0 in read_type_die (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16861
#10 0x0000555564526f3a in get_signatured_type (die=0x7e0ff1f0ffb0, signature=10386129560629316377, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:17998
#11 0x000055556451c23b in lookup_die_type (die=0x7e0ff1f0ffb0, attr=0x7e0ff1f10008, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16808
#12 0x000055556451b2e9 in die_type (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16684
#13 0x000055556451457f in new_symbol (die=0x7e0ff1f0ffb0, type=0x0, cu=0x7d7ff1e0f480, space=0x0) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16089
#14 0x00005555644c52a4 in read_variable (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:9119
#15 0x0000555564494072 in process_die (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:5197
#16 0x000055556449c88e in read_file_scope (die=0x7e0ff1f0fdd0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:6125
#17 0x0000555564493671 in process_die (die=0x7e0ff1f0fdd0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:5098
#18 0x00005555644912f5 in process_full_comp_unit (cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:4851
#19 0x0000555564485e18 in process_queue (per_objfile=0x7d6ff1e71100) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:4161
#20 0x000055556446391d in dw2_do_instantiate_symtab (per_cu=0x7ceff1de42d0, per_objfile=0x7d6ff1e71100, skip_partial=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1650
#21 0x0000555564463b3c in dw2_instantiate_symtab (per_cu=0x7ceff1de42d0, per_objfile=0x7d6ff1e71100, skip_partial=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1671
#22 0x00005555644687fd in dwarf2_base_index_functions::expand_all_symtabs (this=0x7c1ff1e04990, objfile=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1990
#23 0x0000555564381050 in cooked_index_functions::expand_all_symtabs (this=0x7c1ff1e04990, objfile=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/dwarf2/cooked-index.h:237
#24 0x0000555565df5b0d in objfile::expand_all_symtabs (this=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/symfile-debug.c:372
#25 0x0000555565eafc4a in maintenance_expand_symtabs (args=0x0, from_tty=1) at /home/simark/src/binutils-gdb/gdb/symmisc.c:914
The main file contains a stub (skeleton) for a compilation unit and a
stub for a type unit. The .dwo file contains a compilation unit and a
type unit matching those stubs. When doing the initial scan of the main
file, the DWARF reader parses the CU/TU list from the GDB index
(.gdb_index), and thus creates a signatured_type object based on that.
The section field of this signatured_type points to the .debug_types
section in the main file, the one containing the stub. And because GDB
trusts the GDB index, it never needs to look at that .debug_types
section in the main file. That section remains not read in.
When expanding the compilation unit, GDB encounters a type unit
reference (by signature) corresponding to the type in the type unit. We
get in lookup_dwo_signatured_type, trying to see if there is a type unit
matching that signature in the current .dwo file. We proceed to read
and expand that type unit, until we eventually get to a
dwarf2_cu::addr_type() call, which does:
int addr_size = this->per_cu->addr_size ();
dwarf2_per_cu::addr_size() tries to read the header from the section
pointed to by dwarf2_per_cu::section which, if you recall, is the
.debug_types section in the main file that was never read in. That
causes the segfault.
All this was working fine before these patches of mine, that tried to do
some cleanups:
a47e2297fc28 ("gdb/dwarf: pass section offset to dwarf2_per_cu_data constructor") c44ab627b021 ("gdb/dwarf: pass section to dwarf2_per_cu_data constructor") 39ee8c928551 ("gdb/dwarf: pass unit length to dwarf2_per_cu_data constructor")
Before these patches, the fill_in_sig_entry_from_dwo_entry function
(called from lookup_dwo_signatured_type, among others) would overwrite
some dwarf2_per_cu fields (including the section) to point to the .dwo,
rather than represent what's in the main file. Therefore, the header
would have been read from the unit in the .dwo file, and things would
have been fine.
When doing these changes, I mistakenly assumed that the section written
by fill_in_sig_entry_from_dwo_entry was the same as the section already
there, which is why I removed the statements overwriting the section
field (and the two others). To my defense, here's the comment on
dwarf2_per_cu::section:
/* The section this CU/TU lives in.
If the DIE refers to a DWO file, this is always the original die,
not the DWO file. */
struct dwarf2_section_info *section = nullptr;
I would prefer to not reintroduce the behavior of overwriting the
section info in dwarf2_per_cu, because:
1. I find it confusing, I like the invariant of dwarf2_per_cu::section
points to the stub, and dwarf2_cu::section points to where we
actually read the debug info from.
2. The dwarf2_per_bfd::all_units vector is nowadays sorted by (section,
section offset). If we change the section and section offset of a
dwarf2_per_cu, then we can no longer do binary searches in it, we
would have to re-sort the vector (not a big deal, but still adds to
the confusion).
One possible fix would be to make sure that the section is read in when
reading the header, probably in dwarf2_per_cu::get_header. An approach
like that was proposed by Andrew initially, here:
It would work, but there is a more straightforward fix for this
particular problem, I believe. In dwarf2_cu, we have access to the
header read from the unit we're actually reading the DWARF from. In the
DWO case, that is the header read from the .dwo file. We can get the
address size from there instead of going through the dwarf2_per_cu
object. This is what this patch does.
However, there are other case where we get the address (or offset) size
from the dwarf2_per_cu in the DWARF expression evaluator (expr.c,
loc.c), that could cause a similar crash. The next patch handles these
cases.
Modify the gdb.dwarf2/fission-reread.exp test so that it tries running
with an index even with the standard board (that part was originally
written by Andrew).
Finally, just to put things in context, having a stub in the main file
for a type unit is obsolete. It happened in the gcc 4.x days, until
this commit:
Simon Marchi [Mon, 1 Dec 2025 19:56:50 +0000 (14:56 -0500)]
gdb/testsuite/dwarf: emit type unit sections as COMDAT
In an effort to generate ELF files and DWARF info as close as possible
as an actual compiler would generate, change how we emit type unit
sections to emit each type unit in its own section, in COMDAT section
groups.
We currently emit all type units in a single, standard section (either
.debug_info or .debug_types, depending on the DWARF version). Compilers
emit each type unit in its own .debug_types section. Each section is
placed in a COMDAT section group with a signature based on the type
unit's signature. This lets the linker deduplicate identical type units
by discarding section groups with identical signatures (keeping only one
group with a given signature).
Looking at a .s file generated by gcc, we can see that this is how it
specifies the section for a type unit:
The "G" flag tells the assembler to place the section in a section
group with signature "wi.006fd2152a3054a6". That string was generated
from the type unit, signature. Finally, the comdat linkage field
indicates that the section group should have the COMDAT flag.
Update the tu proc to emit a section with these properties. In this
case, it's mandatory to specify the type of the section (progbits).
Update the _section proc to accept the new options "group_signature" and
"linkage".
As a result, if you look at the .debug_types section in a .o file from
gcc:
COMDAT group section [ 2] `.group' [sig.0x0000000000000002] contains 2 sections:
[Index] Name
[ 12] .debug_types
[ 13] .rela.debug_types
In both cases, in the fully linked files, there is a single .debug_types section
containing the two type units, as expected.
Before this patch, when I run gdb.dwarf2/fission-with-type-unit.exp, the
resulting .dwo file has a single .debug_info.dwo. After this patch it
has two: one with the type unit and one with the compile unit (the test
uses DWARF 5). Based on what I see gcc generate when using "-gdwarf-5
-gsplit-dwarf -fdebug-types-section", this is what we expect.
Change-Id: Ie1954dc697fe100b5dbe664d148c71fa02888d96 Approved-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 1 Dec 2025 19:56:48 +0000 (14:56 -0500)]
gdb/testsuite/dwarf: use single abbrev table in .dwo files
When I wrote test gdb.dwarf2/fission-with-type-unit.exp, I did not use
build_executable_and_dwo_files, because it wouldn't work to have
multiple units in the .dwo file, each referring to their own abbrev
table using labels. build_executable_and_dwo_files extracts the .dwo
file content from the .o using objcopy (just like gcc does, I learned),
meaning that the .dwo file never runs through a linker. Anything
needing relocation (like labels pointing to abbrev tables) doesn't work.
I instead opted to use gdb_compile_shlib to build the .dwo file on its
own, so that those labels would get resolved. That causes problems now
that I'm trying to write a test with multiple type units in a .dwo file,
where each type unit should be in its own .debug_types section. Running
the .dwo file through the linker causes all the .debug_types section to
be collapsed into one. And generally, I think it was a bad idea to
generate a .dwo file using the linker, since the idea behind .dwo files
is that they do not need to be linked (therefore improving link
times). We want to produce files as close to what an actual compiler
would produce.
This patch fixes this by doing what compilers do in the same situation:
use a single abbrev table shared by all units in the .dwo file. This
requires the following changes in lib/dwarf.exp:
- Declare a new variable _dwo_abbrev_num, which holds the next
abbrev number to use in the .dwo file's abbrev section
(.debug_abbrev.dwo). Initialize this variable to 1.
- When producing a CU or TU in a .dwo file, use 0 as the abbrev table
offset.
- When generating a DIE, return $_dwo_abbrev_num or $_abbrev_num,
depending on whether the current CU is in a .dwo file.
- After producing a CU or TU in a .dwo file, don't append the
terminator byte.
- After finishing producing the CUs and TUs, append the terminator byte
in .debug_abbrev.dwo if we did output anything there.
Update gdb.dwarf2/fission-with-type-unit.exp to use
build_executable_and_dwo_files, as it should. Remove the
gdb_remote_download call from gdb.dwarf/fission-with-type-unit.exp,
because build_executable_and_dwo_files does not support remote hosts
anyway.
With this change, running with the cc-with-gdb-index board, I see:
(gdb) maint expand-symtabs
/home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:3056: 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 actually an improvement, as the test case didn't run properly
before. The compilation failed with:
gdb compile failed, During symbol reading: Could not find DWO CU fission-with-type-unit.dwo(0xf00d) referenced by CU at offset 0xc [in module /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-with-type-unit/.tmp/fission-with-type-unit]
The reason was that the old code would try to generate the GDB index
during this step:
# Build main file.
if { [build_executable "${testfile}.exp" $binfile \
[list ${srcfile} ${main_asm_file}] {nodebug}] } {
return
}
... which is before the DWO file is even generated. With this patch
things are done in the correct order:
- The -dw.S file is generated
- The -dw.o file is compiled from the -dw.S
- The .dwo sections are extracted to the .dwo file, and stripped from
the -dw.o file
- The executable is linked from the .o and -dw.o
- gdb-add-index is ran on the executable
When gdb-add-index runs, the .dwo file exists, so GDB is able to produce
an index. That index is bogus though, because the .gdb_index format is
unable to describe skeletonless type units. And then GDB gets confused
trying to use that index, leading to the internal error.
Change-Id: Iabbcf00db97faf2a4fa5fc71652ad273081189f9 Approved-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 1 Dec 2025 19:56:47 +0000 (14:56 -0500)]
gdb/testsuite/dwarf: ensure build_executable_and_dwo_files calls untested in all failure paths
There are some paths of build_executable_and_dwo_files that return -1
without calling "untested". As a result, tests such as
gdb.dwarf2/fission-absolute-dwo.exp would exit without leaving a trace.
Add some untested calls to fix that.
Change-Id: I2e632b5b44b11b4beb39791316f1203f9a12bf4f Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 17 Nov 2025 05:03:48 +0000 (00:03 -0500)]
gdb: build solib-svr4-linux.o when building for targets xtensa*-*-*linux*
When building a GDB configured with --target=xtensa-buildroot-linux-uclibc, we get:
CXXLD gdb
/usr/bin/ld: xtensa-linux-tdep.o: in function `xtensa_linux_init_abi(gdbarch_info, gdbarch*)':
/home/simark/src/binutils-gdb/gdb/xtensa-linux-tdep.c:115:(.text+0x102): undefined reference to `make_linux_ilp32_svr4_solib_ops(program_space*)'
Fix it by adding solib-svr4-linux.o to the list of objects build for
targets xtensa*-*-*linux*.
Simon Marchi [Wed, 8 Oct 2025 19:01:34 +0000 (15:01 -0400)]
gdb: fix slowdown during skeletonless type units processing
My commit 6474c699a525 ("gdb/dwarf: sort dwarf2_per_bfd::all_units by
(section, offset)") introduced a pretty bad performance regression in
the "skeletonless type units" step. I have a pretty big executable
(Blender) compiled with -gsplit-dwarf (to generate .dwo files) and
-fdebug-types-section (to generate type units). Before the offending
commit:
Time for "DWARF skeletonless type units": wall 29.126, user 28.507, sys 0.497, user+sys 29.004, 99.6 % CPU
... and after:
Time for "DWARF skeletonless type units": wall 120.768, user 119.543, sys 0.651, user+sys 120.194, 99.5 % CPU
The reason for the slowdown is that add_type_unit now inserts type units
at the right place in the all_units vector to keep it sorted. These
repeated insertions in the middle of the vector require shifting a lot
of elements and end up taking a lot of time.
This patch fixes it by doing just one sort at the end of
process_skeletonless_type_units. The responsibility of keeping the
all_units sorted is delegated to the callers of add_type_unit. The
other two callers call finalize_all_units right after calling
add_type_unit.
One drawback that is probably not a real one: in
process_skeletonless_type_unit, we call process_type_unit. If something
in there needs to look up another type unit by (section, offset), it
wouldn't find it. I don't think that's a real issue though, as type
units are typically self contained. If a type unit needs to refer to a
type defined in another type unit, it would do so by signature, with
DW_FORM_ref_sig8. And during the indexing phase, I don't think we even
look at the DW_AT_type of things anyway.
With this patch applied, I am back to:
Time for "DWARF skeletonless type units": wall 29.277, user 28.632, sys 0.521, user+sys 29.153, 99.6 % CPU
I would like to cherry pick this patch to GDB 17, to avoid shipping GDB
17 with the performance regression.
Change-Id: I2a5b89ebca9e1a4e6248032e144520c9a579f47a
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33526 Approved-By: Tom Tromey <tom@tromey.com> Reviewed-By: Andrew Burgess <aburgess@redhat.com>
(cherry picked from commit 2c3d37c44b70a6e45a43045fcf07e8e739573c49)
Tom de Vries [Fri, 17 Oct 2025 08:48:06 +0000 (10:48 +0200)]
[gdb/tdep] Fix inferior call return of small char array for ppc64 v1 abi some more
PR tdep/33534 reports a regression due to commit 13f1820106c ("[gdb/tdep] Fix
inferior call return of small char array for ppc64 v1 abi").
The regression can be reproduced with the test-case introduced in the commit:
gdb.ada/return-small-char-array.exp, on a ppc64-linux setup with v1 elf abi
(cfarm121).
The commit contains two changes to a piece of code in
ppc64_sysv_abi_return_value:
...
/* Small character arrays are returned, right justified, in r3. */
- if (valtype->code () == TYPE_CODE_ARRAY
+ if (tdep->elf_abi == POWERPC_ELF_V1
+ && valtype->code () == TYPE_CODE_ARRAY
&& !valtype->is_vector ()
&& valtype->length () <= 8
- && valtype->target_type ()->code () == TYPE_CODE_INT
+ && (valtype->target_type ()->code () == TYPE_CODE_INT
+ || valtype->target_type ()->code () == TYPE_CODE_CHAR)
&& valtype->target_type ()->length () == 1)
...
The first change limits the effect of the if clause to the v1 elf abi. This
change doesn't affect the regression, since it's on a ppc64-linux setup with
v1 elf abi. Furthermore, it's correct in the sense that the v2 elf abi
doesn't have this kind of special treatment of small character arrays.
The second change is the part that causes the regression. The code itself
seems correct, in the sense that it enables gdb to recognize small char arrays
in ada.
The regression stems from the following discrepancy.
The comment in gdb states that "small character arrays are returned, right
justified, in r3". This matches the v1 ABI [1].
OTOH, gcc produces code that is not in agreement with this. Instead, it
passes the small character arrays in memory, in a caller-allocated storage
buffer pointed at by r3. This turns out to be an gcc bug [2].
Fix this by treating this as an abi spec bug, and replacing the code handling
the "Small character arrays" case with a comment.
Doing so reveals that there are two problems in the test-case:
- missing fvar-tracking, and
- the "step 2" command doesn't land at the intended line.
Fix these by:
- adding fvar-tracking, and
- setting a breakpoint at the intended line, and continuing to it.
Tested on ppc64-linux (v1 abi), ppc64le-linux (v2 abi), and x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33534
Tom de Vries [Thu, 16 Oct 2025 09:56:35 +0000 (11:56 +0200)]
[gdb/c++] Fix hang on whatis std::string::npos
Consider the following scenario, exercising "whatis std::string::npos":
...
$ cat test.cc
int main (void) {
std::string foo = "bar";
return foo.size ();
}
$ g++ test.cc -g
$ gdb -q -batch -iex "set trace-commands on" a.out -x gdb.in
+start
Temporary breakpoint 1 at 0x4021c7: file test.cc, line 3.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Temporary breakpoint 1, main () at test.cc:3
3 std::string foo = "bar";
+info auto-load python-scripts
No auto-load scripts.
+whatis std::string
type = std::__cxx11::basic_string<char, std::char_traits<char>, \
std::allocator<char> >
+whatis std::string::npos
type = const std::__cxx11::basic_string<char, std::char_traits<char>, \
std::allocator<char> >::size_type
...
After installing the package containing the pretty-printers:
...
$ zypper install libstdc++6-pp
...
and adding some commands to use them, we get instead:
...
$ gdb -q -batch -iex "set trace-commands on" a.out -x gdb.in
+add-auto-load-safe-path /usr/share/gdb/auto-load
+add-auto-load-scripts-directory /usr/share/gdb/auto-load
+start
...
+info auto-load python-scripts
Loaded Script
Yes /usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.34-gdb.py
+whatis std::string
type = std::string
+whatis std::string::npos
type = const std::__cxx11::basic_string<char, std::char_traits<char>, \
std::allocator<char> >::size_type
...
Note that "whatis std::string" now prints "std::string", but that
"whatis std::string::npos" still uses the longer name for std::string.
This is when compiling gdb with -O0. With -O2 -fstack-protector-strong, we
have a hang instead:
...
+whatis std::string
type = std::string
+whatis std::string::npos
<HANG>
...
Valgrind complains about an uninitialized field
demangle_component::d_counting, which is fixed by using
cplus_demangle_fill_name in replace_typedefs_qualified_name.
After fixing that, the hang is also reproducible at -O0.
The hang happens because we're stuck in the while loop in
replace_typedefs_qualified_name, replacing "std::string::size_type" with
"std::string::size_type".
Fix this in inspect_type by checking for this situation, getting us instead:
...
+whatis std::string
type = std::string
+whatis std::string::npos
type = const std::string::size_type
$
...
The test-case is a bit unusual:
- pretty-print.cc is a preprocessed c++ source, reduced using cvise [1], then
hand-edited to fix warnings with gcc and clang.
- the pretty-printer .py file is a reduced version of
/usr/share/gcc-15/python/libstdcxx/v6/printers.py.
Using the test-case (and the cplus_demangle_fill_name fix), I managed to
reproduce the hang on both:
- openSUSE Leap 15.6 with gcc 7, and
- openSUSE Tumbleweed with gcc 15.
The test-case compiles with clang, but the hang didn't reproduce.
Tom de Vries [Sat, 4 Oct 2025 00:16:43 +0000 (02:16 +0200)]
[gdb] Fix assertion failure due to null frame
PR gdb/33512 reports an assertion failure in test-case
gdb.ada/access_to_packed_array.exp on i386-linux:
...
(gdb) maint print symbols
gdb/frame.c:3400: internal-error: reinflate: \
Assertion `m_cached_level >= -1' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: $exp: \
maint print symbols (GDB internal error)
...
I haven't been able to reproduce the failure by running the test-case on
x86_64-linux with target board unix/-m32, but I'm able to reproduce on
x86_64-linux by using the exec attached to the PR:
...
$ cat gdb.in
file foo
maint expand-symtabs
maint print symbols
$ gdb -q -batch -ex "set trace-commands on" -x gdb.in
...
c_to: array (gdb/frame.c:3395: internal-error: reinflate: \
Assertion `m_cached_level >= -1' failed.
...
The backtrace at the point of the assertion failure is:
...
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>,
signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1 0x00007ffff62a8e7f in __pthread_kill_internal (signo=6,
threadid=<optimized out>) at pthread_kill.c:78
#2 0x00007ffff6257842 in __GI_raise (sig=sig@entry=6)
at ../sysdeps/posix/raise.c:26
#3 0x00007ffff623f5cf in __GI_abort () at abort.c:79
#4 0x00000000010e7ac6 in dump_core () at gdb/utils.c:223
#5 0x00000000010e81b8 in internal_vproblem(internal_problem *, const char *, int, const char *, typedef __va_list_tag __va_list_tag *) (
problem=0x2ceb0c0 <internal_error_problem>,
file=0x1ad5a90 "gdb/frame.c", line=3395,
fmt=0x1ad5a08 "%s: Assertion `%s' failed.", ap=0x7fffffffc3c0)
at gdb/utils.c:475
#6 0x00000000010e82ac in internal_verror (
file=0x1ad5a90 "gdb/frame.c", line=3395,
fmt=0x1ad5a08 "%s: Assertion `%s' failed.", ap=0x7fffffffc3c0)
at gdb/utils.c:501
#7 0x00000000019be79f in internal_error_loc (
file=0x1ad5a90 "gdb/frame.c", line=3395,
fmt=0x1ad5a08 "%s: Assertion `%s' failed.")
at gdbsupport/errors.cc:57
#8 0x00000000009b5c16 in frame_info_ptr::reinflate (this=0x7fffffffc878)
at gdb/frame.c:3395
#9 0x00000000009b66f9 in frame_info_ptr::operator-> (this=0x7fffffffc878)
at gdb/frame.h:290
#10 0x00000000009b4bd5 in get_frame_arch (this_frame=...)
at gdb/frame.c:3075
#11 0x000000000081dd89 in dwarf_expr_context::fetch_result (
this=0x7fffffffc810, type=0x410d600, subobj_type=0x410d600,
subobj_offset=0, as_lval=true)
at gdb/dwarf2/expr.c:1006
#12 0x000000000081e2ef in dwarf_expr_context::evaluate (this=0x7fffffffc810,
addr=0x7ffff459ce6b "W\aF\003", len=1, as_lval=true,
per_cu=0x7fffd00053f0, frame=..., addr_info=0x7fffffffcc30, type=0x0,
subobj_type=0x0, subobj_offset=0)
at gdb/dwarf2/expr.c:1136
#13 0x0000000000877c14 in dwarf2_locexpr_baton_eval (dlbaton=0x3e99c18,
frame=..., addr_stack=0x7fffffffcc30, valp=0x7fffffffcab0,
push_values=..., is_reference=0x7fffffffc9b0)
at gdb/dwarf2/loc.c:1604
#14 0x0000000000877f71 in dwarf2_evaluate_property (prop=0x3e99ce0,
initial_frame=..., addr_stack=0x7fffffffcc30, value=0x7fffffffcab0,
push_values=...) at gdb/dwarf2/loc.c:1668
#15 0x00000000009def76 in resolve_dynamic_range (dyn_range_type=0x3e99c50,
addr_stack=0x7fffffffcc30, frame=..., rank=0, resolve_p=true)
at gdb/gdbtypes.c:2198
#16 0x00000000009e0ded in resolve_dynamic_type_internal (type=0x3e99c50,
addr_stack=0x7fffffffcc30, frame=..., top_level=true)
at gdb/gdbtypes.c:2934
#17 0x00000000009e1079 in resolve_dynamic_type (type=0x3e99c50, valaddr=...,
addr=0, in_frame=0x0) at gdb/gdbtypes.c:2989
#18 0x0000000000488ebc in ada_discrete_type_low_bound (type=0x3e99c50)
at gdb/ada-lang.c:710
#19 0x00000000004eb734 in print_range (type=0x3e99c50, stream=0x30157b0,
bounds_preferred_p=0) at gdb/ada-typeprint.c:156
#20 0x00000000004ebffe in print_array_type (type=0x3e99d10, stream=0x30157b0,
show=1, level=9, flags=0x1bdcf20 <type_print_raw_options>)
at gdb/ada-typeprint.c:381
#21 0x00000000004eda3c in ada_print_type (type0=0x3e99d10,
varstring=0x401f710 "c_to", stream=0x30157b0, show=1, level=9,
flags=0x1bdcf20 <type_print_raw_options>)
at gdb/ada-typeprint.c:1015
#22 0x00000000004b4627 in ada_language::print_type (
this=0x2f949b0 <ada_language_defn>, type=0x3e99d10,
varstring=0x401f710 "c_to", stream=0x30157b0, show=1, level=9,
flags=0x1bdcf20 <type_print_raw_options>)
at gdb/ada-lang.c:13681
#23 0x0000000000f74646 in print_symbol (gdbarch=0x3256270, symbol=0x3e99db0,
depth=9, outfile=0x30157b0) at gdb/symmisc.c:545
#24 0x0000000000f737e6 in dump_symtab_1 (symtab=0x3ddd7e0, outfile=0x30157b0)
at gdb/symmisc.c:313
#25 0x0000000000f73a69 in dump_symtab (symtab=0x3ddd7e0, outfile=0x30157b0)
at gdb/symmisc.c:370
#26 0x0000000000f7420f in maintenance_print_symbols (args=0x0, from_tty=0)
at gdb/symmisc.c:481
#27 0x00000000006c7fde in do_simple_func (args=0x0, from_tty=0, c=0x321e270)
at gdb/cli/cli-decode.c:94
#28 0x00000000006ce65a in cmd_func (cmd=0x321e270, args=0x0, from_tty=0)
at gdb/cli/cli-decode.c:2826
#29 0x0000000001005b78 in execute_command (p=0x3f48fe3 "", from_tty=0)
at gdb/top.c:564
#30 0x0000000000966095 in command_handler (
command=0x3f48fd0 "maint print symbols")
at gdb/event-top.c:613
#31 0x0000000001005141 in read_command_file (stream=0x3011a40)
at gdb/top.c:333
#32 0x00000000006e2a64 in script_from_file (stream=0x3011a40,
file=0x7fffffffe21f "gdb.in")
at gdb/cli/cli-script.c:1705
#33 0x00000000006bb88c in source_script_from_stream (stream=0x3011a40,
file=0x7fffffffe21f "gdb.in", file_to_open=0x7fffffffd760 "gdb.in")
at gdb/cli/cli-cmds.c:706
#34 0x00000000006bba12 in source_script_with_search (
file=0x7fffffffe21f "gdb.in", from_tty=0, search_path=0)
at gdb/cli/cli-cmds.c:751
#35 0x00000000006bbab2 in source_script (file=0x7fffffffe21f "gdb.in",
from_tty=0) at gdb/cli/cli-cmds.c:760
#36 0x0000000000b835cb in catch_command_errors (
command=0x6bba7e <source_script(char const*, int)>,
arg=0x7fffffffe21f "gdb.in", from_tty=0, do_bp_actions=false)
at gdb/main.c:510
#37 0x0000000000b83803 in execute_cmdargs (cmdarg_vec=0x7fffffffd980,
file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffd8c8)
at gdb/main.c:606
#38 0x0000000000b84d79 in captured_main_1 (context=0x7fffffffdb90)
at gdb/main.c:1349
#39 0x0000000000b84fe4 in captured_main (context=0x7fffffffdb90)
at gdb/main.c:1372
#40 0x0000000000b85092 in gdb_main (args=0x7fffffffdb90)
at gdb/main.c:1401
#41 0x000000000041a382 in main (argc=9, argv=0x7fffffffdcc8)
at gdb/gdb.c:38
(gdb)
...
The immediate problem is in dwarf_expr_context::fetch_result where we're
calling get_frame_arch:
...
switch (this->m_location)
{
case DWARF_VALUE_REGISTER:
{
gdbarch *f_arch = get_frame_arch (this->m_frame);
...
with a null frame:
...
(gdb) p this->m_frame.is_null ()
$1 = true
(gdb)
...
Fix this using ensure_have_frame in dwarf_expr_context::execute_stack_op for
DW_OP_reg<n> and DW_OP_regx, getting us instead:
...
c_to: array (<>) of character; computed at runtime
...
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33512
(cherry picked from commit 32a7293a027d1bf7690d428075e52aa97dbf8350)
PowerPC: Fix typo in PowerPC note pseudo-section names
The recent tidy-up commit 09e56f0515c3 ("Code tidy: bfd/elf.c:
Tidy up core note handling code.") introduced regressions in the
PowerPC core note handling. The pseudo-section names for TM_CVSX,
TM_SPR, VSX and VMX notes were defined with an underscore instead of a
hyphen, breaking GDB test cases. The same goes for one riscv and one
s390 define.
This patch restores the correct section names by using hyphens in the
definitions, fixing 897 GDB test failures on PowerPC.
bfd/
* elf.c: (NOTE_PSEUDO_SECTION_PPC_TM_CVSX),
(NOTE_PSEUDO_SECTION_PPC_TM_SPR, NOTE_PSEUDO_SECTION_PPC_VSX),
(NOTE_PSEUDO_SECTION_PPC_VMX, NOTE_PSEUDO_SECTION_RISCV_CSR),
(NOTE_PSEUDO_SECTION_S390_CTRS): Use hyphens in section names
instead of underscores.