Simon Marchi [Mon, 9 Feb 2026 21:27:04 +0000 (16:27 -0500)]
gdb/testsuite: do not force -static in gdb.ada/mi_ex_cond.exp
When running gdb.ada/mi_ex_cond.exp on Debian 13, I get:
-catch-exception -c "i = 2" -e constraint_error
^error,msg="Your Ada runtime appears to be missing some debugging information.\nCannot insert Ada exception catchpoint in this configuration."
(gdb)
FAIL: gdb.ada/mi_ex_cond.exp: catch C_E if i = 2 (unexpected output)
And this is despite having the check "gnat_runtime_has_debug_info" at
the top of the file.
The problem is that the "gnat_runtime_has_debug_info" is done using the
toolchain's default mode, regarding linking to a static or shared
libgnat. On Debian, the default is specificalyl changed to be shared
[1].
However, the test forces linking to a static libgnat. The result is
that gnat_runtime_has_debug_info passes, seeing that when linking
against libgnat.so, debug info is available (distributed as separate
debug info, in /usr/lib/debug). But then, the test explicitly builds
against a static libgnat, and then fails because debug info is not
found.
I propose to remove that "force static" part of the test. It was added
in the test in the original commit that introduced it [2] without
explanation. Not forcing it makes more sense to me:
gnat_runtime_has_debug_info checks if, when using the default linking
mode of the toolchain, debug info can be found. And then, not
specifying anything to gdb_compile_ada builds the test binary with the
default mode of the toolchain. So the two are coherent.
With this patch, I see the failures shown by Tom Tromey in this patch
[3], and with his patch applied, the test passes fine.
Tom Tromey [Mon, 9 Feb 2026 19:17:17 +0000 (12:17 -0700)]
Minor Ada test fix for gnat-llvm
gdb.ada/char_enum_overload.exp fails because LLVM optimizes away the
necessary function parameters. Adding a couple of calls to Do_Nothing
makes this test work.
aarch64: Add the missing tests for TLBI <operation> vmallws2e1
In the support for FEAT_TLBID feature patch, few <operation>
variants are added to the aarch64_sys_regs_tlbi table,
and that patch was missing the tests for following <operation>
variants, which are covered in this patch.
Alan Modra [Tue, 10 Feb 2026 00:16:47 +0000 (10:46 +1030)]
tidy elf attr error handling
Add a missing error check, and make another error check a little more
stringent. If it were ever possible for oav2_parse_attr to return
zero, the loop would not terminate.
* elf-attrs.c (oav2_parse_subsection): Check read_ntbs return
for errors. Tidy loop reading attrs, and error on <= 0.
Alan Modra [Tue, 10 Feb 2026 00:04:48 +0000 (10:34 +1030)]
PR 33858 Object Attributes v2 memory leaks
It is possble for elf_object_p to hit errors after or during the loop
processing sections with bfd_section_from_shdr. That means we might
have some object attributes malloc'd. They need cleaning up in
elf_object_p because bfd_check_format_matches only handles tidying of
bfd_alloc memory.
* elfcode.h (elf_object_p): Free object attributes on failure.
Tom Tromey [Mon, 9 Feb 2026 03:52:04 +0000 (20:52 -0700)]
Fix gdb.ada/mi_ex_cond.exp when libgnat debuginfo is installed
When libgnat debuginfo is installed, gdb.ada/mi_ex_cond.exp will fail.
I tracked this down to two problems:
1. The MI output has changed a little. This probably wasn't noticed
because this test only works when libgnat debuginfo is available,
which isn't the norm. This patch updates the expected output.
2. The variable "I" in the test triggers the Ada disambiguation menu,
because some variables named "I" are visible in libgnat. While at
its root this is a deeper problem in the Ada support, it's
complicated to fix this. Since this isn't the point of the test,
this patch just renames the variable in question.
There are some other Ada tests that fail in this setup, but I think
they are a bit more complicated to fix.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon Marchi [Sun, 8 Feb 2026 22:04:11 +0000 (17:04 -0500)]
gdb/registry: add registry::key::try_emplace
We have many times the pattern:
current_source_location *loc
= current_source_key.get (pspace);
if (loc == nullptr)
loc = current_source_key.emplace (pspace);
return loc;
I thought it would be nice to have it directly part of registry::key.
Add a try_emplace method, which is like emplace, except that it returns
the existing data, if any. The try_emplace name comes from similar
methods in std::map or gdb::unordered_map
(ankerl::unordered_dense::map).
Replace as many callers as I could find to use it.
Change-Id: I21f922ca065a354f041caaf70484d6cfbcbb76ed Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Sun, 8 Feb 2026 22:04:10 +0000 (17:04 -0500)]
gdb/registry: make registry::key::emplace return a reference
Since we use C++ and not C, I think that we should gradually move to
using references for things that can never be nullptr. One example of
this is the return value of the emplace method.
Change it to return a reference, and (to keep the patch straightforward)
update all callers to take the address. More patches could follow to
propagate the use of references further.
Change-Id: I725539694cf496f8288918cc29d7aaae9aca2292 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Sun, 8 Feb 2026 22:04:09 +0000 (17:04 -0500)]
gdb/guile: wrap scm-arch.c per-arch data in a structure
scm-arch.c uses "void" as a registry data type here:
/* Use a 'void *' here because it isn't guaranteed that SCM is a
pointer. */
static const registry<gdbarch>::key<void, gdb::noop_deleter<void>>
arch_object_data;
This conflicts with my subsequent patch that makes the emplace method
return a reference because it's not valid to have `void &`.
Circumvent the problem by defining a structure type to use in the
registry, instead of storing the SCM directly. I think that makes the
code more straightforward and less hacky anyway (at the cost of one
extra allocate per gdbarch that you would use in your Guile code...).
Change-Id: I8d92234a9b0384098fa066dc79a42195dee7ca04 Approved-By: Tom Tromey <tom@tromey.com>
Tom Tromey [Fri, 16 Jan 2026 16:19:09 +0000 (09:19 -0700)]
Use std::make_unique with ui_files
This changes a couple of spots to use std::make_unique rather than
'new'. This is a bit more idiomatic. I've only touched code
involving ui_file here, there are plenty more changes like this that
could be made, but I considered those unrelated to this series.
Tom Tromey [Wed, 10 Dec 2025 09:24:13 +0000 (02:24 -0700)]
Warn if log file changed while logging
PR gdb/33531 points out that while some "set logging" commands will
warn if you attempt to change settings when logging is already active,
"set logging file" does not. This patch corrects this oversight.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33531 Approved-By: Andrew Burgess <aburgess@redhat.com>
Tom Tromey [Sat, 6 Dec 2025 21:12:37 +0000 (15:12 -0600)]
Rewrite output redirection and logging
This patch changes how gdb output redirection is done.
Currently, output is done via the UI. gdb_stdout, for example, is a
define the expands to an lvalue referencing a field in the current UI.
When redirecting, this field may temporarily be reset; and when
logging is enabled or disabled, this is also done.
This has lead to bugs where the combination of redirection and logging
results in use-after-free. Crashes are readily observable; see the
new test cases.
This patch upends this. Now, gdb_stdout is simply an rvalue, and
refers to the current interpreter. The interpreter provides ui_files
that do whatever rewriting is needed (mostly for MI); then output is
forward to the current UI via an indirection (see the new
ui::passthrough_file).
The ui provides paging, logging, timestamps, and the final stream that
writes to an actual file descriptor.
Redirection is handled at the ui layer. Rather than changing the
output pipeline, new ui_files are simply swapped in by rewriting
pointers, hopefully with a scoped_restore.
Redirecting at the ui layer means that interpreter rewriting is still
applied when capturing output. This fixes one of the reported bugs.
Not changing the pipeline means that the problems with the combination
of redirect and logging simply vanish. Logging just changes a flag
and doesn't involve object destruction.
Tom Tromey [Sat, 6 Dec 2025 21:35:24 +0000 (15:35 -0600)]
Add a new logging_file implementation
This adds a new logging_file subclass of ui_file. This new subclass
handles the details of logging, by consulting the relevant globals.
I think a dependency on globals is warranted here, because the logging
settings themselves are global.
The idea of this approach is that rather than modifying the output
pipeline in response to logging commands, a logging_file will simply
always be in the pipeline, and will then react to the appropriate
settings. ("Appropriate" because there are tests that the logger
doesn't immediately react to changes, so it captures settings at the
moment logging starts.)
The new code isn't actually used yet -- nothing in this patch
constructs a logging_file. It's separate for easier review.
Tom Tromey [Tue, 9 Dec 2025 15:38:30 +0000 (08:38 -0700)]
Remove m_applied_style from ui_file
While working on this series, I found a number of odd styling issues
recurred. For instance, the issue where the pager would lose track
and style subsequent output incorrectly reappeared.
It turned out that different ui_file objects in the output pipeline
would get confused about their current style. And, looking deeper at
this, I realized that mainly it is the pager that really needs to
track the current style at all. All the other file implementations
can be purely reactive (except the buffered stream code, as Andrew
pointed out).
This patch moves m_applied_style from ui_file and into pager_file.
This necessitated making ui_file::vprintf virtual, so that the base
class could pass in the "plain" style as the starting point, whereas
the pager could use the applied style. (I did not investigate whether
this was truly necessary, and I somewhat suspect it might not be.)
This straightforward approach caused some regressions, mostly
involving extra ANSI escapes being emitted. I fixed most of these by
arranging for ui_out::call_do_message to track styles a little more
thoroughly.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
Tom Tromey [Thu, 11 Dec 2025 22:12:30 +0000 (15:12 -0700)]
Rewrite cli-style.c:do_show
IMO it looks a little nicer if cli-style.c:do_show uses a single
printf to display its output. This is also slightly more
i18-friendly.
I noticed this while debugging a case where multiple redundant ANSI
escapes were sent. In conjunction with a subsequent patch, this
approach happens to fix that problem. FWIW I don't consider such
redundancies to be bugs, but it was convenient to change this one.
Tom Tromey [Tue, 9 Dec 2025 16:37:26 +0000 (09:37 -0700)]
Restore ui_file::can_page
A while back, I removed the ui_file::can_page method. It wasn't
needed for a while, due to how output redirections were done.
With the new approach in this series, it's convenient to have this
method again, because the pipeline downstream from the pager won't
change when logging -- the logging filter will be enabled or disabled
without reconfiguring the pipeline. This method lets the pager adapt
correctly.
Tom Tromey [Sat, 17 Jan 2026 16:09:22 +0000 (09:09 -0700)]
Remove gdb_stdtargin
gdb_stdtargin is only used in a single place; and, strangely, does not
follow the current UI. This patch removes the global and changes the
one user to use gdb_stdin instead.
Tom Tromey [Sun, 7 Dec 2025 00:55:20 +0000 (18:55 -0600)]
Move buffered stream to new files
The buffered stream code is currently in ui-out.h and ui-out.c, which
seems weird because it seems more like a low-level ui-file idea (for
the most part, it does also affect some ui_out).
This patch moves the declarations to a new header file,
buffered-streams.h and the implementation to buffered-streams.c. This
seems cleaner to me.
Tom Tromey [Sun, 7 Dec 2025 23:29:17 +0000 (17:29 -0600)]
Move stdtarg to ui
Currently, most of the output streams are handled by the UI -- with
the sole exception of gdb_stdtarg. This doesn't make sense to me, and
it is is useful in the longer term to make it per-UI so that the
logging approach can be uniform across all streams. So, this moves it
to the UI, following the implementation approach of all other output
streams.
Tom Tromey [Mon, 9 Feb 2026 14:33:59 +0000 (07:33 -0700)]
Remove unused local variable from c_type_print_base_struct_union
In my earlier patch to remove TYPE_FN_FIELD_STUB, I didn't notice that
the local variable mangled_name_holder is now unused and can be
removed. The compiler didn't notice, either, I assume because it has
a constructor and destructor.
The commit causes regressions in 15 test-cases (x86_64-linux, openSUSE
Leap 16.0).
I investigated one regression, in test-case gdb.base/condbreak-call-false.exp,
and in that case glibc debuginfo was required to reproduce the regression.
It's not necessary to link with mold nor to build with -O0 to reproduce
the error, but it makes the error message more informative regarding
which use of std::atomic requires the __atomic_compare_exchange symbol.
For some reason, the compare_exchange_strong calls on
`std::atomic<packed<dwarf_source_language, 2>>` added in 329a53a6d5 make
clang generate a call into libatomic, whereas gcc implements it using
only the generated assembly. I'm no compiler expert, but this seems
like a choice that each compiler is free to make. The solution is to
use the -latomic flag when linking in clang builds.
We (the ROCgdb team) considered writing a targeted configure check to
determine if -latomic was needed for this specific edge case, for the
toolchain in use. But we ended up thinking it would be simpler to just
always link with libatomic, when it is present. We think there is no
real downside to it. If libatomic is not really needed, since most
toolchains now default to using --as-needed, libatomic won't be
DT_NEEDED if it's not truly needed. Plus, if things change (either our
code or the compilers) in the future and more things end up requiring
libatomic, we'll be covered.
Bug 33879 is about the error shown above. Bug 29455 appears to be the
same, but about symbol __atomic_load.
Change-Id: I6778ae8f35acc99ffb8955479bb57766eecf4556
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33879
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29455 Approved-By: Tom Tromey <tom@tromey.com>
Tom Tromey [Wed, 21 Jan 2026 19:27:44 +0000 (12:27 -0700)]
Mark some gdbarch components as "unused"
This adds a new "unused" attribute to gdbarch components, and marks a
few this way. The only goal of this patch is to make it so that
check-gdbarch.py gives an empty report by default.
Tom Tromey [Mon, 4 Nov 2024 20:56:48 +0000 (13:56 -0700)]
Remove the auto_charset gdbarch hook
The auto_charset gdbarch hook has never been set by any architecture.
I probably added it (don't remember) to be parallel to
auto_wide_charset -- but considering that it hasn't ever been needed,
it seems fine to remove it.
Tom Tromey [Mon, 4 Nov 2024 07:51:16 +0000 (00:51 -0700)]
Use 'invalid' rather than 'predicate' in some gdbarch functions
The check-gdbarch.py script points out that a few gdbarch functions
have a predicate that is never called. This patch changes these
functions to use 'invalid=False' instead, removing a bit of code.
Tom Tromey [Sat, 2 Nov 2024 17:36:45 +0000 (11:36 -0600)]
Add check-gdbarch.py
This adds a new check-gdbarch.py script. This script checks the
sources to see which gdbarch methods are set but never called, and
which ones are called but never set.
This uses Pygments to scan the sources, to ensure we don't
accidentally pick up gdbarch references from comments (or, less
likely, strings). Because this is pretty slow, it also uses "tqdm" to
show a progress bar. (You can "pip install tqdm" to get this.)
Tom Tromey [Tue, 13 May 2025 23:53:27 +0000 (17:53 -0600)]
Remove best_symbol and better_symbol
This patch removes best_symbol and better_symbol.
Before some c-exp.y changes this year, best_symbol was the source of
excess CU expansion, because searches that include SEARCH_VAR_DOMAIN
will keep going until a symbol is found in that domain, or until all
matches have been exhausted. So, for instance a "SEARCH_VFT" search
for "int" will, most likely, expand all CUs -- even though the
argument implies that a type would be suitable.
Nowadays, best_symbol is more of an aesthetic offense and abstraction
violation, encoding a workaround for a C++ expression lookup bug into
a low-level lookup function.
This patch changes the the C parser to simply do two lookups,
prioritizing SEARCH_VAR_DOMAIN. This way, it gets the result it is
presumably looking for, without causing excessive expansion (if that's
currently possible) and without pushing its requirements into generic
code.
Note that the special case for "stub" symbols remains. This one is
less problematic, at least for the time being, as such symbols aren't
common. (Kevin does have a patch pending in this area but I don't
believe this change should affect it, as the stub symbol case remains
unchanged.)
New in v2: addressed review comments and reworded the commit text.
v1 is here:
Indu Bhagat [Fri, 6 Feb 2026 20:21:34 +0000 (12:21 -0800)]
objdump: sframe: fix multiple emission of SFrame and DWARF Frame
Currently, when a user specifies both -WF (to dump DWARF Frame) and
--sframe, the dump_dwarf () call is triggered twice,
First, in dump_bfd ():
if (dump_dwarf_section_info)
dump_dwarf (abfd, is_mainfile);
And then again in dump_bfd () via:
if (dump_sframe_section_info)
dump_sframe_section (abfd, dump_sframe_section_name, is_mainfile);
Where dump_sframe_section () itself invokes dump_dwarf () to emit SFrame
section.
The original intent of making dump_sframe_section () to invoke
dump_dwarf () was to reuse the existing (DWARF) machinery for relocation
and emission of SFrame section (along with DWARF sections). But this
may cause duplicate emission as noted above (PR 33806).
So, carve out the necessary work into dump_sframe_section () to make it
not invoke dump_dwarf (): explicitly load the SFrame section and then
invoke the associated display function directly. This ensures that the
SFrame textual dump is emitted exactly once as intended.
Additionally, this patch removes:
- the temporary "sframe-internal-only" debug option because it not
needed anymore, now that we dont use dump_dwarf () for SFrame dumping
anymore.
- stubs from dump_dwarf_section () specific to SFrame, as it is not
called for it anymore.
While at it, xstrdup consistently and free the dump_sframe_section_name
var.
Update the existing sframe-func.s to ensure .eh_frame section is emitted
as well. Add new test objdump-sframe-2.d to verify that textual dump
using objdump contains single textual dumps of .eh_frame and .sframe (if
both --sframe and -WF are specified).
PR libsframe/33806
binutils/
PR libsframe/33806
* dwarf.c (debug_option_table): Remove sframe-internal-only.
* objdump.c (dump_sframe_section): Call display function
directly instead of dump_dwarf.
(dump_bfd): Update call to dump_sframe_section.
(main): Remove 'sframe-internal-only' hack.
binutils/testsuite/
* binutils-all/x86-64/sframe-func.s: Emit .eh_frame section as
well.
* binutils-all/x86-64/objdump-sframe-2.d: New test.
Simon Marchi [Fri, 6 Feb 2026 02:52:30 +0000 (21:52 -0500)]
gdb/block: remove block_iterator::d::block, remove union
The block union field is never used. The block is only used at
initialization time to grab a reference to the mdict, which is stored in
the mdict_iterator. There is no need to store the block in the iterator
itself for future use.
Remove it and remove the union. Leave the compunit_symtab field, whose
name unfortunately conflicts with the method.
Change-Id: I09dbc42f937eaba6c70598acca8ff355c4e5bdb9 Approved-By: Tom Tromey <tom@tromey.com> Tested-By: Guinevere Larsen <guinevere@redhat.com>
Simon Marchi [Thu, 5 Feb 2026 20:42:50 +0000 (15:42 -0500)]
gdb/testsuite: make gdb.dwarf2/dw2-empty-inline-ranges.exp work when ASLR can't be disabled
A colleague that goes by the name "Luis Machado" reported a failure when
running gdb.dwarf2/dw2-empty-inline-ranges.exp. After investigation, we
found that the conditions for the test to fail are:
- running in an environment where GDB can't disable address space
randomization (such as in a container where that capability is
removed)
- a toolchain generating position-independent executables
The test does a first run to grab the addresses of a few labels defined
in the source file. It then crafts the DWARF using these addresses.
And then it does a second run for the actual test stuff.
When the executable is PIE and ASLR is active, then the addresses in
both runs don't agree, which the test doesn't expect.
It is possible to emulate the failure by inserting some:
after both "prepare_for_testing" calls. The (first) failure then
manifests as:
FAIL: gdb.dwarf2/dw2-empty-inline-ranges.exp: dwarf_version=4: empty_loc=start: entry_pc_type=empty: stopped at entry-pc
This test compares the expected stop PC "entry_pc" with the actual stop
PC "pc". In my example run, they were indeed different:
pc = 0x5603ec67a159
entry_pc = 0x55baba6a9159
The simplest way to fix this, which this patch implements, is to use
"nopie" when building the binaries. I don't think this affects the
effectiveness of the test.
Also, in the first run, it is longer necessary to run the inferior
before grabbing the addresses, they are going to be the same with a
non-PIE executable. So remove that.
Change-Id: I3e9b1c056c30a49e01e1a1d3bf28f7e0e409f3c9 Approved-By: Andrew Burgess <aburgess@redhat.com>
Matthieu Longo [Mon, 2 Feb 2026 14:14:30 +0000 (14:14 +0000)]
aarch64: clean up subsection used to initialize the frozen attributes set
On AArch64, some attributes are set globally when software protections
options such as BTI, PAC or GCS are enabled. These attributes are then
used as the frozen set during the attributes merge.
In the current implementation of bfd_elfNN_aarch64_set_options, the
subsection is created before linker options are examined. If relevant
options are provided, the subsection is appended to the frozen set;
otherwise, it is left unused and leaked. This issue was detected by
LeakSanitizer (see the stack trace below).
This patch fixes the memory leak by handling the case where no attributes
are recorded. An 'else' is added to free the empty subsection when it is
not added to the frozen set.
Matthieu Longo [Mon, 2 Feb 2026 14:54:55 +0000 (14:54 +0000)]
bfd: fix memory leak when default-initializing an OAv2 attribute
To merge an OAv2 attribute, the input values must either be present in
the subsections being merged, or a default value must be created for the
missing ones. Note that this default value is not necessarily null.
In the current implementation of oav2_attr_default(), the default value
is created by copying another attribute provided as a template. As a
result, a string attribute may be copied from the template if it is not
NULL. The copied value is overwritten with whatever default the backend
provides for that attribute.
In oav2_attr_overwrite_with_default(), when no default attribute value
is found in the backend, a string attribute is simply assigned NULL.
This ignores the possibility that the original value may be non-NULL,
and causes the previously allocated memory for the string to be leaked.
This issue was detected by the LeakSanitizer (see the relevant part of
the stack trace below).
This patch fixes the memory leak by freeing the existing value before
assigning NULL to the attribute.
==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 5 byte(s) in 1 object(s) allocated from:
#2 xstrdup ../../libiberty/xstrdup.c:34
#3 _bfd_elf_obj_attr_v2_copy ../../bfd/elf-attrs.c:3185
#4 oav2_attr_default ../../bfd/elf-attrs.c:1109
#5 handle_optional_subsection_merge ../../bfd/elf-attrs.c:1558
Matthieu Longo [Mon, 2 Feb 2026 14:40:22 +0000 (14:40 +0000)]
bfd: fix memory leak when assigning the merge result of OAv2 string attributes
oav2_attr_merge() merges input OAv2 attributes and returns a merge result,
which is then assigned to the previous value held by REF.
In the current implementation of handle_optional_subsection_merge(), when
merging string attributes, the existing value is overwritten without first
being freed. This results in a memory leak. This issue was detected by
LeakSanitizer (see the relevant stack trace below).
This patch fixes the memory leak by wrapping the assignment of the merge
result to REF inside a helper function. For string attributes, the helper
frees the previous value before performing the assignment. This approach
also centralizes the logic and makes easier to correctly free and assign
more complex structures in the future, if needed.
Matthieu Longo [Fri, 30 Jan 2026 11:20:02 +0000 (11:20 +0000)]
Object Attributes v2: clean up attributes data when freeing BFDs
Once attributes merge is complete, object attributes from input files
are no longer needed and can be safely released. The same applies to
object attributes associated to the output object. Ideally, a single
clean-up mechanism should handle both inputs and output cases. GNU ld
already provides such a mechanism via _bfd_elf_free_cached_info().
The previous patch series that introduced support for Object Attributes
v2 did not free any OAv2 data, resulting in leaks of all OAv2-related
resources.
This patch adds a new helper, _bfd_elf_cleanup_object_attributes, to
the OAv2 API to deallocate all OAv2 resources associated with a BFD.
The helper is invoked from _bfd_elf_free_cached_info().
The patch also fixes a logical error after the attributes merge, where
object attributes were copied from the accumulator into output_bfd. A
simple pointer copy is insufficient because ownership of the wrapper
must be fully swapped between the two BFDs to ensure resources are
deallocated correctly.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33858 Co-authored-by: Alan Modra <amodra@gmail.com>
Jan Beulich [Fri, 6 Feb 2026 07:52:29 +0000 (08:52 +0100)]
gas: drop pointless tc_fix_adjustable()
Instances yielding constant 1 / true are meaningless, as that's write.c's
default anyway. In KVX also drop TC_FIX_ADJUSTABLE(), which had no user
already when KVX support was first introduced. Since the comment mentions
them: Linkonce sections are taken care of in write.c.
Jan Beulich [Fri, 6 Feb 2026 07:52:02 +0000 (08:52 +0100)]
ld: fold .note.GNU-stack during relocatable linking
PR ld/33851
While in all binutils components we've switched the section to be of
SHT_NOTE type, assembly sources as well as other tools may still generate
SHT_PROGBITS instances. When doing relocatable links, input sections with
differing types would cause multiple output sections to be created, which
some tools choke upon. Fold incoming sections into a single one, the type
of which will be the type of the first section encountered.
David Faust [Wed, 4 Feb 2026 21:53:34 +0000 (13:53 -0800)]
bpf: add may_goto instruction [PR32176]
The BPF "may_goto" instruction is a special sort of conditional jump
where the condition is determined by the BPF runtime. That is, it is
a no-op until the runtime decides otherwise.
For normal asm syntax, the mnemonic "jcond" is chosen in keeping with
the style of following the opcode definitions in the Linux kernel uapi
BPF headers.
This instruction is not currently emitted by GCC, but it can be inserted
into BPF programs via macros defined in the Linux kernel.
The compunit_symtab::includes field says that it contains the flattened
list of all recursively included symtabs:
/* Vector of included compunit symtabs. When searching the static or global
block of this compunit, the corresponding block of all
included compunits will also be searched. Note that this
list must be flattened -- the symbol reader is responsible for
ensuring that this vector contains the transitive closure of all
included compunits. */
std::vector<compunit_symtab *> includes;
The DWARF reader appears to do exactly that, see
recursively_compute_inclusions.
It therefore seems unnecessary to do a recursive search, in
recursively_find_pc_sect_compunit_symtab, it will search some symtabs
multiple times. I confirmed this by hacking the function to print the
searched CUs and to never find anything:
for (compunit_symtab *include : cust->includes)
if (compunit_symtab *found
And then:
$ ./gdb -nx --data-directory=data-directory ~/build/babeltrace/src/lib/.libs/libbabeltrace2.so.0.0.0 -ex "p bt_common_assert_failed" -batch | grep 'Search CU' | sort | uniq -c
1 Search CU 0x7c83249e44b0
1 Search CU 0x7c83249e4690
1 Search CU 0x7c83249e4870
1 Search CU 0x7c83249e4960
1 Search CU 0x7c83249e4b40
1 Search CU 0x7c83249e4d20
1 Search CU 0x7c83249e4f00
2 Search CU 0x7c83249e4ff0
2 Search CU 0x7c83249e50e0
4 Search CU 0x7c83249e51d0
2 Search CU 0x7c83249e52c0
2 Search CU 0x7c83249e53b0
4 Search CU 0x7c83249e54a0
Change recursively_find_pc_sect_compunit_symtab to only search the
flattened list, and rename it accordingly.
With the patch, the same hack (putting the print in the "is_the_one"
lambda) and command as above shows that all CUs are searched exactly
once:
1 Search CU 0x7cc78ffe44b0
1 Search CU 0x7cc78ffe4690
1 Search CU 0x7cc78ffe4870
1 Search CU 0x7cc78ffe4960
1 Search CU 0x7cc78ffe4b40
1 Search CU 0x7cc78ffe4d20
1 Search CU 0x7cc78ffe4f00
1 Search CU 0x7cc78ffe4ff0
1 Search CU 0x7cc78ffe50e0
1 Search CU 0x7cc78ffe51d0
1 Search CU 0x7cc78ffe52c0
1 Search CU 0x7cc78ffe53b0
1 Search CU 0x7cc78ffe54a0
I am not sure how blockvectors work exactly, whether the blockvector of
the includer CU is a superset of the blockvectors of the includees. I
ask that because it seems like in practice, the requested PC always
seems to be found in the first searched CU. I haven't investigated this
point more than that though.
Simon Marchi [Fri, 30 Jan 2026 02:55:27 +0000 (21:55 -0500)]
gdb/symtab: make compunit_symtab::includes a std::vector
Since compunit_symtab is now a properly constructed and destructed
object, we can use fancy C++ things in it. Change the includes field to
be an std::vector.
Previously, the includes list was NULL-terminated. I went through all
users and I'm pretty sure that none of them rely on it being
NULL-terminated anymore.
Change-Id: Ie68a8dc0f227fd49c291d85c3e8e020463e9d0d4 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Fri, 30 Jan 2026 02:55:26 +0000 (21:55 -0500)]
gdb/block: make find_iterator_compunit_symtab a method of block_iterator
I noticed some code in bkscm_print_block_syms_progress_smob peeking a
bit in the implementation details of block_iterator, and doing
essentially the same thing as the existing static function
find_iterator_compunit_symtab.
Change find_iterator_compunit_symtab to become
block_iterator::compunit_symtab, and use it in
bkscm_print_block_syms_progress_smob.
Change-Id: I344a2155a2edb5d278e98684c71f1ee161e8d1d4 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Sat, 24 Jan 2026 05:15:00 +0000 (00:15 -0500)]
gdb/amd-dbgapi: add basic watchpoint support
Add basic watchpoint support for the amd-dbgapi target. This means
placing write watchpoints on globally addressable memory. More
complexity will come eventually to allow placing watchpoints on the
various other address spaces, but that will require adding proper
support for non-default address spaces first.
Implementation
--------------
I think the implementation is not too surprising, just adding the
required target methods. But there are some things worthy of mention:
- amd-dbgapi does not support read watchpoints. If the core attempts
to insert a read (or access, which means read/write) watchpoint,
amd_dbgapi_target::insert_watchpoint returns an error.
If we silently let the beneath target (linux-nat) install the read
watchpoint, it would be potentially confusing. Everything would look
fine to the user, but a read from the GPU would not be caught, so it
would look like the watchpoint doesn't work.
There is a loophole though: read watchpoints created before the
runtime is loaded (and therefore the amd-dbgapi target is pushed)
will still be inserted. Only when execution stops, and the user
tries to resume again, will the check in
amd_dbgapi_target::insert_watchpoint be hit.
Another option would be to allow the host read watchpoint to go
through, but warn that the reads from the AMD GPU device will not be
watched. We would need to be smart to avoid flooding the user with
warnings. But I decided to upstream the current ROCgdb behavior
first, we can always change it later.
- When the amd-dbgapi target gets pushed, we create amd-dbgapi
watchpoints for any existing hardware write watchpoint location.
- When the core asks the target to insert a watchpoint, we ask the
target beneath to insert it first. If the beneath target fails, we
return immediately with an error.
- When the core asks to remove a watchpoint, we ask the target beneath
to to remove it first. Even if it fails, we still try to remove the
amd-dbgapi watchpoint.
- When stopping after a watchpoint hit while the "precise-memory"
setting is not enabled, it is possible for the wave to stop a few
instructions later than the instruction that made the write that
triggered the watchpoint. We print a warning in that case, similar
to what we do when a memory violation happens while "precis-memory"
is disabled.
Testing
-------
- Tests precise-memory-warning-watchpoint.exp and
watchpoint-at-end-of-shader.exp are more or less brought as-is from
downstream ROCgdb. I modified precise-memory-warning-watchpoint.exp
to watch a hipMalloc'ed region instead of a `__device__` global
variable. The latter doesn't work upstream, because we don't yet
support the DWARF constructs that describe the variable location.
- I added test watchpoint-basic.exp with various simple cases to
exercises different code paths added by this patch.
Differences from downstream ROCgdb
----------------------------------
While extracting this code from ROCgdb, I made a few minor but possibly
significant (read: erroneous) changes. Those should be reviewed
carefully. I think that some code in ROCgdb was written at a time where
the amd-dbgapi target was always pushed at the very start of the
inferior execution, so assumptions were different.
- The value type for the `amd_dbgapi_inferior_info::watchpoint_map` map
is now a structure, instead of an std::pair, just because it makes
the code more readable.
- The insert_watchpoint and remove_watchpoint methods (and perhaps
others) now assume that if they are called, the runtime is in the
"enabled" state.
- insert_initial_watchpoints has one more check (loc->owner->type !=
bp_hardware_watchpoint), to filter out non-write watchpoints.
Otherwise, I think that we could mistakenly insert some write
watchpoints for some pre-existing read watchpoints.
- Because it is possible for read watchpoints to be created before the
target is pushed, remove_watchpoint returns early if it sees that the
code asks for the removal of a read watchpoint, instead of asserting
"type == hw_write" (this was caught by the new test).
The first half of this condition should always be true, due to how
std::upper_bound works.
For the second part: if the watchpoint was created successfully, it
is because it did fully cover the requested region (see
insert_one_watchpoint). I don't see why the core would ask us to
remove a watchpoint that wasn't successfully inserted. I am not 100%
sure about that one, there might be some edge cases where this is not
true.
- I changed a manual free in stopped_by_watchpoint to a
gdb::unique_xmalloc_ptr, even though it changes nothing functionally.
- I merged some conditions in amd_dbgapi_target_normal_stop.
Change-Id: Ia15fb7434dc0c142a5a32997ada2e3a163c89f98 Approved-by: Lancelot Six <lancelot.six@amd.com> Co-Authored-By: Laurent Morichetti <laurent.morichetti@amd.com>
Nick Clifton [Thu, 5 Feb 2026 16:17:59 +0000 (16:17 +0000)]
Objdump: New feature display of global variable info based on DWARF info section
Adds the new option --map-global-vars to objdump. This displays the type and location of global files in binaries that contain suiteable debug information.
Indu Bhagat [Wed, 4 Feb 2026 22:56:58 +0000 (14:56 -0800)]
bfd: sframe: use better wording for error messages
Fix PR ld/33849.
Change the messages to display the owner BFD, together with the section
name. E.g., when mixing SFrame V2 and V3, the linker will now emit
something like:
error in test.o (.sframe); unexpected SFrame format version 2
Alan Modra [Wed, 4 Feb 2026 22:04:31 +0000 (08:34 +1030)]
PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries
elfNN_aarch64_plt_sym_val wrongly treats PIEs. PIEs are an executable
but not ET_EXEC, instead being ET_DYN with DF_1_PIE set in DT_FLAGS_1
to distinguish them from shared libraries.
get_plt_type scans .dynamic for DT_AARCH64_BTI_PLT and
DT_AARCH64_PAC_PLT, setting PLT_BTI and PLT_PAC in the function return
value respectively. It's easy enough to extend the .dynamic scan to
also return DF_1_PIE in tdata is_pie.
The patch also makes a few tidies, things I noticed when scanning all
the code dealing with sw_protections.plt_type.
PR 33593
* elfnn-aarch64.c (get_plt_type): Return DF_1_PIE via tdata is_pie.
(elfNN_aarch64_plt_sym_val): Handle PIEs as well as ET_EXEC.
(setup_plt_values): Delete wrong ET_EXEC comments.
(elfNN_aarch64_late_size_sections): Remove excess parentheses.
(elfNN_aarch64_finish_dynamic_sections): Rename type to plt_type,
and simplify test for PLT_BTI or PLT_BTI_PAC.
Tom Tromey [Tue, 3 Feb 2026 20:03:45 +0000 (13:03 -0700)]
Add null check for character type name
The internal AdaCore test suite found that
wchar_printer::get_default_encoding checks the name of a type without
first seeing if the name is null:
else if (streq (chtype->name (), "wchar_t"))
Mysteriously, though, this only seems to happen for certain targets
and perhaps only under certain conditions (I couldn't reproduce it
msyelf).
I felt that the fix is fairly obvious and that this isn't really worth
writing a test for. However I can write one using the DWARF assembler
if someone feels it is worthwhile.
The previous commit fixed an issue where BFD was failing to parse the
NT_PRSTATUS notes in a core file. As a result of this the general
purpose registers were not available to GDB, and as a result GDB would
not add any threads to the inferior when opening a core file.
As GDB requires each inferior to have at least one thread, there is
code in GDB to handle this no-registers case, and add a dummy thread
to the inferior. However, a bug in this code was causing GDB to
crash. It is this crash that the above commit fixed.
This commit adds a test for this fix.
The test contains a Python script which adds a new Python command to
GDB. This Python command can be used to modify an on-disk core file.
The command opens the core file, locates the notes segments, and then
looks through the notes to find NT_PRSTATUS notes. The type value for
these NT_PRSTATUS notes is then changed to a value that GDB doesn't
understand (0xffffffff).
Now when GDB opens the core file the NT_PRSTATUS are no longer
NT_PRSTATUS notes; the core file will appear to have no such notes,
and the previous bug will be triggered.
Running this new test with GDB 16 will trigger the crash. With
current HEAD of master, which includes the above commit, this test
should pass.
I originally wrote the Python script in this test as a standalone
Python script, not as a GDB command, but some of the gcc compiler farm
test machines still have Python 2 as the default. This means that the
corefile-no-threads.exp script would have to figure out which Python
executable to use to run the script.
Much easier to just use GDB's builtin Python interpreter. We know
that this will be at least Python 3.4 (GDB's minimum Python
requirement).
I've tested this on x86-64 in 64-bit and 32-bit mode. And on a big
endian PPC64 machine.
Matthieu Longo [Fri, 30 Jan 2026 18:12:20 +0000 (18:12 +0000)]
aarch64: fix buffer overflow in aarch64-gen
A refactoring in [1] introduced a buffer overflow. A new enum value,
last_iclass, was added at the end of 'enum aarch64_insn_class' to
refer to the last instruction class. This value is then used to size
the array iclass_has_subclasses_p, which is intended to have one
element per enum value.
However, because the enum values start at index 0, last_iclass is
off by one when used as the array length. As a result, the array is
allocated with element too few, leading to a buffer overflow when
accessing the 'lut' class.
The fix adds +1 to last_iclass when defining the array size.
==ERROR: AddressSanitizer: global-buffer-overflow
READ of size 1 at 0x5555556d8d5d thread T0
#0 0x5555555c918d in read_table ./opcodes/aarch64-gen.c:207
#1 0x5555555ca0d1 in initialize_decoder_tree ./opcodes/aarch64-gen.c:435
#2 0x5555555ceaa6 in main ./opcodes/aarch64-gen.c:1386
Andrew Burgess [Thu, 27 Mar 2025 10:53:43 +0000 (10:53 +0000)]
gdb: fix-up truncated inline function block ranges
This commit aims to improve GDB's handling of inline functions. There
are two mechanisms which can tell GDB, or the user of GDB, that the
inferior is within an inline function, these are the block range
associated with an inline instance of a function, and also the line
table, which associates addresses with source lines in the program.
Currently, gcc truncates the address range for, at least some, inline
function blocks, such that a given address is considered outside the
inline function. However, the line table maps that same address to a
line within the inline function.
A consequence of this, is that, when using 'next' to move the inferior
forward, GDB will often stop the inferior believing that the inferior
has left an inline function, and indeed, GDB will claim that the
inferior is in the outer, non-inline function, but GDB will then
display a source line from the inline function as the current location.
An example of this problem can be seen with the test
gdb.cp/step-and-next-inline.exp. Using the
step-and-next-inline-no-header binary that is built as part of the
test:
(gdb) file ./gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header
Reading symbols from ./gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header...
(gdb) break get_alias_set
Breakpoint 1 at 0x401160: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc, line 51.
(gdb) run
Starting program: /tmp/build/gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header
Breakpoint 1, get_alias_set (t=t@entry=0x404038 <xx>)
at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:51
51 if (t != NULL
(gdb) next
52 && TREE_TYPE (t).z != 1
(gdb) next
43 return x; <------------- Problem line.
(gdb) bt
#0 get_alias_set (t=t@entry=0x404038 <xx>) at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:43
#1 0x000000000040105e in main () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:64
(gdb)
I've labelled the issue as 'Problem line'. After the second 'next'
GDB stopped thinking it was in get_alias_set, but printed a line from
the inline function behind the TREE_TYPE macro. The 'Problem line'
should have been line 53, not line 43.
The $pc at which GDB stopped is 0x40116f. If we then use 'objdump
--dwarf=decodedline' to view the line table for the executable, this
is what we see:
File name Line number Starting address View Stmt
...
step-and-next-inline.cc 38 0x401165 x
step-and-next-inline.cc 40 0x401165 1 x
step-and-next-inline.cc 40 0x401165 2
step-and-next-inline.cc 40 0x401167
step-and-next-inline.cc 42 0x40116f x
step-and-next-inline.cc 43 0x40116f 1 x
step-and-next-inline.cc 43 0x40116f 2
step-and-next-inline.cc 52 0x40116f 3
step-and-next-inline.cc 52 0x401172
step-and-next-inline.cc 38 0x401177 x
step-and-next-inline.cc 40 0x401177 1 x
step-and-next-inline.cc 40 0x401177 2
...
NOTE: I use objdump to view the line table, not 'maintenance info
line-table' as GDB drops some line table entries that it sees as
irrelevant. Using objdump give a complete view of the line table.
We can see that address 0x40116f is associated with three line
numbers, 42, and 43 are both within the inline function, and 52 is the
line from which the inline function was called. Notice too that 52 is
a non-statement line.
If we now look at the block structure for the previous $pc
value 0x40116e (i.e. $pc - 1), then we see this:
Here we see 'tree_check', the inline function that backs the TREE_TYPE
macro, this is the inline function we have just stepped out of. This
makes sense as the end-address for the tree_check block is 0x40116f,
and as the block's end address is not inclusive, that means that
0x40116f is the first address outside the block, which, is the current
$pc value.
And so, we can see what's going on. When the 'next' starts GDB is in
get_alias_set, GDB steps forward, entering tree_check. GDB then uses
the extent of the block to figure out where the inline function ends,
and steps forward to that address (0x40116f). At this point, GDB
looks up the current line in the line table (43), and reports a stop
at this line.
In this commit, the fix I propose is to look for the line table
pattern seen above, a sequence of line table entries, that end with a
non-statement entry for the calling line of an inline function,
located at the exact end address of an inline function block.
When such a pattern is found, then we can extend the inline function's
address range to the next line table address, so long as doing so does
not extend the inline function beyond the extent of the containing,
non-inline, function.
In the above example, the block for the tree_check function would be
extended to end at 0x401172. With this fix in place, and with the
same test binary, GDB now behaves like this:
(gdb) break get_alias_set
Breakpoint 1 at 0x401160: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc, line 51.
(gdb) run
Starting program: /tmp/build/gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header
Breakpoint 1, get_alias_set (t=t@entry=0x404038 <xx>)
at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:51
51 if (t != NULL
(gdb) next
52 && TREE_TYPE (t).z != 1
(gdb) next
53 && TREE_TYPE (t).z != 2
(gdb)
The block for the inline function has been updated, like this:
This original patch series from Bernd Edlinger contains a number of
different fixes, some have already been split out and merged into GDB,
but the core idea for how to improve inline function handling by
extending the inline block range is the same, however, the mechanism
Bernd uses is significantly different.
In the above series, the approach taken is to mark the line table at
the end address of an inline function, and a few addresses beyond
that (see the is-weak flag in the above series). Then, when looking
up the block for a given address, if the address is within this marked
region, then we actually return the previous (inline function) block.
I believe that the above is a fair high-level summary of how the above
patch solves the inline function range problem. Any differences are
down to my misunderstanding the above patch, for which I apologise.
My problem with the above patch is that it breaks what I think should
be an invariant of GDB, that when looking up a block for a given
address, the block returned must contain the address within its
ranges. I feel that, if we start to break this invariant, then we
risk introducing bugs within, e.g. the stepping control code.
In contrast, my approach solves this problem during the DWARF parsing,
where problem cases are identified, and the DWARF "fixed" by extending
the block ranges. After this, no additional changes are needed in
GDB, the address to block mapping can work as normal, and the stepping
logic can continue to work just as it always has.
The test changes for gdb.cp/step-and-next-inline.exp have been taken
from Bernd's original patch series, and I've added a Co-Author tag for
Bernd to reflect this, as well as for the inspiration that I took from
his original series when creating this alternative proposal.
If/when this patch is merged, I plan to follow up with some cleanup to
the test case gdb.cp/step-and-next-inline.exp. I think this test
should really be moved to gdb.opt/, it's really testing optimisation
debug, not C++ features, but also the structure of the test file is a
bit of a mess. I think with some restructuring we could make the test
more readable, and also, maybe, test some additional compiler
flags (e.g. more optimisation levels). I've not done the refactoring
in this patch in order to make it clearer what new tests I've added,
and also, I want to leave the test similar to what's in Bernd's
original series, to make comparison easier.
The gdb.cp/step-and-next-inline.exp test was originally added by me
back in 2019, so the problems with it are of my own making.
For testing I've obviously run the entire test suite, but of
particular interest are these tests:
I've run these tests with a range of different gcc versions: 9.5.0,
10.5.0, 11.5.0, 12.2.0, 13.3.0, 14.2.0, 15.1.0. These tests all
relate to optimised debug of inline functions, and all passed with all
compiler versions listed here.
Andrew Burgess [Thu, 20 Mar 2025 11:07:02 +0000 (11:07 +0000)]
gdb: record block end addresses while parsing DIEs
Continuing to work towards the goal of improving GDB's ability to
debug optimised code, this commit stores a map from the end address
of a block (or a block's sub-range) to the block pointer. This
information is collected while parsing the DIEs.
This new map is required as a consequence of the previous commit. The
optimised code fix ups require that we can map from an address back to
a block, something that the address map was perfect for, but the
previous commit deferred building the address map until later on.
The problem is that the optimised code fixes in the next commit
require the address to block map, but also adjust block ranges, which
invalidates the address to block map. We could try to build the full
address to block early on, and then update it as the optimised code
fixes are performed, but this is expensive.
The solution I propose is to build a light weight, partial map, that
only holds the interesting (inline) blocks. This partial map is only
needed between reading the DIE and applying the optimised code fixes,
after which it is done with, and as a consequence we don't need to
update this map as the optimised code fixes adjust block ranges, this
makes the partial map cheaper.
This commit is all about building the new partial map. Currently,
nothing is done with this information; the information is recorded as
the block ranges are parsed, and then discarded after the line table
has been built. But in the next commit, this will be used to help
adjust the ranges of some inline blocks, and this will improve GDB's
ability to debug optimised code.
There should be no user visible changes after this commit.
Andrew Burgess [Mon, 5 Jan 2026 13:44:59 +0000 (13:44 +0000)]
gdb: remove buildsym_compunit::record_block_range
After the last commit I realised that the function
buildsym_compunit::record_block_range is not really needed any more.
This function is basically checking for non-contiguous blocks, and
setting m_pending_addrmap_interesting when a non-contiguous block is
seen.
We can move this check into buildsym_compunit::make_blockvector which
is the only place m_pending_addrmap_interesting is used, we already
loop over all blocks in this function.
This allows us to remove record_block_range and
m_pending_addrmap_interesting from buildsym_compunit.
There is one weird thing in this patch, in dwarf2/read.c, the function
dwarf2_record_single_block_range is now empty, but I've retained this
function. A later patch in this series adds some code back into this
function, so I don't want to delete it here.
Andrew Burgess [Thu, 26 Jun 2025 10:38:53 +0000 (11:38 +0100)]
gdb: create address map after parsing all DIE
Continuing the work done in the last two commits, this commit defers
building the addrmap for a blockvector until after all the DIE have
been read, and the line table processed.
The benefit of this is that any changes to a block's ranges done
during line table processing (see the next commit) will be reflected
in the blockvector's addrmap.
The alternative to this is to build the addrmap as we initially see
each block, but then adjust the addrmap if we later decide to modify a
block. I think deferring the addrmap creation is cleaner, and is less
work overall.
The addrmap requires that we add the innermost blocks first. I
achieve this by walking the blockvector backward, as we always add
parent blocks before their more inner child blocks.
However, the blocks are not added to the blockvector in exactly the
same order as we recorded them before this patch. The key difference
here is that sibling blocks might not appear in the block vector in
the same order as we parsed them from the DWARF.
So long as sibling blocks don't overlap, this shouldn't make any
difference to the final addrmap that is constructed. But if the
sibling blocks do overlap, then there might be an observable change in
behaviour after this patch. But it is not clear to me how critical
this change actually is. As far as I can tell from my experiments, if
two siblings overlap then, for the overlap region, GDB is only able to
find information (e.g. local variables) from one sibling. This is
true before and after this patch, but which sibling is found might
change.
Andrew Burgess [Thu, 20 Mar 2025 10:46:31 +0000 (10:46 +0000)]
gdb: move block range recording into its own function
Like the previous commit, this is a refactor that makes a later commit
in this series easier. The later commit improves GDB's ability to
debug optimised code. To do this I propose to "fix" the address
ranges of some inline blocks.
In order to know which blocks to fix, I need to record the end address
of inline blocks.
And so, I'd like to create a single common function where block ranges
are recorded, in a later commit I can then hook into this function to
record the block's end address(es). This commit sets up this single
common function.
The new function I'm adding dwarf2_record_single_block_range, takes a
currently unused argument unrel_high. This argument will be needed in
the later commit. I've added it now as this will allow the later
commit to be smaller and more focused. I only plan to push this
commit as part of the larger series, so I don't think adding
the (currently) unused argument is too much of a problem.
There should be no user visible change after this commit.
Andrew Burgess [Mon, 17 Mar 2025 15:41:25 +0000 (15:41 +0000)]
gdb: split dwarf line table parsing in two
A later commit in this series, that improves GDB's ability to debug
optimised code, wants to use the line table information in order to
"fix" inline blocks with a truncated address range. For the reasoning
behind wanting to do that, please read ahead in the series.
Assuming that we accept for now the need to use the line table
information to adjust the block ranges, then why is this commit
needed?
GDB splits the line table data info different symtabs, adding end of
sequence markers as we move between symtabs. This seems to work fine
for GDB, but causes a problem for me in this case.
What I will want to do is this: scan the line table and spot line
table entries that corresponds to the end addresses of an inline
block's address range. If the block meets certain requirements, then
the end address of the block is adjusted to be that of the next line
table entry.
The way that GDB currently splits the line table entries between
symtabs makes this harder. I will have the set of blocks end
addresses which I know might be fixable, but to find the line table
entry corresponding to that address requires searching through all the
symtabs. Having found the entry for the end address, I then need to
find the next line table entry. For some blocks this is easy, it's
the next entry in the same symtab. But for other blocks the next
entry might be in a different symtab, which requires yet another full
search.
I did try implementing this approach, but the number of full symtab
searches is significant, and it had a significant impact on GDB's
debug parsing performance. The impact was such that an operation that
currently takes ~7seconds would take ~3minutes or more. Now I could
possibly improve that 3 minutes figure by optimising the code some,
but I think that would add unnecessary complexity.
By deferring building the line table until after we have parsed the
DIEs it becomes simple to spot when a line table entry corresponds to
a block end address, and finding the next entry is always trivial, as,
at this point, the next entry is just the next entry which we will
process. With this approach I see no noticable impact on DWARF
parsing performance.
This patch is just the refactoring. There's no finding block end
addresses and "fixing" being done here. This just sets things up for
the later commits.
The existing code has a single function handle_DW_AT_stmt_list which
loads the line table header and then calls dwarf_decode_lines to
decode the line table itself, splitting the line table entries between
symtabs.
After this commit handle_DW_AT_stmt_list is renamed to
decode_line_header_for_cu, this loads the line table header and
creates the symtabs based off the line table, but doesn't process the
line table. The dwarf_decode_lines function is no longer called at
this point.
In read_file_scope is where dwarf_decode_lines is now called. This
relies on the line table having been loaded earlier, and processes the
line table entries, splitting them between symtabs.
There should be no user visible changes after this commit.
That series has the fixes here merged along with other changes, and
takes a different approach for how to handle the issue addressed here.
Credit for identifying the original issue belongs with Bernd, the
author of the original patch, who I have included as a co-author on
this patch. A brief description of how the approach taken in this
patch differs from the approach Bernd took can be found at the end of
this commit message.
When compiling with optimisation, it can often happen that gcc will
emit an inline function instance with an empty range associated. This
can happen in two ways. The inline function might have a DW_AT_low_pc
and DW_AT_high_pc, where the high-pc is an offset from the low-pc, but
the high-pc offset is given as 0 by gcc.
Alternatively, the inline function might have a DW_AT_ranges, and one
of the sub-ranges might be empty, though usually in this case, other
ranges will be non-empty.
The second case is made worse in that sometimes gcc will specify a
DW_AT_entry_pc value which points to the address of the empty
sub-range.
My understanding of the DWARF spec is that empty ranges as seen in
these examples indicate that no instructions are associated with the
inline function, and indeed, this is how GDB handles these cases,
rejecting blocks and sub-ranges which are empty.
DWARF-5, 2.17.2, Contiguous Address Range:
The value of the DW_AT_low_pc attribute is the address of the
first instruction associated with the entity. If the value of the
DW_AT_high_pc is of class address, it is the address of the first
location past the last instruction associated with the entity...
DWARF-5, 2.17.3, Non-Contiguous Address Ranges:
A bounded range entry whose beginning and ending address offsets
are equal (including zero) indicates an empty range and may be
ignored.
As a consequence, an attempt by the user to place a breakpoint on an
inline function with an empty low/high address range will trigger
GDB's pending breakpoint message:
(gdb) b foo
Function "foo" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
While, having the entry-pc point at an empty range forces GDB to
ignore the given entry-pc and select a suitable alternative.
If instead of ignoring these empty ranges, we instead teach GDB to
treat these as non-empty, what we find is that, in all the cases I've
seen, the debug experience is improved.
As a minimum, in the low/high case, GDB now knows about the inline
function, and can place breakpoints that will be hit. Further, in
most cases, local variables from the inline function can be accessed.
If we do start treating empty address ranges as non-empty then we are
deviating from the DWARF spec. It is not clear if we are working
around a gcc bug (I suspect so), or if gcc actually considers the
inline function gone, and we're just getting lucky that the debug
experience seems improved.
My proposed strategy for handling these empty address ranges is to
only perform this work around if the compiler is gcc, so far I've not
seen this issue with Clang (the only other compiler I've tested),
though extending this to other compilers in the future would be
trivial.
Additionally, I only apply the work around for
DW_TAG_inlined_subroutine DIEs, as I've only seen the issue for
inline functions.
If we find a suitable empty address range then the fix-up is to give
the address range a length of 1 byte.
Now clearly, in most cases, 1 byte isn't even going to cover a single
instruction, but so far this doesn't seem to be a problem. An
alternative to using a 1-byte range would be to try and disassemble
the code at the given address, calculate the instruction length, and
use that, the length of one instruction. But this means that the
DWARF parser now needs to make use of the disassembler, which feels
like a big change that I'd rather avoid if possible.
The other alternative is to allow blocks to be created with zero
length address ranges and then change the rest of GDB to allow for
lookup of zero sized blocks to succeed. This is the approach taken by
the original patch series that I linked above.
The results achieved by the original patch are impressive, and Bernd,
the original patch author, makes a good argument that at least some of
the problems relating to empty ranges are a result of deficiencies in
the DWARF specification rather than issues with gcc.
However, I remain unconvinced. But even if I accept that the issue is
with DWARF itself rather than gcc, the question still remains; should
we fix the problem by synthesising new DWARF attributes and/or accept
non-standard DWARF during the dwarf2/read.c phase, and then update GDB
to handle the new reality, or should we modify the incoming DWARF as
we read it to make it fit GDB's existing algorithms.
The original patch, I believe, took the former approach, while I
favour the later, and so, for now, I propose that the single byte
range proposal is good enough, at least until we find counter examples
where this doesn't work.
This leaves just one question: what about the remaining work in the
original patch. That work deals with problems around the end address
of non-empty ranges. The original patch handled that case using the
same algorithm changes, which is neat, but I think there are
alternative solutions that should be investigated. If the
alternatives don't end up working out, then it's trivial to revert
this patch in the future and adopt the original proposal.
For testing I have two approaches, C/C++ test compiled with
optimisation that show the problems discussed. These are good because
they show that these issues do crop up in compiled code. But they are
bad in that the next compiler version might change the way the test is
optimised such that the problem no longer shows.
And so I've backed up the real code tests with DWARF assembler tests
which reproduce each issue.
The DWARF assembler tests are not really impacted by which gcc version
is used, but I've run all of these tests using gcc versions 8.4.0,
9.5.0, 10.5.0, 11.5.0, 12.2.0, and 14.2.0. I see failures in all of
the new tests when using an unpatched GDB, and no failures when using
a patched GDB.
Alan Modra [Tue, 3 Feb 2026 21:01:26 +0000 (07:31 +1030)]
objdump -d with -j and objdump disassembly of .plt
objdump -D disassembles non-code sections, paying no heed to symbols
in those sections. I think "objdump -d -j .data" should do the same,
ie. not switch into dumping the section as data because an object
symbol is encountered.
On the other hand, dissassembly of .plt which is a code section, can
dump the first part of .plt as data due to the presense of
_PROCEDURE_LINKAGE_TABLE_. Fix that too.
Alan Modra [Tue, 3 Feb 2026 20:22:55 +0000 (06:52 +1030)]
ctf_dump_objts output string
"Section is indexed" and "No symbol table" are generated at the
beginning of ctf_dump_objts but not output, resulting in an asan
complaint about leaked memory. Clearly the messages should either not
be generated, or they should be output. I chose to do the latter in
this patch, which requires some testsuite adjustment.
libctf/
* ctf-dump.c (ctf_dump_objts): Output "Section is indexed" and
"No symbol table" strings, enclosed in parentheses and
indented.
ld/
* testsuite/ld-ctf/data-func-conflicted-vars.d: Update.
* testsuite/ld-ctf/data-func-conflicted.d: Update.
Tom de Vries [Tue, 3 Feb 2026 16:45:38 +0000 (17:45 +0100)]
[pre-commit] Require pre-commit v4.5.1
In December 2025, pre-commit v4.5.1 was released. We currently require v3.2.0
(released in March 2023), or later.
It occurred to me that allowing such a large range of releases might lead to
developers experiencing different behaviors, perhaps running into bugs that
are already fixed in later releases.
Fix this by requiring the latest release, v4.5.1.
The drawback is that we now require a more recent python: v3.10.
[ In more detail, pre-commit requires:
- at v3.2.0, python 3.8
- since v3.6.0, python 3.9
- since v4.4.0, python 3.10. ]
Tested on x86_64-linux, python 3.13.11 by doing "pre-commit run --all-files".