Age | Commit message (Collapse) | Author | Files | Lines |
|
Currently a reinterpret_cast may change the pointer value if
multiple inheritance is involved:
```
(gdb) p r
$1 = (Right *) 0x22f75c
(gdb) p reinterpret_cast<LeftRight*>(r)
$2 = (LeftRight *) 0x22f758
```
It's because value_cast is called in this case, which automatically
does up- and downcasting.
Fixed by simply using the target pointer type in a copy of the
original value:
```
(gdb) p r
$1 = (Right *) 0x3bf87c
(gdb) p reinterpret_cast<LeftRight*>(r)
$2 = (LeftRight *) 0x3bf87c
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18861
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Currently it's not possible to call functions if an argument is a
pointer to an array:
```
(gdb) l f
1 int f (int (*x)[2])
2 {
3 return x[0][1];
4 }
5
6 int main()
7 {
8 int a[2][2] = {{0, 1}, {2, 3}};
9 return f (a);
10 }
(gdb) p f(a)
Cannot resolve function f to any overloaded instance
```
This happens because types_equal doesn't handle array types, so the
function is never even considered as a possibility.
With array type handling added, by comparing element types and array
bounds, the same works:
```
(gdb) p f(a)
$1 = 1
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=15398
Co-Authored-By: Keith Seitz <keiths@redhat.com>
Reviewed-By: Guinevere Larsen <blarsen@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I noticed that "info locals" on a certain large Ada program was very
slow. I tracked this down to ada_get_tsd_type expanding nearly every
CU in the program.
This patch fixes the problem by changing this code to use the more
efficient lookup_transparent_type which, unlike the Ada-specific
lookup functions, does not try to find all matching instances.
Note that I first tried fixing this by changing ada_find_any_type, but
this did not work -- I may revisit this approach at some later date.
Also note that the copyright dates on the test files are set that way
because I copied them from another test.
New in v2: the new test failed on the Linaro regression tester.
Looking at the logs, it seems that gdb was picking up a 'value' from
libgnat:
$1 = {<text variable, no debug info>} 0xf7e227a4 <ada.calendar.formatting.value>
This version renames the local variable in an attempt to work around
this.
v3: In v2, while trying to reproduce the problem locally, I
accidentally forgot to commit one of the changes.
|
|
The gdb.solib_name() and Progspace.solib_name() functions can throw an
exception if the address argument is not a valid address, but this is
not currently tested.
This commit adds a couple of tests to check that exceptions are thrown
correctly.
An early version of this commit updated the documentation, but it was
pointed out that lots of functions throw an exception if passed an
argument of the wrong type, and we don't document all of these, it's
kind-of assumed that passing an object of the incorrect type might
result in an exception, so this updated version leaves the docs alone,
but I do think adding the extra tests has value.
There's no changes to GDB itself in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
symtab-> linetable () is set to null in
buildsym_compunit::end_compunit_symtab_with_blockvector () if the symtab
has no linetable. Attempting to iterate over this linetable using the
Python API caused GDB to segfault.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
In commit 2aaba744467 ("[gdb] Fix "value is not available" with debug frame")
I fixed a case in frame_unwind_register_value where using "set debug frame on"
caused an "info frame" command to abort, reporting a "value is not available"
error, due to the tpidruro register being unavailable.
Subsequently, commit bbb12eb9c84 ("gdb/arm: Remove tpidruro register from
non-FreeBSD target descriptions") removed the unavailable register, which
caused a progression on test-case gdb.base/inline-frame-cycle-unwind.exp.
While investigating the progression (see PR python/31437), I found that the
"debug frame" output of the test-case (when reverting commit bbb12eb9c84)
showed a smilar problem:
...
Python Exception <class 'gdb.error'>: value is not available^M
...
that was absent without "debug frame".
Fix this likewise in fetch_lazy_register, and update the test-case to check
for the exception.
Furthermore, I realized that there's both value::entirely_available and
value::entirely_unavailable, and that commit 2aaba744467 handled the case
of !entirely_available by printing unavailable.
Instead, print:
- "unavailable" for entirely_unavailable, and
- "partly unavailable" for !entirely_unavailable && !entirely_available.
Tested on x86_64-linux and arm-linux.
|
|
ptype is a bit funny, in that it accepts both expressions and type
names. It also evaluates the resulting expression using
EVAL_AVOID_SIDE_EFFECTS -- which both seems sensible (as a user would
you expect ptype to possibly cause inferior execution?), but is also a
historical artifact of how expressions are implemented (there's no
EVAL_FOR_TYPE).
In Ada, calling a function with an array will sometimes result in a
"thick pointer" array descriptor being made. This is essentially a
structure holding a pointer and bounds information.
Currently, in such a callee, printing the type of the array will yield
funny results:
(gdb) print str.all
$1 = "Hello World"
(gdb) ptype str
type = array (<>) of character
(gdb) ptype str.all
type = array (1 .. 0) of character
That "1 .. 0" is the result of an EVAL_AVOID_SIDE_EFFECTS branch
trying to do "something" with an array descriptor, without doing too
much.
I tried briefly to make this code really dereference the array
descriptor and get the correct runtime type. However, that proved to
be tricky; it certainly can't be done for all access types, because
that will cause dynamic type resolution and end up printing just the
runtime type -- which with variants may be pretty far from what the
user may expect.
Instead, this patch arranges to just leave such types alone in this
situation. I don't think this should have an extra effects, because
things like array subscripting still work on thick pointers.
This patch also touches arrayptr.exp, because in that case the access
type is a "thin pointer", and this ensures that the output does not
change in that scenario.
|
|
This patch arranges to set __file__ when source'ing a Python script.
This fixes a problem that was introduced by the "source" rewrite, and
then pointed out by Lancelot Six.
Reviewed-by: Lancelot Six <lancelot.six@amd.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
When certain DAP tests are run in a certain order, dejagnu will throw
an exception during shutdown. After adding many logging statements, I
tracked this down to kill_wait_spawned_process not clearing the
'fileid' board_info entry, causing dejagnu to try to wait for the
process a second time -- and fail.
Tom de Vries then pointed out a second instance of this, which I
tracked down to the same problem occurring when spawning gdbserver.
This version of the patch fixes this by adding a new proc that can be
used to clean up board_info after waiting for a process to exit. I'm
not sure why this problem hasn't affected the test suite in the past.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31435
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
Fedora GDB has carried around a patch for a while which tested
attaching to an i386 process which is stopped within the vDSO library
region. Apparently, at some point in the distant past there was an
issue finding symbol information for this region in this situation.
I'm struggling to track down the precise details of what the original
bug was, however, acquiring symbol information for the vDSO region is
different than for "normal" shared libraries -- the vDSO information
is synthesised within GDB during the attach / inferior creation
process -- so it's not unreasonable to imagine that there could be a
bug specifically in this area of GDB which wouldn't impact "normal"
shared libraries.
I looked for references to vDSO in our testsuite and couldn't find
any tests that looked like they did the same sort of thing, so I'd
like to propose adding this test to our testsuite.
It's a pretty simple test, and doesn't take long to run, so the cost
of adding this is not huge.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
On debian 12, aarch64-linux I run into:
...
(gdb) list .^M
No symbol table is loaded. Use the "file" command.^M
(gdb) FAIL: gdb.base/list-nodebug.exp: first 'list .'
...
The test-case expects some debug info, but none for main. Instead, there's no
debug info at all.
Fix this by adding another source file to the test-case, and compiling it with
debug info.
Tested on aarch64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
PR testsuite/31290
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31290
|
|
When the GCC compiler plugin responds with GCC_C_FE_VERSION_2, gdb can
use the new 'finish_record_with_alignment' method. This lets gdb pass
alignment information to the compiler, which in turn fixes the test
case included in this patch.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31397
|
|
On aarch64-linux, with test-case gdb.base/watchpoint-unaligned.exp I run into:
...
(gdb) watch data.u.size8twice[1]^M
Hardware watchpoint 241: data.u.size8twice[1]^M
(gdb) PASS: gdb.base/watchpoint-unaligned.exp: watch data.u.size8twice[1]
continue^M
Continuing.^M
FAIL: gdb.base/watchpoint-unaligned.exp: continue (timeout)
FAIL: gdb.base/watchpoint-unaligned.exp: size8twice write
...
This happens as follows.
We start the exec and set an 8-byte hardware watchpoint on
data.u.size8twice[1] at address 0x440048:
...
(gdb) p sizeof (data.u.size8twice[1])
$1 = 8
(gdb) p &data.u.size8twice[1]
$2 = (uint64_t *) 0x440048 <data+16>
...
We continue execution, and a 16-byte write at address 0x440040 triggers the
hardware watchpoint:
...
4101c8: a9000801 stp x1, x2, [x0]
...
When checking whether a watchpoint has triggered in
aarch64_stopped_data_address, we check against address 0x440040 (passed in
parameter addr_trap). This behaviour is documented:
...
/* ADDR_TRAP reports the first address of the memory range
accessed by the CPU, regardless of what was the memory
range watched. ... */
...
and consequently the matching logic compares against an addr_watch_aligned:
...
&& addr_trap >= addr_watch_aligned
&& addr_trap < addr_watch + len)
...
However, the comparison fails:
...
(gdb) p /x addr_watch_aligned
$3 = 0x440048
(gdb) p addr_trap >= addr_watch_aligned
$4 = false
...
Consequently, aarch64_stopped_data_address returns false, and
stopped_by_watchpoint returns false, and watchpoints_triggered returns 0,
which make infrun think it's looking at a delayed hardware
breakpoint/watchpoint trap:
...
[infrun] handle_signal_stop: stop_pc=0x4101c8
[infrun] handle_signal_stop: delayed hardware breakpoint/watchpoint trap, ignoring
...
Infrun then ignores the trap and continues, but runs into the same situation
again and again, causing a hang which then causes the test timeout.
Fix this by allowing a match 8 bytes below addr_watch_aligned. This
introduces the possibility for false positives, so we only do this for regular
"value changed" watchpoints.
An earlier version of this patch worked by aligning addr_watch_aligned to 16
instead of 8:
...
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
+ const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 16);
...
but while that fixed the test-case, it didn't fix the problem completely, so
extend the test-case to check more scenarios.
Tested on aarch64-linux.
Tested-By: Luis Machado <luis.machado@arm.com>
Approved-By: Luis Machado <luis.machado@arm.com>
PR tdep/29423
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423
|
|
The other day on irc, we were discussing the "m_line" hack in
tui-out.c, and I mentioned that it would be nice to replace this with
a new ui_out_flag.
Later, I looked at ui_out_flag and found:
ui_source_list = (1 << 0),
... and sure enough, this is tested already.
This patch removes tui-out.[ch] and changes the TUI to use an ordinary
cli-out object without this flag set.
As far as I can tell, this doesn't affect behavior at all -- the TUI
tests all pass, and interactively I tried switching stack frames,
"list", etc, and it all seems to work.
New in v2: fixed the problem pointed out by Keith, and added a test
case for that scenario.
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
|
|
commit f18fc7e5 ("gdb, types: Resolve pointer types dynamically")
caused a regression on a test case in the AdaCore internal test suite.
The issue here is that gdb would try to resolve the type of a dynamic
pointer that happened to be NULL. In this case, the "Location address
is not set." error would end up being thrown from the DWARF expression
evaluator.
I think it makes more sense to special-case NULL pointers and not try
to resolve their target type, as that type can't really be accessed
anyway.
This patch implements this idea, and also adds the missing Ada test
case.
|
|
A Python file in my previous commit (5eb2254a1d1) was formatted with
an older version of black, which gives slightly different results.
Reformat with a newer version of black. This should make our
post-commit testing happy again.
No functional changes in this commit.
|
|
This started with a Red Hat bug report which can be seen here:
https://bugzilla.redhat.com/show_bug.cgi?id=1850710
The problem reported here was using GDB on GNU/Linux for S390, the
user stepped into JIT generated code. As they enter the JIT code GDB
would report 'PC not saved', and this same message would be reported
after each step/stepi.
Additionally, the user had 'set disassemble-next-line on', and once
they entered the JIT code this output was not displayed, nor were any
'display' directives displayed.
The user is not making use of the JIT plugin API to provide debug
information. But that's OK, they aren't expecting any source level
debug here, they are happy to use 'stepi', but the missing 'display'
directives are a problem, as is the constant 'PC not saved' (error)
message.
What is happening here is that as GDB is failing to find any debug
information for the JIT generated code, it is falling back on to the
S390 prologue unwinder to try and unwind frame #0. Unfortunately,
without being able to identify the function boundaries, the S390
prologue scanner can't help much, in fact, it doesn't even suggest an
arbitrary previous $pc value (some targets that use a link-register
will, by default, assume the link-register contains the previous $pc),
instead the S390 will just say, "sorry, I have no previous $pc value".
The result of this is that when GDB tries to find frame #1 we end
throwing an error from frame_unwind_pc (the 'PC not saved' error).
This error is not caught anywhere except at the top-level interpreter
loop, and so we end up skipping all the 'display' directive handling.
While thinking about this, I wondered, could I trigger the same error
using the Python Unwinder API? What happens if a Python unwinder
claims a frame, but then fails to provide a previous $pc value?
Turns out that exactly the same thing happens, which is great, as that
means we now have a way to reproduce this bug on any target. And so
the test included with this patch does just this. I have a Python
unwinder that claims a frame, but doesn't provide any previous
register values.
I then do two tests, first I stop in the claimed frame (i.e. frame #0
is the frame that can't be unwound), I perform a few steps, and check
the backtrace. And second, I stop in a child of the problem
frame (i.e. frame #1 is the frame that can't be unwound), and from
here I check the backtrace.
While all this is going on I have a 'display' directive in place, and
each time GDB stops I check that the display directive triggers.
Additionally, when checking the backtrace, I am checking that the
backtrace finishes with the message 'Backtrace stopped: frame did not
save the PC'.
As for the fix I chose to add a call to frame_unwind_pc directly to
get_prev_frame_always_1. Calling frame_unwind_pc will cache the
unwound $pc value, so this doesn't add much additional work as
immediately after the new frame_unwind_pc call, we call
get_prev_frame_maybe_check_cycle, which actually generates the
previous frame, which will always (I think) require a call to
frame_unwind_pc anyway.
The reason for adding the frame_unwind_pc call into
get_prev_frame_always_1, is that if the frame_unwind_pc call fails we
want to set the frames 'stop_reason', and get_prev_frame_always_1
seems to be the place where this is done, so I wanted to keep the new
stop_reason setting code next to all the existing stop_reason setting
code.
Additionally, once we enter get_prev_frame_maybe_check_cycle we
actually create the previous frame, then, if it turns out that the
previous frame can't be created we need to remove the frame .. this
seemed more complex than just making the check in
get_prev_frame_always_1.
With this fix in place the original S390 bug is fixed, and also the
test added in this commit, that uses the Python API, is also fixed.
Reviewed-By: Kevin Buettner <kevinb@redhat.com>
|
|
The test gdb.threads/threadcrash.exp demanded GDB to fully unwind and
print the names of all functions. However, some of the functions are
from the libc library, and so the test implicitly demanded libc symbols
to be available, and would fail otherwise, as was raised in PR
gdb/31293.
This commit changes it so we only explicitly check for functions that
are not provided by threadcrash.c if they are indeed available.
Tested on arm-linux and x86_64-linux.
Approved-By: Tom de Vries <tdevries@suse.de>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31293
|
|
I noticed in gdb.threads/threadcrash.exp that the usage of test_list is
somewhat convoluted.
Simplify the test-case by storing a classification instead of a pattern in
test_list.
Tested on arm-linux and x86_64-linux.
|
|
A linaro PR [1] reports that the gdb.threads/threadcrash.exp test-case fails
to cout the number of threads in the inferior:
...
FAIL: gdb.threads/threadcrash.exp: test_gcore: $thread_count == 7
FAIL: gdb.threads/threadcrash.exp: test_gcore: $thread_count == [llength $test_list]
...
Fix this by getting the convenience variable _inferior_thread_count as opposed
to calculating it based on the output of "info threads".
Tested on arm-linux and x86_64-linux.
Reviewed-By: Lancelot Six <lancelot.six@amd.com>
Approved-By: Tom de Vries <tdevries@suse.de>
[1] https://linaro.atlassian.net/browse/GNU-1120
|
|
With check-readmore, I run into:
...
FAIL: gdb.threads/threadcrash.exp: test_corefile: \
$thread_count == [llength $test_list]
...
The problem is that the clauses in the gdb_test_multiple for
"thread apply all backtrace" intent to match one line, but actually can
match more than one line, and consequently a match for one type of thread can
consume a line that was supposed to match another thread.
For instance, there's this regexp:
...
-re "\[^\n\]*syscall_task .location=SIGNAL_ALT_STACK\[^\n\]*" {
...
It's limited at the end by \[^\n\]*, meaning the match stops at the end of the
line.
But it doesn't start with a ^, and consequently can match more than one line.
The "\[^\n\]*" at the start doesn't prevent this, there's an implicit .* at
the start of each pattern, unless it's anchored using a ^.
Fix this by rewriting the regexps in a "^\r\n$hs$regexp$hs$eol" style, where:
- hs is: \[^\n\]* (horizontal space), and
- eol is (?=\r\n) (look-ahead end-of-line).
It also turned out to be necessary to drop the -lbl switch, and introduce a
corresponding explicit clause. The -lbl clause is placed ALAP, and
consequently allowed the default fail clause to trigger.
Tested on arm-linux and x86_64-linux.
|
|
In test-case gdb.threads/threadcrash.exp we have an unnecessarily indented
gdb_test_multiple:
...
gdb_test_multiple "thread apply all backtrace" \
"Get thread information" -lbl {
-re "#\[0-9\]+\\\?\\\?\[^\n\]*" {
...
Fix this by moving the command into a variable, allowing the
"gdb_test_multiple ... {" to fit on a single 80 chars line.
Tested on arm-linux and x86_64-linux.
|
|
With python 3.12, I run into:
...
(gdb) PASS: gdb.python/py-block.exp: check variable access
python print (block['nonexistent'])^M
Python Exception <class 'KeyError'>: 'nonexistent'^M
Error occurred in Python: 'nonexistent'^M
(gdb) FAIL: gdb.python/py-block.exp: check nonexistent variable
...
The problem is that that PyErr_Fetch returns a normalized exception, while the
test-case matches the output for an unnormalized exception.
With python 3.6, PyErr_Fetch returns an unnormalized exception, and the
test passes.
Fix this by:
- updating the test-case to match the output for a normalized exception, and
- lazily forcing normalized exceptions using PyErr_NormalizeException.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
A bug report in the DAP specification repository pointed out that it
is typical for DAP implementations to put a function's return value
into the outermost scope.
This patch changes gdb to follow this convention.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31341
Reviewed-By: Kévin Le Gouguec <legouguec@adacore.com>
|
|
This fixes some duplicate test names in gdb.trace/circ.exp when using
native-gdbserver and native-extended-gdbserver boards.
In this test we set the trace buffer size twice. The same test name
was used each time the size was adjusted.
I've fixed this issue by:
1. Creating a new proc, set_trace_buffer_size, which factors out the
code to change the buffer size, and uses test names based on the
size we're setting the buffer too,
2. Calling the new proc each time we want to adjust the buffer size.
After this the duplicate test names are resolved. There should be no
change in what is tested after this commit.
|
|
This commit fixes some duplicate test names in the gdb.trace/
directory when run with the native-gdbserver and
native-extended-gdbserver boards. In this case the duplicates relate
to the calls to gdb_compile_pthreads which emits a fixed PASS message,
as there are two calls to gdb_compile_pthreads we get a duplicate PASS
message.
In both cases the problem is fixed by adding a with_test_prefix around
one of the compilations, however, I've made additional changes to
clean up the tests a little while I was working on them:
1. Switch to use prepare_for_testing instead of
gdb_compile_pthreads. By passing the 'pthreads' option this does
call gdb_compile_pthreads under the hood, but using the standard
compile function is cleaner,
2. Using prepare_for_testing removes the need to call clean_restart
immediately afterwards, so those calls are removed,
3. I removed the unneeded $executable and $expfile globals, where
the $executable global was used I've replaced this with $binfile,
4. When we compile two executables I've now given these different
names so that both exist at the end of the test run,
5. Removed a gdb_reinitialize_dir call, this is covered by
clean_restart,
6. Use gdb_test_no_output where it makes sense.
I now see no duplicate test names when running these test scripts.
There should be no change in what is being tested after this commit.
|
|
In a couple of spots, the TUI tries to center some text in the window.
Andrew noticed that the calculation is done strangely and the text
ends up somewhat to the left of center.
This patch fixes the problem.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31355
|
|
This changes the DAP code to explicitly request that gdb exit.
Previously this could cause crashes, but with the previous cleanups,
this should no longer happen.
This also adds a tests that ensures that gdb exits with status 0.
|
|
Tom de Vries pointed out that the gdb.dap/pause.exp test writes a
Python file but then does not use it. This patch corrects the
oversight.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
Reviewed-By: Tom de Vries <tdevries@suse.de>
|
|
The "python" command (and the Python implementation of the gdb
"source" command) does not handle Python exceptions in the same way as
other gdb-facing Python code. In particular, exceptions are turned
into a generic error rather than being routed through
gdbpy_handle_exception, which takes care of converting to 'quit' as
appropriate.
I think this was done this way because PyRun_SimpleFile and friends do
not propagate the Python exception -- they simply indicate that one
occurred.
This patch reimplements these functions to respect the general gdb
convention here. As a bonus, some Windows-specific code can be
removed, as can the _execute_file function.
The bulk of this change is tweaking the test suite to match the new
way that exceptions are displayed. These changes are largely
uninteresting. However, it's worth pointing out the py-error.exp
change. Here, the failure changes because the test changes the host
charset to something that isn't supported by Python. This then
results in a weird error in the new setup.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
Acked-By: Tom de Vries <tdevries@suse.de>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
|
Say we do:
...
$ make check RUNTESTFLAGS="gdb.dap/ada-nested.exp gdb.dap/pause.exp"
...
and add a perror at the end of pause.exp:
...
dap_shutdown
+
+perror "foo"
...
We run into:
...
UNRESOLVED: gdb.dap/ada-nested.exp: compilation prog.adb
...
This happens because the perror increases the errcnt, which is not reset at
the end of the test-case, and consequently the first pass in the following
test-case is changed into an unresolved.
Version 1.6.3 of dejagnu contains a fix which produces an unresolved at the
end of the test-case, which does reset the errcnt, but this is with version
1.6.1.
Furthermore, we reset the errcnt in clean_restart, but the pass is produced
before, so that doesn't help either.
Fix this by resetting errcnt and warncnt in default_gdb_init.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31351
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31351
|
|
PR ada/30908 turns out to be a duplicate of PR ada/12607, which was fixed by
commit d56fdf1b976 ("Refine Ada overload matching").
Remove the KFAILs for PR ada/30908.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30908
|
|
With test-case gdb.python/py-finish-breakpoint.exp, we run into:
...
(gdb) python print (finishbp_default.hit_count)
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Breakpoint 3 is invalid.
Error while executing Python code.
(gdb) PASS: gdb.python/py-finish-breakpoint.exp: normal conditions: \
check finishBP on default frame has been hit
...
The test producing the pass is:
...
gdb_test "python print (finishbp_default.hit_count)" "1.*" \
"check finishBP on default frame has been hit"
...
so the pass is produced because the 1 in "line 1" matches "1.*".
Temporary breakpoints are removed when hit, and consequently accessing the
hit_count attribute of a temporary python breakpoint (gdb.Breakpoint class) is
not possible, and as per spec we get a RuntimeError.
So the RuntimeError is correct, and not specific to finish breakpoints.
The test presumably attempts to match:
...
(gdb) python print (finishbp_default.hit_count)
1
...
but most likely this output was never produced by any gdb version.
Fix this by checking whether the finishbp_default breakpoint has hit by
checking that finishbp_default.is_valid() is False.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31391
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31391
|
|
arc-analyze-prologue.S test does not contain debug information thus
it must be compiled without -g option. Otherwise GDB will try to
unwind frames using debug information (which does not exist for .S
code!) instead of analyzing frames manually.
Approved-By: Shahab Vahedi <shahab@synopsys.com>
|
|
For a patch I submitted, the Linaro CI reported a failure:
...
FAIL: gdb.dap/attach.exp: exceptions in log file
...
I ran the test-case locally, and observed the same FAIL in the gdb.sum file.
I then wanted to confirm that I reproduced the exact same problem, but
realized that I couldn't because there's no way for me to know what exception
occurred, and where, because that information is logged in the dap.log.$n
file, and the Linaro CI only saves the gdb.sum and gdb.log files.
This issue is even worse if only the CI can reproduce a FAIL.
Fix this in dap_check_log_file by dumping dap.log.$n to gdb.log when
exceptions are found.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
In commit 52498004a34 ("gdb/testsuite: handle long filenames in
gdb.base/startup-with-shell.exp") we fixed a FAIL reported by the Linaro CI:
...
(gdb) print argv[1]
$1 = 0xfffed978 "<snip>/startup-with-shell/unique-file.unique-e"...
(gdb) FAIL: gdb.base/startup-with-shell.exp: startup_with_shell = on; \
run_args = *.unique-extension: first argument expanded
...
PR testsuite/31410 reports a similar failure:
...
(gdb) print argv[1]
$1 = 0xfffeda96 "<snip>/startup-with-shell/*.unique-extens"...
(gdb) FAIL: gdb.base/startup-with-shell.exp: startup_with_shell = off; \
run_args = *.unique-extension: first argument not expanded
...
Fix this in the same way, using "set print characters unlimited".
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31410
|
|
On arm-linux, with a started hello world, running "info frame" works fine, but
when I set debug frame to on, I run into:
...
(gdb) info frame
...
[frame] frame_unwind_register_value: exit
value is not available
(gdb)
...
The problem is here in frame_unwind_register_value:
...
if (value->lazy ())
gdb_printf (&debug_file, " lazy");
else
{
int i;
gdb::array_view<const gdb_byte> buf = value->contents ();
...
where we call value->contents () while !value->entirely_available ().
Fix this by checking value->entirely_available () and printing:
...
[frame] frame_unwind_register_value: -> register=91 unavailable
...
Tested on arm-linux.
PR gdb/31369
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31369
|
|
The output of "info breakpoints" includes breakpoint, watchpoint,
tracepoint, and catchpoint if they are created, so it should show
all the four types are deleted in the output of "info breakpoints"
to report empty list after "delete breakpoints".
It should also change the output of "delete breakpoints" to make it
clear that watchpoints, tracepoints, and catchpoints are also being
deleted. This is suggested by Guinevere Larsen, thank you.
$ make check-gdb TESTS="gdb.base/access-mem-running.exp"
$ gdb/gdb gdb/testsuite/outputs/gdb.base/access-mem-running/access-mem-running
[...]
(gdb) break main
Breakpoint 1 at 0x12000073c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 32.
(gdb) watch global_counter
Hardware watchpoint 2: global_counter
(gdb) trace maybe_stop_here
Tracepoint 3 at 0x12000071c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 27.
(gdb) catch fork
Catchpoint 4 (fork)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000012000073c in main at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:32
2 hw watchpoint keep y global_counter
3 tracepoint keep y 0x000000012000071c in maybe_stop_here at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:27
not installed on target
4 catchpoint keep y fork
Without this patch:
(gdb) delete breakpoints
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) info breakpoints 3
No breakpoint or watchpoint matching '3'.
With this patch:
(gdb) delete breakpoints
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb) info breakpoints 3
No breakpoint, watchpoint, tracepoint, or catchpoint matching '3'.
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Approved-by: Kevin Buettner <kevinb@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
|
I noticed in gdb.reverse/map-to-same-line.{c,exp} that the license urls are
using some kind of indirection via urldefense.proofpoint.com.
Fix this by removing this indirection.
Tested on x86_64-linux.
PR testsuite/31358
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31358
|
|
When DAP shuts down due to an EOF event, there's a race between:
- gdb's main thread handling a SIGHUP, and
- the DAP main thread exiting.
Fix this by waiting for DAP's main thread exit during the gdb_exiting event.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR dap/31380
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31380
|
|
In dap_gdb_start we do:
...
append GDBFLAGS " -iex \"set debug dap-log-file $logfile\" -q -i=dap"
...
While the dap log file setting comes before the dap interpreter setting,
the order is the other way around:
- first, the dap interpreter is started
- second, the -iex commands are executed and the log file is initialized.
Consequently, there's a race between dap interpreter startup and dap log file
initialization.
This cannot be fixed by using -eiex instead. Before the interpreter is
started, the "set debug dap-log-file" command is not yet registered.
Fix this by postponing the start of the DAP server until GDB has processed all
command files.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR dap/31386
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31386
|
|
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
|
|
DBNZ instruction was moved from BRANCH class to a separate one - DBNZ.
Thus, it must be processed separately in arc_insn_get_branch_target
to correctly determine an offset for a possible branch.
The testsuite for DBNZ instruction verifies these cases:
1. Check that dbnz does not branch and falls through if its source
register is 0 after decrementing. GDB must successfully break
on the following instruction after stepping over.
2. Check that dbnz branches to the target correctly if its source register
is not 0 after decrementing - GDB must successfully break on the target
instruction if a forward branch is performed after stepping over.
3. The same as point 2 but for a backward branching case.
Signed-off-by: Yuriy Kolerov <kolerov93@gmail.com>
|
|
While debugging a slow-down in test-case gdb.dap/type_checker.exp due to a WIP
patch, I noticed that test-case gdb.dap/type_checker.exp doesn't have a dap
log file.
This is normally set up by dap_gdb_start, but the test-case doesn't use it.
Fix this by doing "set debug dap-log-file $logfile" in the test-case.
To make it easy to do so, I've factored out a new proc new_dap_log_file, and
while at likewise a new proc current_dap_log_file.
Note that the log file is currently empty.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This patch rewrites the handling of slice types in Rust.
More recent versions of the Rust compiler changed how unsized types
were emitted, letting gdb inspect them more nicely. However, gdb did
not do this, and in fact treated all such types as if they were slices
of arrays, which is incorrect.
This patch rewrites this handling and removes the restriction that
unsized types must be array slices. I've added a comment explaining
how unsized types are represented to rust-lang.c as well.
I looked into a different approach, namely changing the DWARF reader
to fix up slice types to have a dynamic type. However, the approach
taken here turned out to be simpler.
Tested on x86-64 Fedora 38 with a variety of Rust compiler versions.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30330
|
|
In the recent patch titled "gdb, python: selectively omit enabling
stdin in gdb.execute", the black tool found formatting issues. Fix
them.
|
|
From the Python API, we can execute GDB commands via gdb.execute. If
the command gives an exception, however, we need to recover the GDB
prompt and enable stdin, because the exception does not reach
top-level GDB or normal_stop. This was done in commit
commit 1ba1ac88011703abcd0271e4f5d00927dc69a09a
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date: Tue Nov 19 11:17:20 2019 +0000
gdb: Enable stdin on exception in execute_gdb_command
with the following code:
catch (const gdb_exception &except)
{
/* If an exception occurred then we won't hit normal_stop (), or have
an exception reach the top level of the event loop, which are the
two usual places in which stdin would be re-enabled. So, before we
convert the exception and continue back in Python, we should
re-enable stdin here. */
async_enable_stdin ();
GDB_PY_HANDLE_EXCEPTION (except);
}
In this patch, we explain what happens when we run a GDB command in
the context of a synchronous command, e.g. via Python observer
notifications.
As an example, suppose we have the following objfile event listener,
specified in a file named file.py:
~~~
import gdb
class MyListener:
def __init__(self):
gdb.events.new_objfile.connect(self.handle_new_objfile_event)
self.processed_objfile = False
def handle_new_objfile_event(self, event):
if self.processed_objfile:
return
print("loading " + event.new_objfile.filename)
self.processed_objfile = True
gdb.execute('add-inferior -no-connection')
gdb.execute('inferior 2')
gdb.execute('target remote | gdbserver - /tmp/a.out')
gdb.execute('inferior 1')
the_listener = MyListener()
~~~
Using this Python file, we see the behavior below:
$ gdb -q -ex "source file.py" -ex "run" --args a.out
Reading symbols from a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
[New inferior 2]
Added inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
stdin/stdout redirected
Process /tmp/a.out created; pid = 3075406
Remote debugging using stdio
Reading /tmp/a.out from remote target...
...
[Switching to inferior 1 [process 3075400] (/tmp/a.out)]
[Switching to thread 1.1 (process 3075400)]
#0 0x00007ffff7fe3290 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) [Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Inferior 1 (process 3075400) exited normally]
Note how the GDB prompt comes in-between the debugger output. We have this
obscure behavior, because the executed command, "target remote", triggers
an invocation of `normal_stop` that enables stdin. After that, however,
the Python notification context completes and GDB continues with its normal
flow of executing the 'run' command. This can be seen in the call stack
below:
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x00005555561c3acd in normal_stop () at src/gdb/infrun.c:9432
#2 0x00005555561b328e in start_remote (from_tty=0) at src/gdb/infrun.c:3801
#3 0x0000555556441224 in remote_target::start_remote_1 (this=0x5555587882e0, from_tty=0, extended_p=0) at src/gdb/remote.c:5225
#4 0x000055555644166c in remote_target::start_remote (this=0x5555587882e0, from_tty=0, extended_p=0) at src/gdb/remote.c:5316
#5 0x00005555564430cf in remote_target::open_1 (name=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0, extended_p=0) at src/gdb/remote.c:6175
#6 0x0000555556441707 in remote_target::open (name=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0) at src/gdb/remote.c:5338
#7 0x00005555565ea63f in open_target (args=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0, command=0x555558589280) at src/gdb/target.c:824
#8 0x0000555555f0d89a in cmd_func (cmd=0x555558589280, args=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0) at src/gdb/cli/cli-decode.c:2735
#9 0x000055555661fb42 in execute_command (p=0x55555878529e "t", from_tty=0) at src/gdb/top.c:575
#10 0x0000555555f1a506 in execute_control_command_1 (cmd=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:529
#11 0x0000555555f1abea in execute_control_command (cmd=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:701
#12 0x0000555555f19fc7 in execute_control_commands (cmdlines=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:411
#13 0x0000555556400d91 in execute_gdb_command (self=0x7ffff43b5d00, args=0x7ffff440ab60, kw=0x0) at src/gdb/python/python.c:700
#14 0x00007ffff7a96023 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#15 0x00007ffff7a4dadc in _PyObject_MakeTpCall () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#16 0x00007ffff79e9a1c in _PyEval_EvalFrameDefault () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#17 0x00007ffff7b303af in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#18 0x00007ffff7a50358 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#19 0x00007ffff7a4f3f4 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#20 0x00007ffff7a4f883 in PyObject_CallFunctionObjArgs () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#21 0x00005555563a9758 in evpy_emit_event (event=0x7ffff42b5430, registry=0x7ffff42b4690) at src/gdb/python/py-event.c:104
#22 0x00005555563cb874 in emit_new_objfile_event (objfile=0x555558761700) at src/gdb/python/py-newobjfileevent.c:52
#23 0x00005555563b53bc in python_new_objfile (objfile=0x555558761700) at src/gdb/python/py-inferior.c:195
#24 0x0000555555d6dff0 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:61
#25 0x0000555555d6be18 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:111
#26 0x0000555555d69661 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffd080: 0x555558761700) at /usr/include/c++/11/bits/std_function.h:290
#27 0x0000555556314caf in std::function<void (objfile*)>::operator()(objfile*) const (this=0x5555585b5860, __args#0=0x555558761700) at /usr/include/c++/11/bits/std_function.h:590
#28 0x000055555631444e in gdb::observers::observable<objfile*>::notify (this=0x55555836eea0 <gdb::observers::new_objfile>, args#0=0x555558761700) at src/gdb/../gdbsupport/observable.h:166
#29 0x0000555556599b3f in symbol_file_add_with_addrs (abfd=..., name=0x55555875d310 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1125
#30 0x0000555556599ca4 in symbol_file_add_from_bfd (abfd=..., name=0x55555875d310 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1160
#31 0x0000555556546371 in solib_read_symbols (so=..., flags=...) at src/gdb/solib.c:692
#32 0x0000555556546f0f in solib_add (pattern=0x0, from_tty=0, readsyms=1) at src/gdb/solib.c:1015
#33 0x0000555556539891 in enable_break (info=0x55555874e180, from_tty=0) at src/gdb/solib-svr4.c:2416
#34 0x000055555653b305 in svr4_solib_create_inferior_hook (from_tty=0) at src/gdb/solib-svr4.c:3058
#35 0x0000555556547cee in solib_create_inferior_hook (from_tty=0) at src/gdb/solib.c:1217
#36 0x0000555556196f6a in post_create_inferior (from_tty=0) at src/gdb/infcmd.c:275
#37 0x0000555556197670 in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at src/gdb/infcmd.c:486
#38 0x000055555619783f in run_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:512
#39 0x0000555555f0798d in do_simple_func (args=0x0, from_tty=1, c=0x555558567510) at src/gdb/cli/cli-decode.c:95
#40 0x0000555555f0d89a in cmd_func (cmd=0x555558567510, args=0x0, from_tty=1) at src/gdb/cli/cli-decode.c:2735
#41 0x000055555661fb42 in execute_command (p=0x7fffffffe2c4 "", from_tty=1) at src/gdb/top.c:575
#42 0x000055555626303b in catch_command_errors (command=0x55555661f4ab <execute_command(char const*, int)>, arg=0x7fffffffe2c1 "run", from_tty=1, do_bp_actions=true) at src/gdb/main.c:513
#43 0x000055555626328a in execute_cmdargs (cmdarg_vec=0x7fffffffdaf0, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffda3c) at src/gdb/main.c:612
#44 0x0000555556264849 in captured_main_1 (context=0x7fffffffdd40) at src/gdb/main.c:1293
#45 0x0000555556264a7f in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1314
#46 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#47 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
The use of the "target remote" command here is just an example. In
principle, we would reproduce the problem with any command that
triggers an invocation of `normal_stop`.
To omit enabling the stdin in `normal_stop`, we would have to check the
context we are in. Since we cannot do that, we add a new field to
`struct ui` to track whether the prompt was already blocked, and set
the tracker flag in the Python context before executing a GDB command.
After applying this patch, the output becomes
...
Reading symbols from a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
[New inferior 2]
Added inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
stdin/stdout redirected
Process /tmp/a.out created; pid = 3032261
Remote debugging using stdio
Reading /tmp/a.out from remote target...
...
[Switching to inferior 1 [process 3032255] (/tmp/a.out)]
[Switching to thread 1.1 (process 3032255)]
#0 0x00007ffff7fe3290 in ?? () from /lib64/ld-linux-x86-64.so.2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Inferior 1 (process 3032255) exited normally]
(gdb)
Let's now consider a secondary scenario, where the command executed from
the Python raises an error. As an example, suppose we have the Python
file below:
def handle_new_objfile_event(self, event):
...
print("loading " + event.new_objfile.filename)
self.processed_objfile = True
gdb.execute('print a')
The executed command, "print a", gives an error because "a" is not
defined. Without this patch, we see the behavior below, where the
prompt is again placed incorrectly:
...
Reading symbols from /tmp/a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
Python Exception <class 'gdb.error'>: No symbol "a" in current context.
(gdb) [Inferior 1 (process 3980401) exited normally]
This time, `async_enable_stdin` is called from the 'catch' block in
`execute_gdb_command`:
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x0000555556400f0a in execute_gdb_command (self=0x7ffff43b5d00, args=0x7ffff440ab60, kw=0x0) at src/gdb/python/python.c:713
#2 0x00007ffff7a96023 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#3 0x00007ffff7a4dadc in _PyObject_MakeTpCall () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#4 0x00007ffff79e9a1c in _PyEval_EvalFrameDefault () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#5 0x00007ffff7b303af in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#6 0x00007ffff7a50358 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#7 0x00007ffff7a4f3f4 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#8 0x00007ffff7a4f883 in PyObject_CallFunctionObjArgs () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#9 0x00005555563a9758 in evpy_emit_event (event=0x7ffff42b5430, registry=0x7ffff42b4690) at src/gdb/python/py-event.c:104
#10 0x00005555563cb874 in emit_new_objfile_event (objfile=0x555558761410) at src/gdb/python/py-newobjfileevent.c:52
#11 0x00005555563b53bc in python_new_objfile (objfile=0x555558761410) at src/gdb/python/py-inferior.c:195
#12 0x0000555555d6dff0 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:61
#13 0x0000555555d6be18 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:111
#14 0x0000555555d69661 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffd080: 0x555558761410) at /usr/include/c++/11/bits/std_function.h:290
#15 0x0000555556314caf in std::function<void (objfile*)>::operator()(objfile*) const (this=0x5555585b5860, __args#0=0x555558761410) at /usr/include/c++/11/bits/std_function.h:590
#16 0x000055555631444e in gdb::observers::observable<objfile*>::notify (this=0x55555836eea0 <gdb::observers::new_objfile>, args#0=0x555558761410) at src/gdb/../gdbsupport/observable.h:166
#17 0x0000555556599b3f in symbol_file_add_with_addrs (abfd=..., name=0x55555875d020 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1125
#18 0x0000555556599ca4 in symbol_file_add_from_bfd (abfd=..., name=0x55555875d020 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1160
#19 0x0000555556546371 in solib_read_symbols (so=..., flags=...) at src/gdb/solib.c:692
#20 0x0000555556546f0f in solib_add (pattern=0x0, from_tty=0, readsyms=1) at src/gdb/solib.c:1015
#21 0x0000555556539891 in enable_break (info=0x55555874a670, from_tty=0) at src/gdb/solib-svr4.c:2416
#22 0x000055555653b305 in svr4_solib_create_inferior_hook (from_tty=0) at src/gdb/solib-svr4.c:3058
#23 0x0000555556547cee in solib_create_inferior_hook (from_tty=0) at src/gdb/solib.c:1217
#24 0x0000555556196f6a in post_create_inferior (from_tty=0) at src/gdb/infcmd.c:275
#25 0x0000555556197670 in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at src/gdb/infcmd.c:486
#26 0x000055555619783f in run_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:512
#27 0x0000555555f0798d in do_simple_func (args=0x0, from_tty=1, c=0x555558567510) at src/gdb/cli/cli-decode.c:95
#28 0x0000555555f0d89a in cmd_func (cmd=0x555558567510, args=0x0, from_tty=1) at src/gdb/cli/cli-decode.c:2735
#29 0x000055555661fb42 in execute_command (p=0x7fffffffe2c4 "", from_tty=1) at src/gdb/top.c:575
#30 0x000055555626303b in catch_command_errors (command=0x55555661f4ab <execute_command(char const*, int)>, arg=0x7fffffffe2c1 "run", from_tty=1, do_bp_actions=true) at src/gdb/main.c:513
#31 0x000055555626328a in execute_cmdargs (cmdarg_vec=0x7fffffffdaf0, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffda3c) at src/gdb/main.c:612
#32 0x0000555556264849 in captured_main_1 (context=0x7fffffffdd40) at src/gdb/main.c:1293
#33 0x0000555556264a7f in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1314
#34 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#35 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
Again, after we enable stdin, GDB continues with its normal flow
of the 'run' command and receives the inferior's exit event, where
it would have enabled stdin, if we had not done it prematurely.
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x00005555561c3acd in normal_stop () at src/gdb/infrun.c:9432
#2 0x00005555561b5bf1 in fetch_inferior_event () at src/gdb/infrun.c:4700
#3 0x000055555618d6a7 in inferior_event_handler (event_type=INF_REG_EVENT) at src/gdb/inf-loop.c:42
#4 0x000055555620ecdb in handle_target_event (error=0, client_data=0x0) at src/gdb/linux-nat.c:4316
#5 0x0000555556f33035 in handle_file_event (file_ptr=0x5555587024e0, ready_mask=1) at src/gdbsupport/event-loop.cc:573
#6 0x0000555556f3362f in gdb_wait_for_event (block=0) at src/gdbsupport/event-loop.cc:694
#7 0x0000555556f322cd in gdb_do_one_event (mstimeout=-1) at src/gdbsupport/event-loop.cc:217
#8 0x0000555556262df8 in start_event_loop () at src/gdb/main.c:407
#9 0x0000555556262f85 in captured_command_loop () at src/gdb/main.c:471
#10 0x0000555556264a84 in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1324
#11 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#12 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
The solution implemented by this patch addresses the problem. After
applying the patch, the output becomes
$ gdb -q -ex "source file.py" -ex "run" --args a.out
Reading symbols from /tmp/a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
Python Exception <class 'gdb.error'>: No symbol "a" in current context.
[Inferior 1 (process 3984511) exited normally]
(gdb)
Regression-tested on X86_64 Linux using the default board file (i.e. unix).
Co-Authored-By: Oguzhan Karakaya <oguzhan.karakaya@intel.com>
Reviewed-By: Guinevere Larsen <blarsen@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
When building gdb with -O0 -fsanitize=address, and running test-case
gdb.ada/uninitialized_vars.exp, I run into:
...
(gdb) info locals
a = 0
z = (a => 1, b => false, c => 2.0)
=================================================================
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
READ of size 4 at 0x602000097f58 thread T0
#0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
#1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
#2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
#3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
#4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
#5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
#6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
#7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
#8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
#9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
#10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
#11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
#12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
#13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
#14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
#15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
#16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
#17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
#18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
#19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
#20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
#21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
#22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
#23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
#24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
#25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
#26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
#27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
#28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
#29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
#30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
#31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
#32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
#33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
#34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
#35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
#36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
#37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
#38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
#39 0x1768080 in start_event_loop gdb/main.c:408
#40 0x17684c4 in captured_command_loop gdb/main.c:472
#41 0x176cfc8 in captured_main gdb/main.c:1342
#42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
#43 0xb73edc in main gdb/gdb.c:39
#44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
#45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
#46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)
0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
allocated by thread T0 here:
#0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
#1 0xcbc278 in xcalloc gdb/alloc.c:97
#2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
#3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
#4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
#5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
#6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
#7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
#8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
#9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
#10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
#11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
#12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
#13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
#14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
#15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
#16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
#17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
#18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
#19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
#20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
#21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
#22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
#23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
#24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
#25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
#26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
#27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
#28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
#29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
...
The error happens when trying to print either variable y or y2:
...
type Variable_Record (A : Boolean := True) is record
case A is
when True =>
B : Integer;
when False =>
C : Float;
D : Integer;
end case;
end record;
Y : Variable_Record := (A => True, B => 1);
Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
...
when the variables are uninitialized.
The error happens only when printing the entire variable:
...
(gdb) p y.a
$2 = 216
(gdb) p y.b
There is no member named b.
(gdb) p y.c
$3 = 9.18340949e-41
(gdb) p y.d
$4 = 1
(gdb) p y
<AddressSanitizer: heap-buffer-overflow>
...
The error happens as follows:
- field a functions as discriminant, choosing either the b, or c+d variant.
- when y.a happens to be set to 216, as above, gdb interprets this as the
variable having the c+d variant (which is why trying to print y.b fails).
- when printing y, gdb allocates a value, copies the bytes into it from the
target, and then prints the value.
- gdb allocates the value using the type size, which is 8. It's 8 because
that's what the DW_AT_byte_size indicates. Note that for valid values of a,
it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
(b variant), size is 8.
- gdb tries to print field d, which is at an 8 byte offset, and that results
in a out-of-bounds access for the allocated 8-byte value.
Fix this by handling this case in value::contents_copy_raw, such that we have:
...
(gdb) p y
$1 = (a => 24, c => 9.18340949e-41,
d => <error reading variable: access outside bounds of object>)
...
An alternative (additional) fix could be this: in compute_variant_fields_inner
gdb reads the discriminant y.a to decide which variant is active. It would be
nice to detect that the value (y.a == 24) is not a valid Boolean, and give up
on choosing a variant altoghether. However, the situation regarding the
internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not
possible to reliably decide what valid values are.
The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
copyright years.
Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
versions. [ So, it would be nice to rewrite it into a dwarf assembly
test-case. ]
The test-case loops over all languages. This is inherited from an earlier
attempt to fix this, which had language-specific fixes (in print_field_values,
cp_print_value_fields, pascal_object_print_value_fields and
f_language::value_print_inner). I've left this in, but I suppose it's not
strictly necessary anymore.
Tested on x86_64-linux.
PR exp/31258
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
|
|
With gdb.dap/sources.exp on aarch64-linux, I'm running into:
...
{"request_seq": 3, "type": "response", "command": "loadedSources", \
"success": false, "message": "notStopped", "seq": 7}Content-Length: 92^M
^M
{"type": "event", "event": "thread", \
"body": {"reason": "started", "threadId": 1}, \
"seq": 8}FAIL: gdb.dap/sources.exp: loadedSources success
ERROR: tcl error sourcing gdb.dap/sources.exp.
ERROR: tcl error code TCL LOOKUP DICT body
ERROR: key "body" not known in dictionary
while executing
"dict get [lindex $obj 0] body sources"
...
These are the same type of tcl error and FAIL I just fixed for a later
request in the same test-case.
Fix this by:
- moving the wait-for-stop to before the loadedSources request to fix the
FAIL, and
- checking for $obj == "" to fix the tcl error.
Also make the code a bit less indented and more readable by wrapping the tests
in a proc, allowing the use of return to bail out, while still running
dap_shutdown afterwards.
Approved-By: Tom Tromey <tom@tromey.com>
Tested on aarch64-linux.
|
|
Breaking a TCL string to several lines leads to adding of extra
symbols to the resulting expect string. In turn, this leads to
failing of all test cases in gdb.arch/arc-disassembler-options.exp
testsuite. It's necessary to use multi_line function in such
cases.
Approved-By: Tom Tromey <tom@tromey.com>
|