Lulu Cai [Fri, 28 Nov 2025 07:54:58 +0000 (15:54 +0800)]
LoongArch: Add support for the ud macro instruction
In the "ud ui5" macro, the value of ui5 must be in the range 0–31. It
expands to "amswap.w $rd, $r1, $rj", where ui5 specifies the register
number for $rd in the amswap.w instruction, and $rd == $rj.
The test case have been adjusted to no longer report errors for illegal
operands of the amswap.w instruction.
gas/
* config/tc-loongarch.c (check_this_insn_before_appending): No
longer check amswap.w.
* testsuite/gas/loongarch/illegal-operand.l: Update.
* testsuite/gas/loongarch/illegal-operand.s: Update.
* testsuite/gas/loongarch/macro_ud.d: New test.
* testsuite/gas/loongarch/macro_ud.s: New test.
Tom de Vries [Mon, 8 Dec 2025 15:38:28 +0000 (16:38 +0100)]
[gdb/testsuite] Fix FAIL in gdb.multi/remote-with-running-inferior.exp
Occasionally, with test-case gdb.multi/remote-with-running-inferior.exp I run
into:
...
(gdb) continue^M
Continuing.^M
^M
Thread 1.1 "remote-with-run" hit Breakpoint 1.1, main () at \
remote-with-running-inferior.c:31^M
31 for (int i = 0; i < 30; ++i)^M
(gdb) PASS: $exp: target_non_stop=auto: non_stop=off: \
continue to breakpoint: continue to breakpoint in breakpt
bt 1^M
(gdb) FAIL: $exp: target_non_stop=auto: non_stop=off: \
check inferior 1 is in breakpt
...
The problem is a race between:
- inferior 1 reaching main, and
- gdb setting a breakpoint on main.
If the breakpoint on main is set before inferior 1 reaches main, the
breakpoint triggers for inferior 1, which the test-case doesn't expect.
Fix this by setting the breakpoint on main only for inferior 2.
Andrew Burgess [Thu, 23 Oct 2025 15:34:20 +0000 (16:34 +0100)]
gdbsupport: remove undefined behaviour from (forward_)scope_exit
Our implementation of scope_exit and forward_scope_exit make use of
the Curiously Recurring Template Pattern (CRTP) to provide the
"release" functionality, this is done in the scope_exit_base class in
scope-exit.h.
The interesting (for this commit) parts of scope_exit_base look like
this:
~scope_exit_base ()
{
if (!m_released)
{
auto *self = static_cast<CRTP *> (this);
self->on_exit ();
}
}
... snip ...
};
By the time ~scope_exit_base is called the destructor for the derived
class (called CRTP here) has already been run, which means any data
members in the derived class will have also have had their destructors
run. As a result of this I believe that casting 'this' to the derived
type, and then calling the on_exit method is undefined behaviour, as
'this' can no longer be considered a valid instance of CRTP (the CRTP
part has been destructed).
In reality, the memory for the derived type is not reclaimed until
after ~scope_exit_base has finished, so as long as the data members of
the derived type are Plain Old Data (POD), then the current code
should be just fine; any data members of the derived class will remain
in place, and untouched, until ~scope_exit_base has completed.
But still, I don't think we should rely on undefined behaviour.
I actually ran into this when, in another series, I tried to reuse
scope_exit_base with a class where a data member was not POD, and in
this case GDB would crash because my new on_exit function was making
use of the non-POD data member after it had been destructed, and
resources released.
I propose that we move away from the CRTP, and instead flip the class
hierarchy. Instead of derived classes like scope_exit inheriting from
scope_exit_base, scope_exit_base should inherit from scope_exit.
What this means, is that when ~scope_exit_base is called, ~scope_exit
will not yet have been run, and the data members of scope_exit will
still be valid.
To allow the existing names to be used, the plan is that the existing
scope_exit and forward_scope_exit classes are renamed to
scope_exit_policy and forward_scope_exit_policy. These policy classes
will then be injected via a template argument as the base class for
scope_exit_base. Finally, we can:
template<typename EF>
using scope_exit = scope_exit_base<scope_exit_policy<EF>>;
which defines the scope_exit type. This type is a drop in replacement
with all of GDB's existing code, but avoids the undefined behaviour.
We can do something similar with forward_scope_exit.
There should be no user visible changes after this commit.
Starting in C23, strchr and strrchr will return const char *, if fed a
const char *. This means that several files in the BFD directory will
fail to build as they are assigning the return of those functions to a
char *.
Fix this by const-ifying several variables. The only place where that
wasn't just that was in targets.c, where a variable was being used in
subsequent strrchr invocations to change the underlying string, so a new
variable had to be introduced.
No user-visible change should happen after this commit.
Guinevere Larsen [Thu, 30 Oct 2025 20:43:55 +0000 (17:43 -0300)]
gdb/record_full: add ptid entry for history.
For record full to work on multi-threaded inferiors, we must know to
which thread any given recorded instruction belongs to. This commit adds
this as a new entry for each instruction when an inferior is
multi-threaded. This way, when replaying the instruction, the subsystem
is able to change inferior thread as needed, and avoid SIGILLs when
changing stuff
Ideally, we would only add the PTID entry when we actually need to
switch threads, but that is left as a future improvement.
WIP: replaying doesn't automatically change threads yet, but there was
an attempt
Magnus Wållberg [Mon, 8 Dec 2025 09:33:40 +0000 (20:03 +1030)]
PR 33676 ld segfaults when using binary input inside NOLOAD
The code at ldlang.c:2840-2841 checks if the output BFD is ELF format,
then unconditionally uses elf_section_type() on the input section
without verifying the input section is also ELF format.
This was introduced in commit d87be451e (PR ld/32787) which added
special handling for NOLOAD note sections.
PR 33676
PR 32787
* ldlang.c (lang_add_section): Check section owner's BFD
flavour before using elf_section_type.
Alan Modra [Mon, 8 Dec 2025 05:30:16 +0000 (16:00 +1030)]
PR 33698 and PR 33700
It is possible for dump_relocations to return on an error from
slurp_rela_relocs or slurp_rel_relocs without writing to
"all_relocations". In that case an uninitialised r_symbol is passed
to free at the end of process_got_section_contents.
Tom de Vries [Mon, 8 Dec 2025 08:30:25 +0000 (09:30 +0100)]
[gdb/build] Re-add *.[ch] in gdb.pot
In commit 4a40fe05bf0 ("[gdb/build] Handle gdbsupport and gdbserver in
gdb.pot"), in order to handle '*.cc' files I did:
...
- -name '*.[hc]' -print
+ -name '*.[hc]' -o -name '*.cc' -print
...
but failed to understand that this no longer printed the '*.[hc]' names.
Fix this by adding a '-print' for '*.[hc]'.
Tested by doing:
...
$ cd build/gdb
$ make po/gdb.pot
...
$ grep -c symtab.c po/gdb.pot
102
...
H.J. Lu [Sat, 6 Dec 2025 02:17:39 +0000 (10:17 +0800)]
elf: Add SHT_SUNW_ctf and SHT_SUNW_symnsort
On Solaris 11.4, there is SHT_SUNW_symnsort and no SHT_SUNW_symtabnsort.
SHT_SUNW_symnsort is defined to 0x6fffffec, which is the same as
SHT_SUNW_symtabnsort. There is also SHT_SUNW_ctf. Add SHT_SUNW_ctf and
rename SHT_SUNW_symtabnsort to SHT_SUNW_symnsort. Move SHT_SUNW_phname
after SHT_SUNW_symnsort.
binutils/
* readelf.c (get_solaris_section_type): Add SHT_SUNW_ctf and
SHT_SUNW_symnsort. Move SHT_SUNW_phname after SHT_SUNW_symnsort.
Remove SHT_SUNW_symtabnsort.
include/
* elf/common.h (SHT_SUNW_ctf): New.
(SHT_SUNW_symtabnsort): Renamed to ...
(SHT_SUNW_symnsort): This.
(SHT_SUNW_phname): Moved after SHT_SUNW_symnsort.
Tom Tromey [Fri, 5 Dec 2025 18:43:08 +0000 (11:43 -0700)]
Unconditionally pass is_a_field_of_this in c-exp.y
In a review to a different patch of mine, Simon asked for this change.
The idea here is that there's no need to pass null as the "field of
this" parameter, as lookup_language_this checks the language anyway.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Tom de Vries [Sun, 7 Dec 2025 09:59:54 +0000 (10:59 +0100)]
[gdb/contrib] Check clean files in check-whitespace-pre-commit.sh
The pre-commit check check-whitespace checks diffs.
Consequently, we detect something like this:
...
$ echo >> gdb/testsuite/lib/gdb.exp
$ git commit -a -m trailing-empty-line
...
check-whitespace.........................................................Failed
- hook id: check-whitespace
- duration: 0.01s
- exit code: 2
gdb/testsuite/lib/gdb.exp:11717: new blank line at EOF.
...
But say we work around the failing check using --no-verify, then we no longer
detect it after the commit has succeeded:
...
$ git commit -a -m trailing-empty-line --no-verify
[detached HEAD e6302105522] trailing-empty-line
1 file changed, 1 insertion(+)
$ pre-commit run --all-files check-whitespace
check-whitespace.........................................................Passed
- hook id: check-whitespace
- duration: 0.3s
...
Fix this in check-whitespace-pre-commit.sh by distinguishing between clean and
other files. Doing so is easier to do in a more advanced scripting language,
so rewrite into python.
Since a recent commit, gdb/testsuite is clean, so I'm using that as
simple classifier for now.
For the other files we do what we did before, and check just the staging area:
...
$ git --no-pager diff --staged --check "${other[@]}"
...
But for clean files, we check the entire file, including staged changes:
...
$ empty=$(git hash-object -t tree /dev/null)
$ git diff-index --cached --check $empty "${clean[@]}"
...
Consequently, we do see:
...
$ git commit -a -m trailing-empty-line --no-verify
[detached HEAD e6302105522] trailing-empty-line
1 file changed, 1 insertion(+)
$ pre-commit run --all-files check-whitespace
check-whitespace.........................................................Failed
- hook id: check-whitespace
- duration: 0.64s
- exit code: 2
gdb/testsuite/lib/gdb.exp:11717: new blank line at EOF.
...
elf: Renumber local dynamic symbols only if needed
caused regressions for hppa64-linux which adds local dynamic symbols,
__text_seg and __data_seg in elf64_hppa_late_size_sections. Set
has_local_dynsyms to true when adding __text_seg and __data_seg.
* elf64-hppa.c (elf64_hppa_late_size_sections): Set
has_local_dynsyms to true when adding __text_seg and __data_seg.
Andrew Burgess [Mon, 17 Nov 2025 14:08:57 +0000 (14:08 +0000)]
gdb: display a symbol more often in multi-file list output
I noticed that when a command line 'list foo.c:10' displays multiple
files, the symbol would always be shown as "???", e.g.:
file: "/tmp/foo.c", line number: 10, symbol: "???"
this is because, when the symtab_and_line is created for the
'foo.c:10', the pc and symbol are never filled in.
In this commit, I propose that, when we decide that the above header
line needs to be printed, we should attempt to lookup a symbol for the
relevant line, and if one is found, we can use that.
The symbol lookup is done by first calling find_pc_for_line, and then
using find_symbol_for_pc to find a suitable symbol.
On some configurations (SLES with glibc-devel installed), the compiler
links /usr/lib64/crit1.o (which contains some debug information) into
the final binary. As a result, the binary contains "some" debug
information, which makes the above pattern fail. The testcase is still
valid as we only really need the GPU code object (embedded in the main
binary) to not contain debug information, so this patch proposes to
relax this first step by using "gdb_load" instead.
Tested on x86_64-linux + AMDGPU gfx1031.
Change-Id: Id903f62e170af69c001b39f4681602a54e2fdaf1 Approved-By: Tom Tromey <tom@tromey.com>
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.
In --help option, adds znver6 to the list of CPUs under -march.
Please find the ISA descriptions for AVX512_BMM instructions below.
AVX512 Bit Manipulation Instructions
====================================
The AVX512BMM instructions include Bit Matrix Multiply and Bit Reversal
operations.
CPUID
-----
Support is indicated by the new CPUID 8000_0021, EAX bit 23, labeled AVX512_BMM.
DESCRIPTION
-----------
256 BIT VERSIONS
----------------
16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR reduction.
A ymm register holds a 16x16 bit matrix. The third source matrix for
accumulation is in ymm1.
512 BIT VERSIONS
----------------
2 parallel 16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR
reduction.
Each 256-bit chunk of a zmm register holds a 16x16 bit matrix. The third source
matrices for accumulation are in zmm1.
DESCRIPTION
-----------
Bit reversal within a byte boundary. Only applied to input bytes where the
corresponding mask bit is set; otherwise, bytes are left untouched or zeroed out
if zero masking is indicated.
gas/ChangeLog:
* NEWS: Add znver6 ARCH.
* config/tc-i386.c: Add znver6 ARCH, avx512_bmm SUBARCH.
* doc/c-i386.texi: Likewise.
* testsuite/gas/i386/i386.exp: Add znver6 test cases.
* testsuite/gas/i386/x86-64.exp: Add znver6 test cases.
* testsuite/gas/i386/arch-16-znver6.d: New test.
* testsuite/gas/i386/arch-16.d: New test.
* testsuite/gas/i386/arch-16.s: New test.
* testsuite/gas/i386/avx512_bmm.d: New test.
* testsuite/gas/i386/avx512_bmm.s: New test.
* testsuite/gas/i386/avx512_bmm_vl-inval.l: New test.
* testsuite/gas/i386/avx512_bmm_vl-inval.s: New test.
* testsuite/gas/i386/avx512_bmm_vl.d: New test.
* testsuite/gas/i386/avx512_bmm_vl.s: New test.
* testsuite/gas/i386/x86-64-arch-6-znver6.d: New test.
* testsuite/gas/i386/x86-64-arch-6.d: New test.
* testsuite/gas/i386/x86-64-arch-6.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm-bad.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm-bad.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.l: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl.s: New test.
Jan Beulich [Fri, 5 Dec 2025 09:12:34 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NCI-NDD-NF and testing
To reflect spec version 007's introduction of the three-way APX-NCI-NDD-NF
also introduce a respective ISA specifier, without that actually having a
counterpart in opcodes.
Add a testcase to cover all four new ISA specifiers.
Jan Beulich [Fri, 5 Dec 2025 09:12:12 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NF
While spec version 007 introduced the three-way APX-NCI-NDD-NF, let's
split the three aspects (NCI, NDD, and NF) in gas. For NF we only need to
guard the {nf} pseudo-prefix.
Jan Beulich [Fri, 5 Dec 2025 09:12:00 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NDD
While spec version 007 introduced the three-way APX-NCI-NDD-NF, let's
split the three aspects (NCI, NDD, and NF) in gas. Note that NDD also
applies to a number of EVEX-encoded insns with EVEX.ndd clear.
Some extra logic is needed in cpu_flags_match() to avoid the need to
add APX_NDD to CPU_FLAGS_COMMON.
Tom de Vries [Fri, 5 Dec 2025 07:24:06 +0000 (08:24 +0100)]
[gdb/testsuite] Fix gdb.base/long_long.exp on arm
On armv7hl-suse-linux-gnu, I run into:
...
(gdb) p/f val.oct
$26 = -5.9822653797615723e-120
(gdb) FAIL: gdb.base/long_long.exp: p/f val.oct
...
There's some complicated logic here in the test-case:
...
if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
# ARM FPA floating point numbers are not strictly little endian or big
# endian, but a hybrid. They are in little endian format with the two
# words swapped in big endian format.
# EABI targets default to natural-endian VFP format.
if { ([istarget "arm*-*-*"]) \
&& !([istarget "*-*-*eabi*"] || \
[istarget "*-*-mingw32ce*"] || \
[istarget "*-*-openbsd*"]) } then {
# assume the long long represents a floating point double in ARM format
gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
} else {
# assume the long long represents a floating point double in little
# endian format
gdb_test "p/f val.oct" "-5.9822653797615723e-120"
}
} else {
gdb_test "p/f val.oct" "-2.42716126e-15"
}
...
which makes the test-case expect the ARM FPA variant.
I think trying to pin down the exact circumstances under which we have ARM FPA
is unnecessary, so I could live with:
...
set re_val_oct_f [string_to_regexp "-5.9822653797615723e-120"]
if { [istarget "arm*-*-*"] } {
set re_val_oct_f_arm_fpa [string_to_regexp "2.1386676354387559e+265"]
re_val_oct_f "$re_val_oct_f|$re_val_oct_f_arm_fpa"
}
....
But instead, I propose to just drop the arm-specific part.
I doubt whether an ARM VPA setup is still part of any test matrix. And if it
is, then I expect other tests to fail as well for the same reason. The ARM
FPA logic is used only once in the test-case, but -5.9822653797615723e-120 is
used more frequently.
Indeed, I wonder the same about setups where -2.42716126e-15 is expected.
On such a setup, won't this fail as well:
...
gdb_test "x/2gf g" "3.5127005640885037e-303.*-5.9822653797615723e-120"
...
?
Unfortunately I'm not sure what setup to use to trigger the -2.42716126e-15
case.
Fix this as good as possible by choosing once between -5.9822653797615723e-120
and -2.42716126e-15, assigning it to re_val_oct_f, and using it everywhere
where those constants are used.
gdb: handle unlimited screen width case in print_gdb_hints
was merged that deleted some of the code I'd spotted. All that's left
is a 'return' that can be removed, there's nothing after the 'if'
block, the function just returns.
There should be no user visible changes after this commit.
Tom Tromey [Thu, 4 Dec 2025 14:36:59 +0000 (07:36 -0700)]
Fix 'ptype' of a certain Ada modular type
If an Ada modular type is the same size as gdb's own ULONGEST, ptype
will show "mod 0". This happens because ada_modulus does:
return (ULONGEST) high.const_val () + 1;
This patch cleans this up, replacing ada_modulus with a function to
return the upper bound (if available), and then fixing the various
callers. The type-printing caller still does the "+1", but now this
is done with a gdb_mpz.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33690 Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon Marchi [Tue, 2 Dec 2025 21:09:26 +0000 (16:09 -0500)]
gdb: remove find_target_at
... to make the current_inferior reference bubble up one level. Since
find_target_at would become a trivial wrapper around
inferior::target_at, remove it. I think it's clearer anyway to see
explicitly that the "subject" of the method call is the inferior.
Change-Id: I73ec44d37e7afea6e85b1689af65e32ae8e5a695 Approved-By: Tom Tromey <tom@tromey.com>
Alice Carlotti [Tue, 4 Nov 2025 12:22:52 +0000 (12:22 +0000)]
aarch64: Enable `-M notes' by default
We already print other instruction comments, such as condition code
aliases, by default. The `-M no-notes' option has been available in
Binutils for over 7 years, so if anyone does need the notes to be
disabled then they can do so explicitly.
Alice Carlotti [Wed, 5 Nov 2025 12:06:14 +0000 (12:06 +0000)]
aarch64: Refactor sysreg operand printing
This hopefully makes the logic clearer. It also adds NULL checks before
recording notes, and explicitly compares the inexactness of inexact
matches (although this extra comparison isn't used for any existing
encodings).
Alice Carlotti [Tue, 4 Nov 2025 12:28:56 +0000 (12:28 +0000)]
aarch64: Fix incorrect sysreg notes operand notes
When support for Armv8-R was added in 2020, aarch64_print_operand was
modified to check architecture features when searching for a system
register name. However, this mismatch is then conflated with
read-only/write-only mismatches, leading to incorrect note emission when
reading a read-only or writing a write-only system register that is not
available in whichever of Armv8-A or Armv8-R we are using.
The original code also segfaults when parsing `msr mpuir_el1, w1'. This
segfault arises while suggesting alternative assembler input with
corrected qualifiers, due to a missing NULL check when attempting to
emit notes. The segfault is unreachable after this change, but a
subsequent patch will incorporate NULL checking anyway.
Once notes are enabled by default, an existing `mrs x0, mpuir_el1' test
will verify that the incorrect notes are no longer generated.
Alice Carlotti [Wed, 5 Nov 2025 13:21:02 +0000 (13:21 +0000)]
aarch64: Improve comment for aarch64_opnd_info.sysreg.flags
This field is used differently during assembly and disassembly. It
would be nice if we could make this more consistent, but for now just
extend the comment to explain what is going on.
Patrick Monnerat [Sat, 29 Nov 2025 14:48:55 +0000 (15:48 +0100)]
gdb: handle unlimited screen width case in print_gdb_hints
This avoids a crash when this function is called while screen width is
unlimited. In such a case (unconditionally occurring in insight), WIDTH
is returned as a negative signed integer, so it has to be compared to
another signed integer, not a size_t.
Also remove an unused WIDTH-sized variable that may fail in the above
case.
Tom de Vries [Thu, 4 Dec 2025 09:29:52 +0000 (10:29 +0100)]
[gdb/testsuite] Fix build-id check in gdb.python/py-missing-objfile.exp
I recently added two requires in test-case gdb.python/py-missing-objfile.exp:
...
# The following tests assume that the build-ids of binfile and libfile can be
# found in the core file.
require {expect_build_id_in_core_file $binfile}
require {expect_build_id_in_core_file $libfile}
...
However, at the point where the check is done, the files are no longer
available at that location, which makes the require fail.
First, make the problem visible, by making proc expect_build_id_in_core_file
throw an error if the filename argument specifies a non-existing file.
Then, fix test-case gdb.python/py-missing-objfile.exp by moving the calls to
expect_build_id_in_core_file to a point where the files exist.
gdb/testsuite: Fix doc comment in allow_aarch64_sme_tests
The comment says that it returns 0 if the target supports SME and 1 if
it doesn't, but it actually does the opposite. The code does the right
thing, so fix the comment.
Simon Marchi [Wed, 26 Nov 2025 17:45:38 +0000 (12:45 -0500)]
gdb/guile: remove support for Guile < 2.2
I propose to remove the code in guile/scm-ports.c supporting Guile <
2.2. The rationale is:
- The code within USING_GUILE_BEFORE_2_2 amounts to about half of the
file, it makes it much more complicated than it would be otherwise.
I'm trying to investigate PR 29825 [1] and this is getting in the
way.
- Guile 2.2, which would now be the baseline for what we require, is
now 8 years old. Guile 2.2 is legacy (the current stable branch is
3.0), but it is still actively packaged [2][3].
- The Guile support code doesn't receive as much contribution, testing
and love as the Python support code, for instance. We don't have
cycles to spare to support an obsolete version of Guile.
This patch removes the USING_GUILE_BEFORE_2_2 define and all the
portions of code within `#if USING_GUILE_BEFORE_2_2`.
Tom Tromey [Fri, 28 Nov 2025 19:55:07 +0000 (12:55 -0700)]
Print more template parameters with ptype
This bug points out that a template parameter that is a constant is
not printed by 'ptype' -- in fact, only type parameters are displayed.
However, there's no real reason for this, and any template parameter
that the DWARF reader can turn into a symbol should be printable.
Note that some parameters are still missing from the DWARF; see the
kfails in the test for details.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33670 Reviewed-By: Christina Schimpe <christina.schimpe@intel.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
Tom de Vries [Wed, 3 Dec 2025 09:27:24 +0000 (10:27 +0100)]
[gdb/testsuite] Fix ERROR: can't read _line_unit_advertised_version: no such variable
With test-case gdb.base/until-trailing-insns.exp I run into:
...
ERROR: tcl error code TCL READ VARNAME
ERROR: can't read "_line_unit_advertised_version": no such variable
while executing
"if {$_line_unit_advertised_version == "default"} {
set _line_unit_advertised_version $_line_unit_version
}"
...
Fix this by using the correct variable name in two places in Dwarf::lines:
use _line_unit_advertised_version instead of _line_advertised_unit_version.
Tom de Vries [Wed, 3 Dec 2025 08:07:30 +0000 (09:07 +0100)]
[gdb/symtab] Fix DW_TAG_member regression
On openSUSE Leap 15.6 x86_64, with gcc 7 and test-case
gdb.base/condbreak-multi-context.exp I run into:
...
(gdb) print aaa^M
$3 = <optimized out>^M
(gdb) FAIL: $exp: start_before=true: scenario_1: print aaa
...
This is a regression since commit 86ac8c54623 ("Convert
lookup_symbol_in_objfile").
Likewise in test-cases gdb.cp/m-static.exp and gdb.cp/namespace.exp.
The failure is specific to using Dwarf v4:
- using target board unix/gdb:debug_flags=-gdwarf-5 fixes it
- using target board unix/gdb:debug_flags=-gdwarf-4 on Tumbleweed (with gcc 15
and Dwarf v5 default) triggers it
The variable we're trying to print, A::aaa is a static const int member:
...
class A : public Base
{
public:
static const int aaa = 10;
...
};
...
With Dwarf v5, we have this DIE:
...
<2><356>: Abbrev Number: 2 (DW_TAG_variable)
<357> DW_AT_name : aaa
<35c> DW_AT_linkage_name: _ZN1A3aaaE
<364> DW_AT_external : 1
<364> DW_AT_accessibility: 1 (public)
<364> DW_AT_declaration : 1
<364> DW_AT_const_value : 10
...
and the cooked index contains these corresponding entries:
...
[45] ((cooked_index_entry *) 0x7facf0004730)
name: _ZN1A3aaaE
canonical: _ZN1A3aaaE
qualified: _ZN1A3aaaE
DWARF tag: DW_TAG_variable
flags: 0x4 [IS_LINKAGE]
DIE offset: 0x356
parent: ((cooked_index_entry *) 0)
[52] ((cooked_index_entry *) 0x7facf0004700)
name: aaa
canonical: aaa
qualified: A::aaa
DWARF tag: DW_TAG_variable
flags: 0x0 []
DIE offset: 0x356
parent: ((cooked_index_entry *) 0x7facf00046d0) [A]
...
With Dwarf v4, we have instead the following DIE:
...
<2><350>: Abbrev Number: 3 (DW_TAG_member)
<351> DW_AT_name : aaa
<35b> DW_AT_external : 1
<35b> DW_AT_accessibility: 1 (public)
<35c> DW_AT_declaration : 1
<35c> DW_AT_const_value : 4 byte block: a 0 0 0
...
and there are no corresponding entries.
Fix this by adding an entry:
...
[47] ((cooked_index_entry *) 0x7f5a24004660)
name: aaa
canonical: aaa
qualified: A::aaa
DWARF tag: DW_TAG_member
flags: 0x0 []
DIE offset: 0x350
parent: ((cooked_index_entry *) 0x7f5a24004630) [A]
...
Add a regression test in the form of a dwarf assembly test-case printing the
value of variable A::aaa.
In the test-case, for A::aaa, DW_FORM_flag is used to encode
DW_AT_declaration. In v1 of this patch that mattered (because of using
has_hardcoded_declaration in abbrev_table::read), but that's no longer the
case. Nevertheless, also add an A::bbb using FORM_flag_present for
DW_AT_declaration (and while we're at it, DW_AT_external as well).
Also add two variants, for which <optimized out> is printed:
- A::ccc: a variant with DW_AT_location instead of DW_AT_const_value, and
- A::ddd: a variant without external.
This behavior is not part of the regression. I've reproduced it using a
system gdb based on 14.2. It's also not specific to using the cooked index,
it reproduces with -readnow as well.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/33415
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33415
Tom de Vries [Wed, 3 Dec 2025 07:58:13 +0000 (08:58 +0100)]
[gdb/symtab] Bail out for too short line header
The Free Pascal Compiler fpc supports generating different versions of DWARF:
...
$ fpc -h
Free Pascal Compiler version 3.2.2 [2025/09/10] for x86_64
...
-gw Generate DWARFv2 debug information (same as -gw2)
-gw2 Generate DWARFv2 debug information
-gw3 Generate DWARFv3 debug information
-gw4 Generate DWARFv4 debug information (experimental)
...
The v4 support is experimental, and indeed the line number information is
broken (missing maximum_operations_per_instruction field in the .debug_line
header), so setting a breakpoint on a line number is not possible:
...
$ fpc -gw4 hello.pas
...
$ gdb -q hello
Reading symbols from hello...
(gdb) b hello.pas:8
No compiled code for line 8 in file "hello.pas".
Make breakpoint pending on future shared library load? (y or [n])
...
The brokenness is detected by llvm-dwarfdump (second warning):
...
$ llvm-dwarfdump -debug-line hello
hello: file format elf64-x86-64
.debug_line contents:
debug_line[0x00000000]
warning: parsing line table prologue at offset 0x0 found opcode base of 0. \
Assuming no standard opcodes
warning: unknown data in line table prologue at offset 0x0: parsing ended (at \
offset 0x00000017) before reaching the prologue end at offset 0x2a
...
Likewise, detect the situation the second warning describes in
dwarf_decode_line_header, getting us instead:
...
(gdb) b hello.pas:8
❌malformed line number program header, advertised length does not match \
actual length
(gdb)
...
Tested on x86_64-linux.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Tom de Vries [Tue, 2 Dec 2025 19:52:18 +0000 (20:52 +0100)]
[gdb] Handle *.ac and *.m4 files in .gitattributes
Since commit 52ca3d3fe61 ("toplevel: unify the GCC and GDB/binutils .editorconfig
files"), .editorconfig has settings for .ac and .m4 files:
...
[*.{ac,m4}]
indent_style = tab
indent_size = 2
trim_trailing_whitespace = true
...
There are no setting for those files in .gitattributes, so the whitespace
attribute defaults to trailing-space (shorthand for blank-at-eol,
blank-at-eof) and space-before-tab.
Since according to .editorconfig the indentation style is tab, add
indent-with-non-tab as well.
Since aclocal.m4 is generated, unset the whitespace attribute. Likewise for
configure.
Probably, this eventually needs to be added to root level .gitattributes, but
for now try this in gdb*/.gitattributes.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon Marchi [Mon, 17 Nov 2025 21:25:18 +0000 (16:25 -0500)]
gdb/ser-unix: work around conflicting types for tcflag_t
When trying to cross-compile GDB to sparc-buildroot-linux-uclibc, I get:
CXX ser-unix.o
In file included from /data1/smarchi/many-buildroots/toolchains/sparc/sparc-buildroot-linux-uclibc/sysroot/usr/include/termios.h:39,
from /home/smarchi/src/binutils-gdb/gdb/ser-unix.c:51:
/data1/smarchi/many-buildroots/toolchains/sparc/sparc-buildroot-linux-uclibc/sysroot/usr/include/bits/termios.h:26:22: error: conflicting declaration ‘typedef unsigned int tcflag_t’
26 | typedef unsigned int tcflag_t;
| ^~~~~~~~
In file included from /home/smarchi/src/binutils-gdb/gdb/ser-unix.c:46:
/data1/smarchi/many-buildroots/toolchains/sparc/sparc-buildroot-linux-uclibc/sysroot/usr/include/asm/termbits.h:13:25: note: previous declaration as ‘typedef long unsigned int tcflag_t’
13 | typedef unsigned long tcflag_t;
| ^~~~~~~~
uClibc and the kernel don't agree on the definition of tcflag_t for this
architecture. Here' uClibc [1]:
typedef unsigned int tcflag_t;
And here's the kernel [2]:
#if defined(__sparc__) && defined(__arch64__)
typedef unsigned int tcflag_t;
#else
typedef unsigned long tcflag_t; <--- that branch is take
#endif
glibc [3] has the same definition as uClibc, so we would get the same
problem.
I propose to work around this the same way as we handle differences in
the termios structure, by renaming the version from the kernel.
I opened a bug on the glibc bugzilla [4] to ask if this is something
that would need to be fixed on the libc side, but in the mean time we
need to work around it.
Tom Tromey [Sun, 16 Nov 2025 21:15:48 +0000 (14:15 -0700)]
Rewrite the @selector code
This rewrites the Objective-C @selector implementation in c-exp.y,
following a couple general comments in the patch supplied for
bug 20503.
I suspect something else changed in the Objective-C runtime, though,
as most of the examples in that bug still do not work, even though
this series (I believe) addresses all the same points.
Tom Tromey [Sun, 16 Nov 2025 21:01:42 +0000 (14:01 -0700)]
Remove a couple Objective-C expression helpers
The Objective-C expression code has a couple of helper functions with
just a single caller. This patch unifies them with the appropriate
evaluate method.
Tom Tromey [Sun, 16 Nov 2025 17:33:37 +0000 (10:33 -0700)]
Rename lookup_struct_typedef
The helper function lookup_struct_typedef is only ever called with
"noerr=1". This patch removes the parameter, changes the name, and
removes some unnecessary code.
Tom Tromey [Sat, 15 Nov 2025 18:25:42 +0000 (11:25 -0700)]
Minor fixes to make gdb.objc tests pass
Once the gdb.objc tests compile, you can see that they do not pass.
The issue is primarily that they are over-strict about line numbers.
This fixes the problem by replacing these line numbers with $decimal.
Tom Tromey [Sat, 15 Nov 2025 17:37:37 +0000 (10:37 -0700)]
Make the gdb.objc tests compile
The gdb.objc tests haven't compiled in years. This patch fixes this,
based on a comment in bug 31671.
I don't know whether this approach works with the clang implementation
of Objective-C. However, it does work with GCC, provided that
gnustep-base is installed.
Nick Clifton [Tue, 2 Dec 2025 11:06:01 +0000 (11:06 +0000)]
Synchronize the dwarf2.h and dwarf2.def files with their gcc counterparts, bringing the definitions of DW_AT_language_name and DW_AT_language_version. Add code to binutils/dwarf.c to display these attributes.
H.J. Lu [Sat, 29 Nov 2025 00:47:46 +0000 (08:47 +0800)]
x86: traverse loc_hash_table only if used
Traverse x86 loc_hash_table only if it is used.
* elf32-i386.c (elf_i386_output_arch_local_syms): Traverse
loc_hash_table only if has_loc_hash_table is set.
* elf64-x86-64.c (elf_x86_64_output_arch_local_syms): Likewise.
* elfxx-x86.c (_bfd_elf_x86_get_local_sym_hash): Set
has_loc_hash_table.
(_bfd_x86_elf_late_size_sections): Traverse loc_hash_table only
if has_loc_hash_table is set.
* elfxx-x86.h (elf_x86_link_hash_table): Move plt0_pad_byte and
add has_loc_hash_table.
Simon Marchi [Mon, 17 Nov 2025 21:48:25 +0000 (16:48 -0500)]
gdb, gdbserver: propagate use of target_desc unique pointers
Propagate the use of target_desc unique pointers further. Basically,
avoid releasing target_desc objects, except in some spots in gdbserver
(e.g. netbsd) where we don't currently have a persistent container for
created target descriptions (and the target desc just leaks). Introduce
const_target_desc_up to change some `const target_desc *` to a unique
pointer without loss of constness.
Architectures that use the old regformats/regdat.sh don't need to be
changed, because their target_desc objects are statically allocated in
the generated files.
I was able to built-test these native configs:
- Linux AArch64
- Linux ARC
- Linux AMD64
- Linux ARM
- Linux LoongArch
- Linux M68K
- Linux Microblaze
- Linux MIPS (32 and 64)
- Linux or1k
- Linux PPC (32 and 64)
- Linux RISC-V
- Linux s390x
- Linux SH4
- Linux Sparc (32 and 64)
- Linux Xtensa
- FreeBSD AMD64
- NetBSD AMD64
- Windows i686
- Windows AMD64
For the rest, I did my best by staring at the code long enough. I
probably missed or messed some spots, but that shouldn't be difficult to
fix.
Simon Marchi [Mon, 1 Dec 2025 21:19:07 +0000 (16:19 -0500)]
gdbserver: remove leftovers from tic6x target_desc selftests
Commit 9a5d3e6c4a50 ("gdb: remove tic6x .dat files") removed the .dat
files that were used solely for selftests in linux-tic6x-low.cc.
However, I forgot to remove the things that depended on that in
linux-tic6x-low.cc (or rather, I put them in the wrong patch). As-is,
linux-tic6x-low.cc will certainly no build, because function
selftests::tdesc::tic6x_tdesc_test is not defined anywere. Remove those
remaining bits.
Tom Tromey [Fri, 14 Nov 2025 20:44:22 +0000 (13:44 -0700)]
Rename some locals in objc_msgcall_operation::evaluate
This renames a couple of local variables in
objc_msgcall_operation::evaluate, in preparation for the next patch.
This is done separately because the next patch is pretty messy and
this makes it a little simpler.
Tom Tromey [Fri, 14 Nov 2025 20:42:11 +0000 (13:42 -0700)]
Use a vector in objc_msgcall_operation::evaluate
This changes objc_msgcall_operation::evaluate to use a std::vector
rather than XALLOCAVEC. alloca is bad and should generally be
avoided; and anyway there's no justification for it here.
Tom Tromey [Fri, 14 Nov 2025 20:40:22 +0000 (13:40 -0700)]
Fix crash from eval_op_objc_msgcall
Trying to evaluate an Objective-C message call will cause gdb to
crash. This happens because this code was not correctly updated when
call_function_by_hand was changed to accept an array_view, and the
trailing NULL pointer was no longer required.
GNAT recently added support for asynchronous aborts of tasks blocked in
calls to Ada.Synchronous_Task_Control.Suspend_Until_True. That GNAT
change added a new value to the Task_States enumerated type. This patch
adds the corresponding value to task_states.
Simon Marchi [Fri, 21 Nov 2025 20:14:05 +0000 (15:14 -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 [Fri, 21 Nov 2025 20:14:03 +0000 (15:14 -0500)]
gdb/dwarf: store addr/offset/ref_addr sizes in dwarf2_per_cu
New in v2:
- make the test try with indexes by default
- using uint8_t instead of unsigned char
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>
Simon Marchi [Fri, 21 Nov 2025 20:14:02 +0000 (15:14 -0500)]
gdb/dwarf: when in dwarf2_cu, read addr_size from dwarf2_cu::header
New in v2: make the test try with indexes by default
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: