Age | Commit message (Collapse) | Author | Files | Lines |
|
While working on another patch which changes how we parse the line
DWARF line tables I noticed what I think is a minor bug in how we
process the line tables.
What I noticed is that my new line table parser was adding more END
markers into the parsed table than GDB's current approach. This
difference was observed when processing the debug information for
libstdc++.
Here is the line table from the new test, this is a reasonable
reproduction of the problem case that I observed in the actual debug
line table:
Contents of the .debug_line section:
dw2-skipped-line-entries-1.c:
File name Line number Starting address View Stmt
dw2-skipped-line-entries-1.c 101 0x40110a x
/tmp/dw2-skipped-line-entries-2.c:
dw2-skipped-line-entries-2.c 201 0x401114 x
/tmp/dw2-skipped-line-entries-3.c:
dw2-skipped-line-entries-3.c 301 0x40111e x
/tmp/dw2-skipped-line-entries-1.c:
dw2-skipped-line-entries-1.c 102 0x401128 x
dw2-skipped-line-entries-1.c 103 0x401128 x
dw2-skipped-line-entries-1.c 104 0x401128 x
/tmp/dw2-skipped-line-entries-2.c:
dw2-skipped-line-entries-2.c 211 0x401128
/tmp/dw2-skipped-line-entries-3.c:
dw2-skipped-line-entries-3.c 311 0x401132
/tmp/dw2-skipped-line-entries-1.c:
dw2-skipped-line-entries-1.c 104 0x40113c
dw2-skipped-line-entries-1.c 105 0x401146 x
dw2-skipped-line-entries-1.c - 0x401150
The problem is caused by the entry for line 211. Notice that this
entry is at the same address as the previous entries. Further, the
entry for 211 is a non-statement entry, while the previous entries are
statement entries.
As the entry for line 211 is a non-statement entry, and the previous
entries at that address are statement entries in a different symtab,
it is thought that it is better to prefer the earlier entries (in
dw2-skipped-line-entries-1.c), and so the entry for line 211 will be
discarded.
As GDB parses the line table it switches between the 3 symtabs (based
on source filename) adding the relevant entries to each symtab.
Additionally, as GDB switches symtabs, it adds an END entry to the
previous symtab.
The problem then is that, for the line 211 entry, this is the only
entry in dw2-skipped-line-entries-2.c before we switch symtab again.
But the line 211 entry is discarded. This means that GDB switches
from dw2-skipped-line-entries-1.c to dw2-skipped-line-entries-2.c, and
then on to dw2-skipped-line-entries-3.c without ever adding an entry
to dw2-skipped-line-entries-2.c.
And here then is the bug. GDB updates its idea of the previous symtab
not when an entry is written into a symtab, but every time we change
symtab.
In this case, when we switch to dw2-skipped-line-entries-3.c we add
the END marker to dw2-skipped-line-entries-2.c, even though no entries
were written to dw2-skipped-line-entries-2.c. At the same time, no
END marker is ever written into dw2-skipped-line-entries-1.c as the
dw2-skipped-line-entries-2.c entry (for line 211) was discarded.
Here is the 'maint info line-table' for dw2-skipped-line-entries-1.c
before this patch:
INDEX LINE REL-ADDRESS UNREL-ADDRESS IS-STMT PROLOGUE-END EPILOGUE-BEGIN
0 101 0x000000000040110a 0x000000000040110a Y
1 END 0x0000000000401114 0x0000000000401114 Y
2 102 0x0000000000401128 0x0000000000401128 Y
3 103 0x0000000000401128 0x0000000000401128 Y
4 104 0x0000000000401128 0x0000000000401128 Y
5 104 0x000000000040113c 0x000000000040113c
6 105 0x0000000000401146 0x0000000000401146 Y
7 END 0x0000000000401150 0x0000000000401150 Y
And after this patch:
INDEX LINE REL-ADDRESS UNREL-ADDRESS IS-STMT PROLOGUE-END EPILOGUE-BEGIN
0 101 0x000000000040110a 0x000000000040110a Y
1 END 0x0000000000401114 0x0000000000401114 Y
2 102 0x0000000000401128 0x0000000000401128 Y
3 103 0x0000000000401128 0x0000000000401128 Y
4 104 0x0000000000401128 0x0000000000401128 Y
5 END 0x0000000000401132 0x0000000000401132 Y
6 104 0x000000000040113c 0x000000000040113c
7 105 0x0000000000401146 0x0000000000401146 Y
8 END 0x0000000000401150 0x0000000000401150 Y
Notice that we gained an extra entry, the END marker that was added at
position #5 in the table.
Now, does this matter? I cannot find any bugs that trigger because of
this behaviour.
So why fix it? First, the current behaviour is inconsistent, as we
switch symtabs, we usually get an END marker in the previous symtab.
But occasionally we don't. I don't like things that are inconsistent
for no good reason. And second, as I said, I want to change the line
table parsing. To do this I want to check that my new parser creates
an identical table to the current parser. But my new parser naturally
"fixes" this inconsistency, so I have two choices, do extra work to
make my new parser bug-compatible with the current one, or fix the
current one. I'd prefer to just fix the current line table parser.
There's a test that includes the above example and checks that the END
markers are put in the correct place. But as I said, I've not been
able to trigger any negative behaviour from the current solution, so
there's no test that exposes any broken behaviour.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I think that is clearer and helps readability.
Rename a few iteration variables from "index" or "idx" to "shard". In
my mental model, the "index" is the whole thing, so it's confusing to
use that word when referring to shards.
Change-Id: I208cb839e873c514d1f8eae250d4a16f31016148
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I find this typedef to be confusing. The name is a bit too generic, so
it's not clear what it represents. When using the typedef for a
cooked_index_shard unique pointer, I think that spelling out the vector
type is not overly long.
Change-Id: I99fdab5cd925c37c3835b466ce40ec9c1ec7209d
Approved-By: Tom Tromey <tom@tromey.com>
|
|
New in v2:
- install address map in a single shard
- update test gdb.mi/mi-sym-info.exp to cope with the fact that
different symbols could be returned when using --max-results
When playing with the .debug_names reader, I noticed it was
significantly slower than the DWARF scanner. Using a "performance"
build of GDB (with optimization, no runtime sanitizer enabled, etc), I
measure with the following command on a rather large debug info file
(~4 GB):
$ time ./gdb -q -nx --data-directory=data-directory <binary> -iex 'maint set dwarf sync on' -batch
This measures the time it takes for GDB to build the cooked index (plus
some startup and exit overhead). I have a version of the binary without
.debug_names and a version with .debug_names added using gdb-add-index.
The results are:
- without .debug_names: 7.5 seconds
- with .debug_names: 24 seconds
This is a bit embarrassing, given that the purpose of .debug_names is to
accelerate things :). The reason is that the .debug_names processing is
not parallelized at all, while the DWARF scanner is heavily
parallelized.
The process of creating the cooked index from .debug_names is roughly in
two steps:
1. scanning of .debug_names and creation of cooked index entries (see
mapped_debug_names_reader::scan_all_names)
2. finalization of the index, name canonicalization and sorting of the
entries (see cooked_index::set_contents).
This patch grabs a low hanging fruit by creating multiple cooked index
shards instead of a single one during step one. Just doing this allows
the second step of the processing to be automatically parallelized, as
each shard is sent to a separate thread to be finalized.
With this patch, I get:
- without .debug_names: 7.5 seconds
- with .debug_names: 9.7 seconds
Not as fast as we'd like, but it's an improvement.
The process of scanning .debug_names could also be parallelized to shave
off a few seconds. My profiling shows that out of those ~10 seconds of
excecution, about 6 are inside scan_all_names. Assuming perfect
parallelization with 8 threads, it means that at best we could shave
about 5 seconds from that time, which sounds interesting. I gave it a
shot, but it's a much more intrusive change, I'm not sure if I will
finish it.
This patch caused some regressions in gdb.mi/mi-sym-info.exp with the
cc-with-debug-names board, in the test about the `--max-results` switch.
It appears at this test is relying on the specific symbols returned when
using `--max-results`. As far as I know, we don't guarantee which
specific symbols are returned, so any of the matching symbols could be
returned.
The round robin method used in this patch to assign index entries to
shards ends up somewhat randomizing which CU gets expanded first during
the symbol search, and therefore which order they appear in the
objfile's CU list, and therefore which one gets searched first.
I meditated on whether keeping compunits sorted within objfiles would
help make things more stable and predictable. It would somewhat, but it
wouldn't remove all sources of randomness. It would still possible for
a call to `expand_symtabs_matching` to stop on the first hit. Which
compunit gets expanded then would still be dependent on the specific
`quick_symbol_functions` internal details / implementation.
Commit 5b99c5718f1c ("[gdb/testsuite] Fix various issues in
gdb.mi/mi-sym-info.exp") had already started to make the test a bit more
flexible in terms of which symbols it accepts, but with this patch, I
think it's possible to get wildly varying results. I therefore modified
the test to count the number of returned symbols, but not expect any
specific symbol.
Change-Id: Ifd39deb437781f72d224ec66daf6118830042941
Approved-By: Tom Tromey <tom@tromey.com>
|
|
The following patch makes the .debug_names reader create multiple cooked
index shards, only one of them having an address map. The others will
have a nullptr address map.
Change the code using cooked_index_shard::m_addrmap to account for the
fact that it can be nullptr.
Change-Id: Id05b974e661d901dd43bb5ecb3a8fcfc15abc7ed
Approved-By: Tom Tromey <tom@tromey.com>
|
|
New in v2:
- add doc
- fix computation of offset in entry pool
Due to a mistake in the DWARF 5 spec, the way that GDB interprets
DW_IDX_parent when generating and reading .debug_names is not correct.
In Section 6.1.1.2, the parent index entry attribute is described as:
Parent debugging information entry, a reference to the index entry for
the parent. This is represented as the offset of the entry relative to
the start of the entry pool.
But in Table 6.1, DW_IDX_parent is described as:
Index of name table entry for parent
These two contradict each other. The former is the correct one and the
latter is an unfortunate leftover from an earlier version of the
proposal, according to [1]. It does make sense, because pointing to a
name table entry is ambiguous, while poiting to an index entry directly
is not. Unfortunately, GDB implemented pointing to a name table entry.
Changes on the writer side:
- For each written pool entry, remember the offset within the pool.
- Change the DW_IDX_parent form to DW_FORM_data4.
Using DW_FORM_udata isn't an option, because we don't know the actual
value when doing the first pass of writing the pool (see next point),
so we wouldn't know how many bytes to reserve, if we used a
variable-size encoding.
Using a fixed 4 bytes encoding would be an issue if the entry pool
was larger than 4 GiB, but that seems unlikely.
Note that clang uses DW_FORM_ref4 for this, but I'm not sure it is
appropriate, since forms of the reference class are specified as
referring "to one of the debugging information entries that describe
the program". Since we're not referring to a DIE, I decided to stay
with a form of the "constant" class. I think that readers will be
able to understand either way.
- Write a dummy 4 byte number when writing the pool, then patch those
values later. This is needed because parents can appear before their
children in the pool (there's no way to ensure that parents always
appear before their children), so we might now know at first what
value to put in.
- Add a `write_uint` method to `class data_buf` to support that use
case of patching a value in the middle of the data buffer.
- Simplify the type of `m_name_to_value_set`, we no longer need to
track the index at which a name will be written at.
- Produce a new augmentation string, "GDB3", to be able to distinguish
"old" and "new" indexes. It would be possible for a reader to
distinguish the two semantics of DW_IDX_parent using the form.
However, current versions of GDB don't do that, so they would be
confused trying to read a new index. I think it is preferable to use
a new augmentation string so that they will reject a new index
instead.
Changes on the reader side:
- Track the GDB augmentation version, in addition to whether the
augmentation string indicates the index was produced by GDB.
- When reading index entries, maintain a "pool offset" -> "cooked index
entry" mapping, to be able to find parents by pool offset.
- When resolving parents, keep the existing behavior of finding parents
by name table index if the augmentation string is "GDB2. Otherwise,
look up parents by pool offset. This assumes that .debug_names from
other producers (if/when we add support for reading them) use pool
offsets for DW_IDX_parent. This at least what clang does.
- Simplify augmentation string comparison a bit by using array views.
Update the "Extensions to ‘.debug_names’" section of the documentation
to reflect the new augmentation string version.
Tested by:
- manually producing executables with "GDB2" and "GDB3" .debug_names
sections and reading them.
- running the testsuite with the cc-with-debug-names board
[1] https://lists.dwarfstd.org/pipermail/dwarf-discuss/2025-January/002618.html
Change-Id: I265fa38070b86ef320e0a972c300d1d755735d8d
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
The cooked index "start_reading" method can only be called after the
dwarf2_per_bfd "index_table" member is set. This patch refactors this
code a little to centralize this constraint, adding a new
dwarf2_per_bfd::start_reading method and another (virtual) method to
dwarf_scanner_base.
This removes some casts, but also is also useful to support another
series I'm working on where the .gdb_index is rewritten.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
This changes dwarf2_read_gdb_index to return bool rather than int.
|
|
All the reported races have been fixed, so this patch re-enabled
background DWARF reading.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31751
Tested-By: Tom de Vries <tdevries@suse.de>
|
|
These includes are reported as unused by clangd.
Change-Id: Ibf3cdc881abad5f5969edca623412ceac7212149
|
|
They are unused, according to clangd.
Add some includes to other files, which were relying on transitive
includes.
Change-Id: I3bcb4be93b3a18bf44a4068f4067e567f83e1d4f
|
|
It is unused, according to clangd.
Change-Id: Ieadb84a2b1953b70d82a28775472fd347a809a62
|
|
dwarf2_per_bfd is used but never declared in this file, forward-declare
it.
dwarf2/types.h is unused, according to clangd.
Change-Id: I324b68894008af20307030c9e36c5abe06e36a78
|
|
show_index_cache_command prints whether the index-cache is enabled.
This text was added back in 2018 in commit 87d6a7aa (Add DWARF index
cache). Then in 2021, the enabling option was changed via commit
7bc5c369 (gdb: introduce "set index-cache enabled", deprecate "set
index-cache on/off").
This latter change made this output, IMO, redundant. That is,
currently gdb will show:
(gdb) show index-cache
...
index-cache enabled: The index cache is off.
...
The index cache is currently disabled.
This patch removes the redundant output.
|
|
The debug output that says a line has been recorded is currently
outside the `if` block which decides if the line should be recorded or
not. This means the debug output will claim the line was recorded,
when actually it wasn't!
Fixed by moving the debug output inside the `if` block.
Should be no user visible changes after this commit (except if debug
output is turned on).
Approved-By: Tom Tromey <tom@tromey.com>
|
|
We found that the gdb.ada/import.exp test fails when 'mold' is used as
the linker. This happens because mold decides to mark most of the
symbols in the executable as being file-local. I tend to think this
choice, while non-traditional, is probably fine. So, this patch fixes
the problem by changing the relevant Ada code to look for file-local
symbols as well.
Furthermore, there are two overloads of lookup_minimal_symbol_linkage
that both have a final 'bool' parameter -- but with radically
different meanings. This patch somewhat clears up this confusion as
well.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31378
|
|
When building gdb with gcc 7.5.0, I run into:
...
gdb/dwarf2/cooked-index.c: In lambda function:
gdb/dwarf2/cooked-index.c:104:5: error: \
the value of ‘_sch_tolower’ is not usable in a constant expression
};
^
In file included from gdbsupport/gdb-safe-ctype.h:47:0,
from gdb/dwarf2/cooked-index.c:34:
include/safe-ctype.h:111:29: note: ‘_sch_tolower’ was not declared ‘constexpr’
extern const unsigned char _sch_tolower[256];
^~~~~~~~~~~~
...
This does not happen with gcc 8.2.1.
Fix this by dropping the constexpr on lambda function munge in
cooked_index_entry::compare for gcc 7.
Tested by completing the build on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
In commit 64a97606 ("Support template lookups in
strncmp_iw_with_mode"), gdb was changed so that a command like "break
func<templ>" would match instantiations like "func<templ<int>>".
The new indexer does not support this and so this is a regression.
This went unnoticed because gdb.linespec.cpcompletion.exp puts all
these functions into the main file, and this CU is expanded early.
This patch fixes the bug by changing the cooked index entry comparison
function. It also updates the test to fail without this fix.
Regression tested on x86-64 Fedora 40.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32482
|
|
When running test-case gdb.base/fission-macro.exp on openSUSE Tumbleweed
(using gcc 14) with target board unix/-m32, I get:
...
(gdb) info macro FIRST^M
Defined at /data/vries/gdb/src/gdb/testsuite/gdb.base/fission-macro.c:0^M
-DFIRST=1^M
(gdb) FAIL: $exp: \
dwarf_version=5: dwarf_bits=32: strict_dwarf=0: info macro FIRST
...
instead of the expected:
...
(gdb) info macro FIRST^M
Defined at /data/vries/gdb/src/gdb/testsuite/gdb.base/fission-macro.c:18^M
(gdb) PASS: $exp: \
dwarf_version=5: dwarf_bits=32: strict_dwarf=0: info macro FIRST
...
A dwarf-5 .debug_str_offsets section starts with a header consisting of:
- an initial length (4 bytes for 32-bit and 12 bytes for 64-bit),
- a 2 byte version string, and
- 2 bytes padding
so in total 8 bytes for 32-bit and 16 bytes for 64-bit.
This offset is calculated here in dwarf_decode_macros:
...
str_offsets_base = cu->header.addr_size;
...
which is wrong for both dwarf-5 cases (and also happens to be wrong for
dwarf-4).
Fix this by computing str_offsets_base correctly for dwarf-5, for both the
32-bit and 64-bit case.
Likewise, fix this for dwarf-4, using str_offsets_base 0. We can only test
this with gcc-15, because gcc 14 and earlier don't have the fix for
PR debug/115066.
Tested on x86_64-linux.
Tested test-case using a current gcc trunk build, and gcc 14.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/31897
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31897
|
|
My earlier changes introduced a self-test crash. This patch fixes the
bug by introducing a new method overload into mock_mapped_index.
|
|
The base class mapped_index_base is no longer needed. Previously it
was used by both the .gdb_index and .debug_names readers, but the
latter now uses the cooked index instead.
This patch removes mapped_index_base, merging it into
mapped_gdb_index. Supporting code that is specific to .gdb_index is
also moved into read-gdb-index.c. This shrinks dwarf2/read.c a bit,
which is nice.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32504
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
gdb_index_unpack is not used and can be removed. The include of
extract-store-integer.h is also no longer needed by this file.
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
I found a number of .c files that need to include
extract-store-integer.h but that were only including it indirectly.
This patch adds the missing includes. This change enables the next
patch.
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
Sometimes, in the GDB testsuite, we want to test the ability of specific
unwinders to handle some piece of code. Usually this is done by trying
to outsmart GDB, or by coercing the compiler to remove information that
GDB would rely on. Both approaches have problems as GDB gets smarter
with time, and that compilers might differ in version and behavior, or
simply introduce new useful information. This was requested back in 2003
in PR backtrace/8434.
To improve our ability to thoroughly test GDB, this patch introduces a
new maintenance command that allows a user to disable some unwinders,
based on either the name of the unwinder or on its class. With this
change, it will now be possible for GDB to not find any frame unwinders
for a given frame, which would previously cause GDB to assert. GDB will
now check if any frame unwinder has been disabled, and if some has, it
will just error out instead of asserting.
Unwinders can be disabled or re-enabled in 3 different ways:
* Disabling/enabling all at once (using '-all').
* By specifying an unwinder class to be disabled (option '-class').
* By specifying the name of an unwinder (option '-name').
If you give no options to the command, GDB assumes the input is an
unwinder class. '-class' would make no difference if used, is just here
for completeness.
This command is meant to be used once the inferior is already at the
desired location for the test. An example session would be:
(gdb) start
Temporary breakpoint 1, main () at omp.c:17
17 func();
(gdb) maint frame-unwinder disable ARCH
(gdb) bt
\#0 main () at omp.c:17
(gdb) maint frame-unwinder enable ARCH
(gdb) cont
Continuing.
This commit is a more generic version of commit 3c3bb0580be0,
and so, based on the final paragraph of the commit message:
gdb: Add switch to disable DWARF stack unwinders
<...>
If in the future we find ourselves adding more switches to disable
different unwinders, then we should probably move to a more generic
solution, and remove this patch.
this patch also reverts 3c3bb0580be0
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=8434
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
temp adding completion
|
|
Frame unwinders have historically been a structure populated with
callback pointers, so that architectures (or other specific unwinders)
could install their own way to handle the inferior. However, since
moving to C++, we could use polymorphism to get the same functionality
in a more readable way. Polymorphism also makes it simpler to add new
functionality to all frame unwinders, since all that's required is
adding it to the base class.
As part of the changes to add support to disabling frame unwinders,
this commit makes the first baby step in using polymorphism for the
frame unwinders, by making frame_unwind a virtual class, and adds a
couple of new classes. The main class added is frame_unwind_legacy,
which works the same as the previous structs, using function pointers
as callbacks. This class was added to allow the transition to happen
piecemeal. New unwinders should instead follow the lead of the other
classes implemented.
2 of the others, frame_unwind_python and frame_unwind_trampoline, were added
because it seemed simpler at the moment to do that instead of reworking
the dynamic allocation to work with the legacy class, and can be used as
an example to future implementations.
Finally, the cygwin unwinder was converted to a class since it was most
of the way there already.
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
A future patch will add a way to disable certain unwinders based on
different characteristics. This patch aims to make it more convenient
to disable related unwinders in bulk, such as architecture specific
ones, by identifying all unwinders by which part of the code adds it.
The classes, and explanations, are as follows:
* GDB: An internal unwinder, added by GDB core, such as the unwinder
for dummy frames;
* EXTENSION: Unwinders added by extension languages;
* DEBUGINFO: Unwinders installed by the debug info reader;
* ARCH: Unwinders installed by the architecture specific code.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
In rw_pieced_value, when reading/writing part of a register, DW_OP_piece and
DW_OP_bit_piece are handled the same, but the standard tells us:
- DW_OP_piece: if the piece is located in a register, but does not occupy the
entire register, the placement of the piece within that register is defined
by the ABI.
- DW_OP_bit_piece: if the location is a register, the offset is from the least
significant bit end of the register.
Add a new hook gdbarch_dwarf2_reg_piece_offset that allows us to define the
ABI-specific behaviour for DW_OP_piece.
The default implementation of the hook is the behaviour of DW_OP_bit_piece, so
there should not be any functional changes.
Tested on s390x-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Add a new field "dwarf_location_atom op" to dwarf_expr_piece to keep track of
which dwarf_location_atom caused a dwarf_expr_piece to be added.
This is used in the following patch.
Tested on s390x-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Iain pointed out a crash in the DWARF indexer when run on a certain D
program. The DWARF in this case has a nameless enum class; this
causes an assertion failure.
This patch arranges to simply ignore such types. The fact that an
enum class is nameless in this case appears to be a compiler bug.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32518
Approved-By: Tom de Vries <tdevries@suse.de>
|
|
The code in dwarf2/read.c:new_symbol that handles Ada 'import' symbols
has a bug. It uses the current scope, which by default this is the
file scope -- even for a global symbol like:
<1><1186>: Abbrev Number: 4 (DW_TAG_variable)
<1187> DW_AT_name : (indirect string, offset: 0x1ad2): pkg__imported_var_ada
...
<1196> DW_AT_external : 1
This disagrees with the scope computed by the DWARF indexer.
Now, IMO new_symbol and its various weirdness really has to go. And,
ideally, this information would come from the indexer rather than
perhaps being erroneously recomputed. But meanwhile, this patch fixes
the issue at hand.
This came up while working on another change that exposes the bug.
Reviewed-By: Tom de Vries <tdevries@suse.de>
|
|
This patch is the result of running check-include-guards.py on the
current tree. Running it a second time causes no changes.
Reviewed-By: Tom de Vries <tdevries@suse.de>
|
|
This adds a new "command" style that is used when styling the name of
a gdb command.
Note that not every instance of a command name that is output by gdb
is changed here. There is currently no way to style error() strings,
and there is no way to mark up command help strings.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31747
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Keith Seitz <keiths@redhat.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
Add new DWARF5 language codes to gdb/dwarf2/read.c where
they are converted to GDB language names. The codes
were added to include/dwarf.h by syncing with gcc, Ada language
codes were added to dwarf.h earlier.
Approved-By: Tom Tromey <tom@tromey.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
In commit 8a61ee551ce ("[gdb/symtab] Workaround PR gas/31115"), I applied a
workaround for PR gas/31115 in read_func_scope, fixing test-case
gdb.arch/pr25124.exp.
Recently I noticed that the test-case is failing again.
Fix this by factoring out the workaround into a new function fixup_low_high_pc
and applying it in dwarf2_die_base_address.
While we're at it, do the same in dwarf2_record_block_ranges.
Tested on arm-linux with target boards unix/-marm and unix/-mthumb.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
|
|
Remove some includes reported as unused by clangd. Add some to files
that actually need it.
Change-Id: I01c61c174858c1ade5cb54fd7ee1f582b17c3363
|
|
After the commit:
commit b9de07a5ff74663ff39bf03632d1b2ea417bf8d5
Date: Thu Oct 10 11:37:34 2024 +0100
gdb: fix handling of DW_AT_entry_pc of inlined subroutines
GDB's buildbot CI testing highlighted this assertion failure:
(gdb) c
Continuing.
../../binutils-gdb/gdb/block.h:203: internal-error: set_entry_pc: Assertion `start >= this->start () && start < this->end ()' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
FAIL: gdb.base/break-probes.exp: run til our library loads (GDB internal error)
This assertion was in the new function set_entry_pc and is asserting
that the default_entry_pc() value is within the blocks start/end
range.
The default_entry_pc() is the value GDB will use as the entry-pc if
the DWARF doesn't specifically override the entry-pc. This value is
calculated as:
1. The start address of the first sub-range within the block, if the
block has more than 1 range, or
2. The low address (from DW_AT_low_pc) for the block.
If the block only has a single range then this means the block was
defined with low/high pc attributes (case #2 above). These low/high
pc values are what block::start() and block::end() return. This means
that by definition, if the block is continuous, the above assert
cannot trigger as 'start', the default_entry_pc() would be equivalent
to block::start().
This means that, for the assert to trigger, the block must have
multiple ranges, and the first address of the first range is not
within the blocks low/high address range. This seems wrong.
I inspected the state at the time the assert triggered and discovered
the block's start() address. Then I removed the assert and restarted
GDB. I was now able to inspect the blocks at the offending address:
(gdb) maintenance info blocks 0x7ffff7dddaa4
Blocks at 0x7ffff7dddaa4:
from objfile: [(objfile *) 0x44a37f0] /lib64/ld-linux-x86-64.so.2
[(block *) 0x46b30c0] 0x7ffff7ddd5a0..0x7ffff7dde8a6
entry pc: 0x7ffff7ddd5a0
is global block
symbol count: 4
is contiguous
[(block *) 0x46b3020] 0x7ffff7ddd5a0..0x7ffff7dde8a6
entry pc: 0x7ffff7ddd5a0
is static block
symbol count: 9
is contiguous
[(block *) 0x46b2f70] 0x7ffff7ddda00..0x7ffff7dddac3
entry pc: 0x7ffff7ddda00
function: __GI__dl_find_dso_for_object
symbol count: 4
is contiguous
[(block *) 0x46b2e10] 0x7ffff7dddaa4..0x7ffff7dddac3
entry pc: 0x7ffff7dddaa4
inline function: __GI__dl_find_dso_for_object
symbol count: 5
is contiguous
[(block *) 0x46b2a40] 0x7ffff7dddaa4..0x7ffff7dddac3
entry pc: 0x7ffff7dddaa4
symbol count: 1
is contiguous
[(block *) 0x46b2970] 0x7ffff7dddaa4..0x7ffff7dddac3
entry pc: 0x7ffff7dddaa4
symbol count: 2
address ranges:
0x7ffff7ddda0e..0x7ffff7ddda77
0x7ffff7ddda90..0x7ffff7ddda96
I've left everything in for context, but the only really interesting
bit is the very last block, it's low/high range is:
0x7ffff7dddaa4..0x7ffff7dddac3
but it has separate ranges:
0x7ffff7ddda0e..0x7ffff7ddda77
0x7ffff7ddda90..0x7ffff7ddda96
which are all outside the low/high range. This is what triggers the
assert. But why does that block exist at all?
What I believe is happening is that we're running into a bug in older
versions of GCC. The buildbot failure was with an 8.5 gcc, and Tom de
Vries also reported seeing failures when using version 7 and 8 gcc,
but not with gcc 9 and onward.
Looking at the DWARF I can see that the problematic block is created
from this DIE:
<4><15efb>: Abbrev Number: 83 (DW_TAG_lexical_block)
<15efc> DW_AT_abstract_origin: <0x15e9f>
<15efe> DW_AT_low_pc : 0x7ffff7dddaa4
<15f06> DW_AT_high_pc : 31
which links via DW_AT_abstract_origin to:
<2><15e9f>: Abbrev Number: 80 (DW_TAG_lexical_block)
<15ea0> DW_AT_ranges : 0x38e0
<15ea4> DW_AT_sibling : <0x15eca>
And so we can see that <15efb> has got both low/high pc attributes and
a ranges attribute.
If I widen my checking to parents of DIE <15efb> then I see that they
also have DW_AT_abstract_origin, however, there is something
interesting going on, the parent DIEs are linking to a different DIE
tree than <15efb>.
What I believe is happening is this, we have an abstract instance
tree, this is rooted at a DW_AT_subprogram, and contains all the
blocks, variables, parameters, etc, that you would expect. As this is
an abstract instance, then there are no low/high pc attributes, and no
ranges attributes in this tree. This makes sense.
Now elsewhere we have a DW_TAG_subprogram (not
DW_TAG_inlined_subroutine) which links via
DW_AT_abstract_origin to the abstract DW_AT_subprogram. This case is
documented in the DWARF 5 spec in section 3.3.8.3, and describes an
Out-of-Line Instance of an Inlined Subroutine. Within this out of
line instance many of the DIE correctly link back, using
DW_AT_abstract_origin to the abstract instance tree. This tree also
includes the DIE <15e9f>, which is where our problem DIE references.
Now, to really confuse things, within this out-of-line instance we
have a DW_TAG_inlined_subroutine, which is another instance of the
same abstract instance tree! This would seem to indicate a recursive
call to the inline function, and the compiler, for some reason, needed
to instantiate an out of line instance of this function.
And it is within this nested, inlined subroutine, that the problem DIE
exists. The problem DIE is referencing the corresponding DIE within
the out of line instance tree, but I am convinced this must be a (long
fixed) GCC bug, and that the problem DIE should be referencing the DIE
within the abstract instance tree.
I'm aware that the above is pretty confusing. The actual DWARF would
be a around 200 lines long, so I'd like to avoid dumping it in here.
But here's my attempt at representing what's going on in a minimal
example. The numbers down the side represent the section offset, not
the nesting level, and I've removed any attributes that are not
relevant:
<1> DW_TAG_subprogram
<2> DW_TAG_lexical_block
<3> DW_TAG_subprogram
DW_AT_abstract_origin <1>
<4> DW_TAG_lexical_block
DW_AT_ranges ...
<5> DW_TAG_inlined_subroutine
DW_AT_abstract_origin <1>
<6> DW_TAG_lexical_block
DW_AT_abstract_origin <4>
DW_AT_low_pc ...
DW_AT_high_pc ...
The lexical block at <6> is linking to <4> when it should be linking
to <2>.
There is one additional thing that we might wonder about, which is,
when calculating the low/high pc range for a block, why does GDB not
make use of the range information and expand the range beyond the
defined low/high values?
The answer to this is in dwarf_get_pc_bounds_ranges_or_highlow_pc in
dwarf/read.c. This is where the low/high bounds are calculated. What
we see is that GDB first checks for a low/high attribute pair, and if
that is present, this defines the address range for the block. Only
if there is no DW_AT_low_pc do we check for the DW_AT_ranges, and use
that to define the extent of the block. And this makes sense, section
3.5 of the DWARF-5 spec says:
The lexical block entry may have either a DW_AT_low_pc and DW_AT_high_pc
pair of attributes or a DW_AT_ranges attribute whose values encode the
contiguous or non-contiguous address ranges, respectively, of the machine
instructions generated for the lexical block...
Section 3.5 is specifically about lexical blocks, but the same
wording, about it being either low/high OR ranges is repeated for
other DW_TAG_ types.
So this explains why GDB doesn't use the ranges to expand the problem
blocks ranges; as the first DIE has low/high addresses, these are
used, and the ranges is not consulted.
It is only later in dwarf2_record_block_ranges that we create a range
based off the low/high pc, and then also process the ranges data, this
allows the problem block to exist with ranges that are outside the
low/high range.
To solve this I considered a number of options:
1. Prevent loading certain attributes from an abstract instance.
Section 3.3.8.1 of the DWARF-5 spec talks about which attributes are
appropriate to place in an abstract instance. Any attribute that
might vary between instances should not appear in an abstract
instance. DW_AT_ranges is included as an example in the
non-exhaustive list of attributes that should not appear in an
abstract instance.
Currently in dwarf2_attr (dwarf2/read.c), when we see a
DW_AT_abstract_origin attribute, we always follow this to try and find
the attribute we are looking for. But we could change this function
so that we prevent this following for attributes that we know should
not be looked up in an abstract instance. This would solve the
problem in this case by preventing us finding the DW_AT_ranges in the
incorrect abstract instance.
2. Filter the ranges.
Having established a blocks low/high address range in
dwarf_get_pc_bounds_ranges_or_highlow_pc, we could allow
dwarf2_record_block_ranges to parse the ranges, but we could reject
any range that extends outside the blocks defined start and end
addresses.
For well behaved DWARF where we have either low/high or ranges, then
the blocks start/end are defined from the range data, and so, by
definition, every range would be acceptable.
But in our problem case we would reject all of the invalid ranges.
This is my least favourite solution as it feels like rejecting the
ranges is tackling the problem too late on.
3. Don't try to parse ranges when we have low/high attributes.
This option involves updating dwarf2_record_block_ranges to match the
behaviour of dwarf_get_pc_bounds_ranges_or_highlow_pc, and, I believe,
to match the DWARF spec: don't try to read range data from
DW_AT_ranges if we have low/high pc attributes.
In our case this solves the issue because the problematic DIE has the
low/high attributes, and it then links to the wrong DIE which happens
to have DW_AT_ranges. With this change in place we don't even look
for the DW_AT_ranges.
If the problem were reversed, and the initial DIE had DW_AT_ranges,
but the incorrectly referenced DIE had the low/high pc attributes,
we would pick up the wrong addresses, but this wouldn't trigger any
asserts. The reason is that dwarf_get_pc_bounds_ranges_or_highlow_pc
would also find the low/high addresses from the incorrectly referenced
DIE, and so we would just end up with a block which had the wrong
address ranges, but the block would be self consistent, which is
different to the problem we hit here.
In the end, in this commit I went with solution #3, having
dwarf_get_pc_bounds_ranges_or_highlow_pc and
dwarf2_record_block_ranges be consistent seems sensible. However, I
do wonder if in the future we might want to explore solution #1 as an
additional safety feature.
With this patch in place I'm able to run the gdb.base/break-probes.exp
without seeing the assert that CI testing highlighted. I see no
regressions when testing on x86-64 GNU/Linux with gcc 9.3.1.
Note: the diff in this commit looks big, but it's really just me
indenting the code.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
The test gdb.cp/step-and-next-inline.exp creates a test binary called
step-and-next-inline-no-header. This test includes a function
`tree_check` which is inlined 3 times.
When testing with some older versions of gcc (I've tried 8.4.0, 9.3.1)
we see the following DWARF representing one of the inline instances of
tree_check:
<2><8d9>: Abbrev Number: 38 (DW_TAG_inlined_subroutine)
<8da> DW_AT_abstract_origin: <0x9ee>
<8de> DW_AT_entry_pc : 0x401165
<8e6> DW_AT_GNU_entry_view: 0
<8e7> DW_AT_ranges : 0x30
<8eb> DW_AT_call_file : 1
<8ec> DW_AT_call_line : 52
<8ed> DW_AT_call_column : 10
<8ee> DW_AT_sibling : <0x92d>
...
<1><9ee>: Abbrev Number: 46 (DW_TAG_subprogram)
<9ef> DW_AT_external : 1
<9ef> DW_AT_name : (indirect string, offset: 0xe8): tree_check
<9f3> DW_AT_decl_file : 1
<9f4> DW_AT_decl_line : 38
<9f5> DW_AT_decl_column : 1
<9f6> DW_AT_linkage_name: (indirect string, offset: 0x2f2): _Z10tree_checkP4treei
<9fa> DW_AT_type : <0x9e8>
<9fe> DW_AT_inline : 3 (declared as inline and inlined)
<9ff> DW_AT_sibling : <0xa22>
...
Contents of the .debug_ranges section:
Offset Begin End
...
00000030 0000000000401165 0000000000401165 (start == end)
00000030 0000000000401169 0000000000401173
00000030 0000000000401040 0000000000401045
00000030 <End of list>
...
Notice that one of the sub-ranges of tree-check is empty, this is the
line marked 'start == end'. As the end address is the first address
after the range, this range cover absolutely no code.
But notice too that the DW_AT_entry_pc for the inline instance points
at this empty range.
Further, notice that despite the ordering of the sub-ranges, the empty
range is actually in the middle of the region defined by the lowest
address to the highest address. The ordering is not a problem, the
DWARF spec doesn't require that ranges be in any particular order.
However, this empty range is causing issues with GDB newly acquire
DW_AT_entry_pc support.
GDB already rejects, and has done for a long time, empty sub-ranges,
after all, the DWARF spec is clear that such a range covers no code.
The recent DW_AT_entry_pc patch also had GDB reject an entry-pc which
was outside of the low/high bounds of a block.
But in this case, the entry-pc value is within the bounds of a block,
it's just not within any useful sub-range. As a consequence, GDB is
storing the entry-pc value, and making use of it, but when GDB stops,
and tries to work out which block the inferior is in, it fails to spot
that the inferior is within tree_check, and instead reports the
function into which tree_check was inlined.
I've tested with newer versions of gcc (12.2.0 and 14.2.0) and with
these versions gcc is still generating the empty sub-range, but now
this empty sub-range is no longer the entry point. Here's the
corresponding ranges table from gcc 14.2.0:
Contents of the .debug_rnglists section:
Table at Offset: 0:
Length: 0x56
DWARF version: 5
Address size: 8
Segment size: 0
Offset entries: 0
Offset Begin End
...
00000021 0000000000401165 000000000040116f
0000002b 0000000000401040 (base address)
00000034 0000000000401040 0000000000401040 (start == end)
00000037 0000000000401041 0000000000401046
0000003a <End of list>
...
The DW_AT_entry_pc is 0x401165, but this is not the empty sub-range,
as a result, when GDB stops at the entry-pc, GDB will correctly spot
that the inferior is in the tree_check function.
The fix I propose here is, instead of rejecting entry-pc values that
are outside the block's low/high range, instead reject entry-pc values
that are not inside any of the block's sub-ranges.
Now, GDB will ignore the prescribed entry-pc, and will instead select
a suitable default entry-pc based on either the block's low-pc value,
or the first address of the first range.
I have extended the gdb.cp/step-and-next-inline.exp test to check this
case, but this does depend on the compiler version being used (newer
compilers will always pass, even without the fix).
So I have also added a DWARF assembler test to cover this case.
Reviewed-By: Kevin Buettner <kevinb@redhat.com>
|
|
Before the fix for PR symtab/32225, the parent map dump showed a mapping from
section offsets to cooked index entries:
...
0x0000000000000035 0x3ba9560 (0x34: sp1::A)
...
but now that's no longer the case:
...
0x00000000406f5405 0x410a04d0 (0x34: sp1::A)
...
Fix this by extending the annotation somewhat, such that we get:
...
map start:
0x0000000012c52405 0x135fd550
(section: .debug_info, offset: 0x35) -> (0x34: sp1::A)
...
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32225
|
|
Consider test-case:
...
$ cat test.c
namespace sp1 {
class A {
int i;
const int f1 = 1;
...
const int f29 = 1;
};
}
sp1::A a;
void _start (void) {}
$ cat test2.c
namespace sp2 {
class B {
float f;
const float f1 = 1;
...
const float f29 = 1;
};
}
sp2::B b;
...
compiled like this:
...
$ g++ test.c -gdwarf-4 -c -g -fdebug-types-section
$ g++ test2.c -gdwarf-5 -c -g -fdebug-types-section
$ g++ -g test.o test2.o -nostdlib
...
Using:
...
$ gdb -q -batch -iex "maint set worker-threads 0" a.out -ex "maint print objfiles"
...
we get a cooked index entry with incorrect parent:
...
[29] ((cooked_index_entry *) 0x3c57d1a0)
name: B
canonical: B
qualified: sp1::A::B
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x154
parent: ((cooked_index_entry *) 0x3c57d110) [A]
...
The problem is that the parent map assumes that all offsets are in the same
section.
Fix this by using dwarf2_section_info::buffer-relative addresses instead,
which get us instead:
...
[29] ((cooked_index_entry *) 0x3f0962b0)
name: B
canonical: B
qualified: sp2::B
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x154
parent: ((cooked_index_entry *) 0x3f096280) [sp2]
...
Tested on x86_64-linux.
PR symtab/32225
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32225
|
|
Convert dwarf2_per_objfile::die_type_hash, which maps debug info
offsets to `type *`, to gdb::unordered_map.
Change-Id: I5c174af64ee46d38a465008090e812acf03704ec
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Convert one use of htab_t, mapping (unrelocated) pc to call_site
objects, to `gdb::unordered_map<unrelocated_addr, call_site *>`.
Change-Id: I40a0903253a8589dbdcb75d52ad4d233931f6641
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Convert one use of htab_t, mapping offsets to die_info object, to
`gdb::unordered_set`.
Change-Id: Ic80df22bda551e2d4c2511d167e057f4d6cd2b3e
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This converts more code in the DWARF reader to use the new hash table.
Change-Id: I86f8c0072f0a09642de3d6f033fefd0c8acbc4a3
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This converts the DWARF abbrevs themselves to use the new hash table.
Change-Id: I0320a733ecefe2cffeb25c068f17322dd3ab23e2
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This converts the DWARF abbrev cache to use the new hash table.
Change-Id: I5e88cd4030715954db2c43f873b77b6b8e73f5aa
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This converts dwarf2/macro.c to use the new hash table.
Change-Id: I6af0d1178e2db330fe3a89d57763974145ed17c4
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
It can never return nullptr, return a reference instead of a pointer.
Change-Id: Ibc6f16eb74dc16059152982600ca9f426d7f80a4
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Make `abbrev_table_cache::find` const, make it return a pointer to
`const abbrev_table`, adjust the fallouts.
Make `cooked_index_storage::get_abbrev_table_cache` const, make itreturn
a pointer to const `abbrev_table_cache`.
Change-Id: If63b4b3a4c253f3bd640b13bce4a854eb2d75ece
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This cache holds `abbrev_table` objects, so I think it's clearer and
more consistent to name it `abbrev_table_cache`. Rename it and
everything that goes along with it.
Change-Id: I43448c0aa538dd2c3ae5efd2f7b3e7b827409d8c
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Eli mentioned [1] that given that we use US English spelling in our
documentation, we should use "behavior" instead of "behaviour".
In wikipedia-common-misspellings.txt there's a rule:
...
behavour->behavior, behaviour
...
which leaves this as a choice.
Add an overriding rule to hardcode the choice to common-misspellings.txt:
...
behavour->behavior
...
and add a rule to rewrite behaviour into behavior:
...
behaviour->behavior
...
and re-run spellcheck.sh on gdb*.
Tested on x86_64-linux.
[1] https://sourceware.org/pipermail/gdb-patches/2024-November/213371.html
|