aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
AgeCommit message (Collapse)AuthorFilesLines
2024-03-20Fix reinterpret_cast for classes with multiple inheritanceHannes Domani2-0/+18
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>
2024-03-20Fix comparison of array typesHannes Domani1-0/+1
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>
2024-03-19Speed up lookup of "type_specific_data"Tom Tromey6-0/+170
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.
2024-03-19gdb/python: test exception case for gdb.solib_nameAndrew Burgess1-0/+15
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>
2024-03-19gdb/python: Fix segfault when iterating over empty linetableToby Lloyd Davies2-0/+95
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>
2024-03-19[gdb] Further fix "value is not available" with debug frameTom de Vries1-1/+6
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.
2024-03-18Fix Ada 'ptype' of access to arrayTom Tromey2-0/+15
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.
2024-03-18Set __file__ when source'ing a Python scriptTom Tromey1-0/+3
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>
2024-03-18Clear board_info entry after waiting for processTom Tromey2-0/+16
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>
2024-03-18gdb/testsuite: attach to i386 process stopped in vDSOAndrew Burgess2-0/+80
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>
2024-03-17[gdb/testsuite] Fix gdb.base/list-no-debug.exp on debianTom de Vries3-5/+35
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
2024-03-14Pass alignment when using GCC_C_FE_VERSION_2Tom Tromey2-0/+10
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
2024-03-14[gdb/tdep] Fix gdb.base/watchpoint-unaligned.exp on aarch64Tom de Vries2-35/+54
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
2024-03-11Remove tui-out.[ch]Tom Tromey1-0/+2
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>
2024-03-11Special case NULL pointers in dynamic type resolutionTom Tromey3-2/+71
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.
2024-03-11gdb/testsuite: reformat file with a more recent version of blackAndrew Burgess1-1/+0
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.
2024-03-11gdb/unwinders: better support for $pc not savedAndrew Burgess3-0/+232
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>
2024-03-11gdb/testsuite: Reduce gdb.threads/threadcrash.exp reliance on libc symbolsGuinevere Larsen1-7/+41
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
2024-03-11gdb/testsuite: Simplify gdb.threads/threadcrash.expTom de Vries1-29/+60
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.
2024-03-11gdb/testsuite: Use _inferior_thread_count in gdb.threads/threadcrash.expGuinevere Larsen1-21/+2
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
2024-03-11gdb/testsuite: Fix gdb.threads/threadcrash.exp with check-readmoreTom de Vries1-10/+19
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.
2024-03-11gdb/testsuite: Reduce indentation in gdb.threads/threadcrash.expTom de Vries1-58/+58
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.
2024-03-09[gdb/python] Normalize exceptions in gdbpy_err_fetchTom de Vries1-1/+1
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>
2024-03-08Add return value to DAP scopeTom Tromey2-0/+118
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>
2024-03-05gdb/testsuite: fix duplicate test names in gdb.trace/circ.expAndrew Burgess1-31/+45
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.
2024-03-05gdb/testsuite: fix some more duplicate test names in gdb.trace/Andrew Burgess2-55/+46
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.
2024-03-01Fix TUI text centeringTom Tromey1-1/+4
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
2024-02-27Explicitly quit gdb from DAP server threadTom Tromey1-0/+9
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.
2024-02-27Use the .py file in gdb.dap/pause.expTom Tromey1-1/+1
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>
2024-02-27Rewrite "python" command exception handlingTom Tromey31-184/+189
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>
2024-02-27[gdb/testsuite] Reset errcnt and warncnt in default_gdb_initTom de Vries1-0/+9
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
2024-02-27[gdb/testsuite] Remove KFAIL for PR ada/30908Tom de Vries2-44/+4
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
2024-02-27[gdb/testsuite] Fix test in gdb.python/py-finish-breakpoint.expTom de Vries1-1/+2
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
2024-02-27arc: Don't build arc-analyze-prologue.S with -gYuriy Kolerov1-1/+7
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>
2024-02-26[gdb/testsuite] Dump dap.log.$n to gdb.log when exceptions foundTom de Vries1-0/+3
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>
2024-02-26[gdb/testsuite] Further handle long filenames in gdb.base/startup-with-shell.expTom de Vries1-0/+1
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
2024-02-26[gdb] Fix "value is not available" with debug frameTom de Vries3-0/+104
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
2024-02-26gdb: Modify the output of "info breakpoints" and "delete breakpoints"Tiezhu Yang40-86/+87
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>
2024-02-22[gdb/testsuite] Fix license text in gdb.reverse/map-to-same-line.{c,exp}Tom de Vries2-2/+2
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
2024-02-22[gdb/dap] Fix race between dap exit and gdb exitTom de Vries1-0/+9
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
2024-02-22[gdb/dap] Fix race between dap startup and dap log fileTom de Vries2-0/+13
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
2024-02-21[gdb/testsuite] Fix error handling in _dap_read_jsonTom de Vries1-4/+23
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
2024-02-21arc: Determine a branch target of DBNZ correctlyYuriy Kolerov2-0/+144
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>
2024-02-21[gdb/testsuite] Set up dap log file in gdb.dap/type_checker.expTom de Vries2-7/+18
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>
2024-02-20Rewrite Rust slice type handlingTom Tromey4-2/+128
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
2024-02-19testsuite, python: reformat python files using blackTankut Baris Aktemur2-7/+11
In the recent patch titled "gdb, python: selectively omit enabling stdin in gdb.execute", the black tool found formatting issues. Fix them.
2024-02-19gdb, python: selectively omit enabling stdin in gdb.executeTankut Baris Aktemur6-0/+211
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>
2024-02-19[gdb/exp] Fix printing of out of bounds struct membersTom de Vries2-0/+155
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
2024-02-14[gdb/testsuite] Fix another fail and tcl error in gdb.dap/sources.expTom de Vries1-17/+24
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.
2024-02-13arc: Don't use multiline in arc-disassembler-options.exp testYuriy Kolerov1-4/+5
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>