aboutsummaryrefslogtreecommitdiff
path: root/gdb
AgeCommit message (Collapse)AuthorFilesLines
2023-12-22gdb: fix refactoring hiccup in rs6000_register_to_valueKévin Le Gouguec1-1/+1
In 2023-12-14 "gdb: make get_frame_register_bytes take the next frame" (9fc79b42369), *_register_to_value functions were made to (a) call get_next_frame_sentinel_okay (frame) (b) pass that next frame to get_frame_register_bytes. Step (b) was omitted for rs6000-tdep.c; this manifests as a regression on PPC platforms for e.g. O2_float_param: instead of seeing… Temporary breakpoint 1, callee.increment (val=val@entry=99.0, msg=...) at callee.adb:19 … we get "optimized_out" for val. Passing next_frame to get_frame_register_bytes fixes the issue. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-12-22Add 'program' to DAP 'attach' requestTom Tromey5-9/+42
In many cases, it's not possible for gdb to discover the executable when a DAP 'attach' request is used. This patch lets the IDE supply this information. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-12-22gdb: add git trailer information on gdb/MAINTAINERSGuinevere Larsen1-8/+90
The project has been using Tested-By (tb), Reviewed-By (rb) and Approved-By (ab) for some time, but there has been no information to be found in the actual repository. This commit changes that by adding information about all git trailers to the MAINTAINERS file, so that it can be easily double-checked. Simply put, the trailers in use work as follows: * Tested-by: The person tested the patch and it fixes the problem, or introduces no regressions (or both). * Acked-by: The general outline looks good, but the maintainer hasn't looked at the code * Reviewed-by: The code looks good, but the reviewer has not approved the patch to go upstream * Approved-by: The patch is ready to be pushed to master These last 3 trailers can also be restricted to one or more areas of GDB by adding the areas in a comma separated list in parenthesis after the trailers. Finally, for completeness sake, the trailers Co-Authored-By and Bug were added, even though they have been in use for a long time already Reviewed-By: Kevin Buettner <kevinb@redhat.com> Reviewed-By: Luis Machado <luis.machado@arm.com> Approved-By: John Baldwin <jhb@FreeBSD.org>
2023-12-21Rename TUI locator window -> statusTom Tromey8-30/+30
The TUI status window is called the "locator" in the source, but "status" in the documentation. Whenever I've needed to find the code, I've had to search to "locate" it (ha, ha). This patch renames the window to match the public name of the window.
2023-12-21Rename tui-stack -> tui-statusTom Tromey13-13/+13
The TUI status line is called the "status" window in the documentation, but not in the source. There, the relevant files are named "tui-stack", which to me makes it sound like they have something to do with backtraces. This patch renames them to "tui-status".
2023-12-21Fix Clang build issue with flexible array member and non-trivial dtorPedro Alves1-1/+9
Commit d5cebea18e7a ("Make cached_reg_t own its data") added a destructor to cached_reg_t. That caused a build problem with Clang, which errors out like so: > CXX python/py-unwind.o > gdb/python/py-unwind.c:126:16: error: flexible array member 'reg' of type 'cached_reg_t[]' with non-trivial destruction > 126 | cached_reg_t reg[]; > | ^ This is is not really a problem for our code, which allocates the whole structure with xmalloc, and then initializes the array elements with in-place new, and then takes care to call the destructor manually. Like, commit d5cebea18e7a did: @@ -928,7 +927,7 @@ pyuw_dealloc_cache (frame_info *this_frame, void *cache) cached_frame_info *cached_frame = (cached_frame_info *) cache; for (int i = 0; i < cached_frame->reg_count; i++) - xfree (cached_frame->reg[i].data); + cached_frame->reg[i].~cached_reg_t (); Maybe we should get rid of the flexible array member and use a bog standard std::vector. I doubt this would cause any visible performance issue. Meanwhile, to unbreak the build, this commit switches from C99-style flexible array member to 0-length array. It behaves the same, and Clang doesn't complain. I got the idea from here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70932#c11 GCC 9, our oldest support version, already supported this: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Zero-Length.html but the extension is actually much older than that. Note that C99-style flexible array members are not standard C++ either. Change-Id: I37dda18f367e238a41d610619935b2a0f2acacce
2023-12-20Fix handling of vanishing threads that were stepping/stoppingPedro Alves1-41/+153
Downstream, AMD is carrying a testcase (gdb.rocm/continue-over-kernel-exit.exp) that exposes a couple issues with the amd-dbgapi target's handling of exited threads. The test can't be added upstream yet, unfortunately, due to dependency on DWARF extensions that can't be upstreamed yet. However, it can be found on the mailing list on the same series as this patch. The test spawns a kernel with a number of waves. The waves do nothing but exit. There is a breakpoint on the s_endpgm instruction. Once that breakpoint is hit, the test issues a "continue" command. We should see one breakpoint hit per wave, and then the whole program exiting. We do see that, however we also see this: [New AMDGPU Wave ?:?:?:1 (?,?,?)/?] [AMDGPU Wave ?:?:?:1 (?,?,?)/? exited] *repeat for other waves* ... [Thread 0x7ffff626f640 (LWP 3048491) exited] [Thread 0x7fffeb7ff640 (LWP 3048488) exited] [Inferior 1 (process 3048475) exited normally] That "New AMDGPU Wave" output comes from infrun.c itself adding the thread to the GDB thread list, because it got an event for a thread not on the thread list yet. The output shows "?"s instead of proper coordinates, because the event was a TARGET_WAITKIND_THREAD_EXITED, i.e., the wave was already gone when infrun.c added the thread to the thread list. That shouldn't ever happen for the amd-dbgapi target, threads should only ever be added by the backend. Note "New AMDGPU Wave ?:?:?:1" is for wave 1. What happened was that wave 1 terminated previously, and a previous call to amd_dbgapi_target::update_thread_list() noticed the wave had vanished and removed it from the GDB thread list. However, because the wave was stepping when it terminated (due to the displaced step over the s_endpgm) instruction, it is guaranteed that the amd-dbgapi library queues a WAVE_COMMAND_TERMINATED event for the exit. When we process that WAVE_COMMAND_TERMINATED event, in amd-dbgapi-target.c:process_one_event, we return it to the core as a TARGET_WAITKIND_THREAD_EXITED event: static void process_one_event (amd_dbgapi_event_id_t event_id, amd_dbgapi_event_kind_t event_kind) { ... if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID && event_kind == AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED) ws.set_thread_exited (0); ... } Recall the wave is already gone from the GDB thread list. So when GDB sees that TARGET_WAITKIND_THREAD_EXITED event for a thread it doesn't know about, it adds the thread to the thread list, resulting in that: [New AMDGPU Wave ?:?:?:1 (?,?,?)/?] and then, because it was a TARGET_WAITKIND_THREAD_EXITED event, GDB marks the thread exited right afterwards: [AMDGPU Wave ?:?:?:1 (?,?,?)/? exited] The fix is to make amd_dbgapi_target::update_thread_list() _not_ delete vanishing waves iff they were stepping or in progress of being stopped. These two cases are the ones dbgapi guarantees will result in a WAVE_COMMAND_TERMINATED event if the wave terminates: /** * A command for a wave was not able to complete because the wave has * terminated. * * Commands that can result in this event are ::amd_dbgapi_wave_stop and * ::amd_dbgapi_wave_resume in single step mode. Since the wave terminated * before stopping, this event will be reported instead of * ::AMD_DBGAPI_EVENT_KIND_WAVE_STOP. * * The wave that terminated is available by the ::AMD_DBGAPI_EVENT_INFO_WAVE * query. However, the wave will be invalid since it has already terminated. * It is the client's responsibility to know what command was being performed * and was unable to complete due to the wave terminating. */ AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED = 2, As the comment says, it's GDB's responsability to know whether the wave was stepping or being stopped. Since we now have a wave_info map with one entry for each wave, that seems like the place to store that information. However, I still decided to put all the coordinate information in its own structure. I.e., basically renamed the existing wave_info to wave_coordinates, and then added a new wave_info structure that holds the new state, plus a wave_coordinates object. This seemed cleaner as there are places where we only need to instantiate a wave_coordinates object. There's an extra twist. The testcase also exercises stopping at a new kernel right after the first kernel fully exits. In that scenario, we were hitting this assertion after the first kernel fully exits and the hit of the breakpoint at the second kernel is handled: [amd-dbgapi] process_event_queue: Pulled event from dbgapi: event_id.handle = 26, event_kind = WAVE_STOP [amd-dbgapi-lib] suspending queue_3, queue_2, queue_1 (refresh wave list) ../../src/gdb/amd-dbgapi-target.c:1625: internal-error: amd_dbgapi_thread_deleted: Assertion `it != info->wave_info_map.end ()' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. This is the exact same problem as above, just a different manifestation. In this scenario, we end up in update_thread_list successfully deleting the exited thread (because it was no longer the current thread) that was incorrectly added by infrun.c. Because it was added by infrun.c and not by amd-dbgapi-target.c:add_gpu_thread, it doesn't have an entry in the wave_info map, so amd_dbgapi_thread_deleted trips on this assertion: gdb_assert (it != info->wave_info_map.end ()); here: ... -> stop_all_threads -> update_thread_list -> target_update_thread_list -> amd_dbgapi_target::update_thread_list -> thread_db_target::update_thread_list -> linux_nat_target::update_thread_list -> delete_exited_threads -> delete_thread -> delete_thread_1 -> gdb::observers::observable<thread_info*>::notify -> amd_dbgapi_thread_deleted -> internal_error_loc The testcase thus tries both running to exit after the first kernel exits, and running to a breakpoint in a second kernel after the first kernel exits. Approved-By: Lancelot Six <lancelot.six@amd.com> (amdgpu) Change-Id: I43a66f060c35aad1fe0d9ff022ce2afd0537f028
2023-12-20Fix thread target ID of exited wavesPedro Alves4-38/+135
Currently, if you step over kernel exit, you see: stepi [AMDGPU Wave ?:?:?:1 (?,?,?)/? exited] Command aborted, thread exited. (gdb) Those '?' are because the thread/wave is already gone by the time GDB prints the "exited" notification, we can't ask dbgapi for any info about the wave anymore. This commit fixes it by caching the wave's coordinates as soon as GDB sees the wave for the first time, and making amd_dbgapi_target::pid_to_str use the cached info. At first I thought of clearing the wave_info object from a thread_exited observer. However, that is too soon, resulting in this: (gdb) si [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited] Command aborted, thread exited. (gdb) thread [Current thread is 6 (AMDGPU Wave ?:?:?:0 (?,?,?)/?) (exited)] We need instead to clear the wave info when the thread is ultimately deleted, so we get: (gdb) si [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited] Command aborted, thread exited. (gdb) thread [Current thread is 6 (AMDGPU Wave 1:4:1:1 (0,0,0)/0) (exited)] And for that, we need a new thread_deleted observable. Approved-By: Simon Marchi <simon.marchi@efficios.com> Approved-By: Lancelot Six <lancelot.six@amd.com> (amdgpu) Change-Id: I6c3e22541f051e1205f75eb657b04dc15e547580
2023-12-20Step over thread exit, always delete the thread non-silentlyPedro Alves1-4/+7
With AMD GPU debugging, I noticed that when stepping over a breakpoint placed on top of the s_endpgm instruction inline (displaced=off), GDB would behave differently -- it wouldn't print the wave exit. E.g: With displaced stepping, or no breakpoint at all: stepi [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited] Command aborted, thread exited. (gdb) With inline stepping: stepi Command aborted, thread exited. (gdb) In the cases we see the "exited" notification, handle_thread_exit is what first called delete_thread on the exiting thread, which is non-silent. With inline stepping, however, handle_thread_exit ends up in update_thread_list (via restart_threads) before any delete_thread call. Thus, amd_dbgapi_target::update_thread_list notices that the wave is gone and deletes it with delete_thread_silent. This commit fixes it, by making handle_thread_exited call set_thread_exited (with the default silent=false) early, which emits the user-visible notification. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I22ab3145e18d07c99dace45576307b9f9d5d966f
2023-12-20displaced_step_finish: Don't fetch the regcache of exited threadsPedro Alves2-7/+14
displaced_step_finish can be called with event_status.kind == TARGET_WAITKIND_THREAD_EXITED, and in that case it is not possible to get at the already-exited thread's registers. This patch moves the get_thread_regcache calls to branches that actually need it, where we know the thread is still alive. It also adds an assertion to get_thread_regcache, to help catching these broken cases sooner. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I63b5eacb3e02a538fc5087c270d8025adfda88c3
2023-12-20Ensure selected thread after thread exit stopPedro Alves1-0/+7
While making step over thread exit work properly on AMDGPU, I noticed that if there's a breakpoint on top of the exit syscall, and, displaced stepping is off, then when GDB reports "Command aborted, thread exited.", GDB also switches focus to a random thread, instead of leaving the exited thread as selected: (gdb) thread [Current thread is 6, lane 0 (AMDGPU Lane 1:4:1:1/0 (0,0,0)[0,0,0])] (gdb) si Command aborted, thread exited. (gdb) thread [Current thread is 5 (Thread 0x7ffff626f640 (LWP 3248392))] (gdb) The previous patch extended gdb.threads/step-over-thread-exit.exp to exercise this on GNU/Linux (on the CPU side), and there, after that "si", we always end up with the exiting thread as selected even without this fix, but that's just a concidence, there's a code path that happens to select the exiting thread for an unrelated reason. This commit add the explict switch, fixing the latent problem for GNU/Linux, and the actual problem on AMDGPU. I wrote a gdb.rocm/ testcase for this, but it can't be upstreamed yet, until more pieces of the DWARF machinery are upstream as well. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I6ff57a79514ac0142bba35c749fe83d53d9e4e51
2023-12-20gdb.threads/step-over-thread-exit.exp improvementsPedro Alves2-24/+119
This commit makes the following improvements to gdb.threads/step-over-thread-exit.exp: - Add a third axis to stepping over the breakpoint with displaced vs inline stepping -- also test with no breakpoint at all. - Check that when GDB reports "Command aborted, thread exited.", the selected thread is the thread that exited. This is always true currently on GNU/Linux by coincidence, but a similar testcase on AMD GPU exposed a problem here. Better make the testcase catch any potential regression. - Fixes a race that Simon ran into with GDBserver testing. (gdb) next [New Thread 2143071.2143438] Thread 3 "step-over-threa" hit Breakpoint 2, 0x000055555555524e in my_exit_syscall () at .../testsuite/lib/my-syscalls.S:74 74 SYSCALL (my_exit, __NR_exit) (gdb) FAIL: gdb.threads/step-over-thread-exit.exp: displaced-stepping=auto: non-stop=on: target-non-stop=on: schedlock=off: cmd=next: ns_stop_all=0: command aborts when thread exits I was not able to reproduce it, but I believe that what happens is the following: Once we continue, the thread 2 exits, and the main thread thus unblocks from its pthread_join, and spawns a new thread. That new thread may hit the breakpoint at my_exit_syscall very quickly. GDB could then see/process that breakpoint event before the thread exit event for the thread we care about, which would result in the failure seen above. The fix here is to not loop and start a new thread at all in the scenario where the race can happen. We only need to loop and spawn new threads when testing with "cmd=continue" and schedlock off, in which case GDB doesn't abort the command when the thread exits. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I90c95c32f00630a3f682b1541c23aff52451f9b6
2023-12-20Fix bug in previous remote unique_ptr changePedro Alves1-2/+3
By inspection, I noticed that the previous patch went too far, here: @@ -7705,7 +7713,8 @@ remote_target::discard_pending_stop_replies (struct inferior *inf) if (rs->remote_desc == NULL) return; - reply = (struct stop_reply *) rns->pending_event[notif_client_stop.id]; + stop_reply_up reply + = as_stop_reply_up (std::move (rns->pending_event[notif_client_stop.id])); /* Discard the in-flight notification. */ if (reply != NULL && reply->ptid.pid () == inf->pid) That is always moving the stop reply from pending_event, when we only really want to peek into it. The code further below that even says: /* Discard the in-flight notification. */ if (reply != NULL && reply->ptid.pid () == inf->pid) { /* Leave the notification pending, since the server expects that we acknowledge it with vStopped. But clear its contents, so that later on when we acknowledge it, we also discard it. */ This commit reverts that hunk back, adjusted to use unique_ptr::get(). Change-Id: Ifc809d1a8225150a4656889f056d51267100ee24
2023-12-20Complete use of unique_ptr with notif_event and stop_replyPedro Alves3-55/+54
We already use unique_ptr with notif_event and stop_reply in some places around the remote target, but not fully. There are several code paths that still use raw pointers. This commit makes all of the ownership of these objects tracked by unique pointers, making the lifetime flow much more obvious, IMHO. I notice that it fixes a leak -- in remote_notif_stop_ack, We weren't destroying the stop_reply object if it was of TARGET_WAITKIND_IGNORE kind. Approved-By: Tom Tromey <tom@tromey.com> Change-Id: Id81daf39653d8792c8795b2a145772176bfae77c
2023-12-20Make cached_reg_t own its dataPedro Alves3-26/+16
struct cached_reg_t owns its data buffer, but currently that is managed manually. Convert it to use a unique_xmalloc_ptr. Approved-By: Tom Tromey <tom@tromey.com> Change-Id: I05a107098b717299e76de76aaba00d7fbaeac77b
2023-12-20gdb: remove stale comment and ctor in gdbarch_infoSimon Marchi1-7/+1
tdesc_data is not part of a union, since commit 4f3681cc3361 ("Fix thread's gdbarch when SVE vector length changes"). Remove the stale comment and constructor. Change-Id: Ie895ce36614930e8bd9c4967174c8bf1b321c503
2023-12-19gdb: use put_frame_register instead of put_frame_register_bytes in ↵Simon Marchi1-10/+10
pseudo_to_concat_raw Here, we write single complete registers, we don't need the functionality of put_frame_register_bytes, use put_frame_register instead. Change-Id: I987867a27249db4f792a694b47ecb21c44f64d08 Approved-By: Tom Tromey <tom@tromey.com>
2023-12-19gdb: remove stale comment in value_assignSimon Marchi1-7/+0
This comment is no longer relevant, put_frame_register_bytes now accepts the "next frame". Change-Id: I077933a03f8bdb886f8ba10a98d1202a38bce0a9 Approved-By: Tom Tromey <tom@tromey.com>
2023-12-19gdb: register frame_destroyed function for amd64 gdbarchGuinevere Larsen2-24/+25
gdbarches usually register functions to check when a frame is destroyed which is used with software watchpoints, since the expression of the watchpoint is no longer vlaid at this point. On amd64, this wasn't done anymore because GCC started using CFA for variable locations instead. However, clang doesn't use the CFA and instead relies on specifying when an epilogue has started, meaning software watchpoints get a spurious hit when a frame is destroyed. This patch re-adds the code to register the function that detects when a frame is destroyed, but only uses this when the producer is LLVM, so gcc code isn't affected. The logic that identifies the epilogue has been factored out into the new function amd64_stack_frame_destroyed_p_1, so the frame sniffer can call it directly, and its behavior isn't changed. This can also remove the XFAIL added to gdb.python/pq-watchpoint tests that handled this exact flaw in clang. Co-Authored-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-12-18gdb/testsuite: another attempt to fix gdb.threads/thread-specific-bp.expAndrew Burgess1-18/+6
The gdb.threads/thread-specific-bp.exp test has been a little problematic, see commits: commit 89702edd933a5595557bcd9cc4a0dcc3262226d4 Date: Thu Mar 9 12:31:26 2023 +0100 [gdb/testsuite] Fix gdb.threads/thread-specific-bp.exp on native-gdbserver and commit 2e5843d87c4050bf1109921481fb29e1c470827f Date: Fri Nov 19 14:33:39 2021 +0100 [gdb/testsuite] Fix gdb.threads/thread-specific-bp.exp But I recently saw a test failure for that test, which looked like this: ... (gdb) PASS: gdb.threads/thread-specific-bp.exp: non_stop=on: thread 1 selected continue -a Continuing. Thread 1 "thread-specific" hit Breakpoint 4, end () at /tmp/binutils-gdb/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.threads/thread-specific-bp.c:29 29 } (gdb) [Thread 0x7ffff7c5c700 (LWP 1552086) exited] Thread-specific breakpoint 3 deleted - thread 2 no longer in the thread list. FAIL: gdb.threads/thread-specific-bp.exp: non_stop=on: continue to end (timeout) ... This only crops up (for me) when running on a loaded machine, and still only occurs sometimes. I've had to leave the test running in a loop for 10+ minutes sometimes in order to see the failure. The problem is that we use gdb_test_multiple to try and match two patterns: (1) The 'Thread-specific breakpoint 3 deleted ....' message, and (2) The GDB prompt. As written in the test, we understand that these patterns can occur in any order, and we have a flag for each pattern. Once both patterns have been seen then we PASS the test. The problem is that once expect has matched a pattern, everything up to, and including the matched text is discarded from the input buffer. Thus, if the input buffer contains: <PATTERN 2><PATTERN 1> Then expect will first try to match <PATTERN 1>, which succeeds, and then expect discards the entire input buffer up to the end of the <PATTERN 1>. As a result, we will never spot <PATTERN 2>. Obviously we can't just reorder the patterns within the gdb_test_multiple, as the output can legitimately (and most often does) occur in the other order, in which case the test would mostly fail, and only occasionally pass! I think the easiest solution here is just to have the gdb_test_multiple contain two patterns, each pattern consists of the two parts, but in the alternative orders, thus, for a particular output configuration, only one regexp will match. With this change in place, I no longer see the intermittent failure. Approved-By: Tom Tromey <tom@tromey.com>
2023-12-16Use function entry point record only for entry valuesHannes Domani3-5/+7
PR28987 notes that optimized code sometimes shows the wrong value of variables at the entry point of a function, if some code was optimized away and the variable has multiple values stored in the debug info for this location. In this example: ``` void foo() { int l_3 = 5, i = 0; for (; i < 8; i++) ; test(l_3, i); } ``` When compiled with optimization, the entry point of foo is at the test() function call, since everything else is optimized away. The debug info of i looks like this: ``` (gdb) info address i Symbol "i" is multi-location: Base address 0x140001600 Range 0x13fd41600-0x13fd41600: the constant 0 Range 0x13fd41600-0x13fd41600: the constant 1 Range 0x13fd41600-0x13fd41600: the constant 2 Range 0x13fd41600-0x13fd41600: the constant 3 Range 0x13fd41600-0x13fd41600: the constant 4 Range 0x13fd41600-0x13fd41600: the constant 5 Range 0x13fd41600-0x13fd41600: the constant 6 Range 0x13fd41600-0x13fd41600: the constant 7 Range 0x13fd41600-0x13fd4160f: the constant 8 (gdb) p i $1 = 0 ``` Currently, when at the entry point of a function, it will always show the initial value (here 0), while the user would expect the last value (here 8). This logic was introduced for showing the entry-values of function arguments if they are available, but for some reason this was added for non-entry-values as well. One of the tests of amd64-entry-value.exp shows the same problem for function arguments, if you "break stacktest" in the following example, you stop at this line: ``` 124 static void __attribute__((noinline, noclone)) 125 stacktest (int r1, int r2, int r3, int r4, int r5, int r6, int s1, int s2, 126 double d1, double d2, double d3, double d4, double d5, double d6, 127 double d7, double d8, double d9, double da) 128 { 129 s1 = 3; 130 s2 = 4; 131 d9 = 3.5; 132 da = 4.5; 133 -> e (v, v); 134 asm ("breakhere_stacktest:"); 135 e (v, v); 136 } ``` But `bt` still shows the entry values: ``` s1=s1@entry=11, s2=s2@entry=12, ..., d9=d9@entry=11.5, da=da@entry=12.5 ``` I've fixed this by only using the initial values when explicitely looking for entry values. Now the local variable of the first example is as expected: ``` (gdb) p i $1 = 8 ``` And the test of amd64-entry-value.exp shows the expected current and entry values of the function arguments: ``` s1=3, s1@entry=11, s2=4, s2@entry=12, ..., d9=3.5, d9@entry=11.5, da=4.5, da@entry=12.5 ``` Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28987 Tested-By: Guinevere Larsen <blarsen@redhat.com> Approved-By: Tom Tromey <tom@tromey.com>
2023-12-16[gdb/build] Remove dependency on _rl_term_autowrapTom de Vries1-8/+11
Commit deb1ba4e38b ("[gdb/tui] Fix TUI resizing for TERM=ansi") introduced a dependency on readline private variable _rl_term_autowrap. There is precedent for this, but it's something we want to get rid of (PR build/10723). Remove the dependency on _rl_term_autowrap, and instead calculate readline_hidden_cols by comparing the environment variable COLS with cols as returned by rl_get_screen_size. Tested on x86_64-linux. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=10723
2023-12-16[gdb/tui] Show regs when switching to regs layoutTom de Vries3-8/+22
When starting gdb in CLI mode, running to main and switching into the TUI regs layout: ... $ gdb -q a.out -ex start -ex "layout regs" ... we get: ... +---------------------------------+ | | | [ Register Values Unavailable ] | | | +---------------------------------+ ... Fix this by handling this case in tui_data_window::rerender. Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com> PR tui/28600 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28600
2023-12-16[gdb/tui] Use more box_width in tui-regs.cTom de Vries1-2/+6
While experimenting with can_box () == false by default, I noticed two places in tui-regs.c where we can replace a hardcoded 1 with box_width (). It also turned out to be necessary to set scrollok to false, otherwise writing the last char of the last line with register info will cause a scroll. Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com>
2023-12-15Refine Ada overload matchingTom Tromey3-11/+108
Currently, the overload handling in Ada assumes that any two array types are compatible. However, this is obviously untrue, and a user reported an oddity where comparing two Ada strings resulted in a call to the "=" function for packed boolean arrays. This patch improves the situation somewhat, by requiring that the two arrays have the same arity and compatible base element types. This is still over-broad, but it seems safe and is better than the status quo.
2023-12-15Boolify ada_type_matchTom Tromey1-5/+5
This changes ada_type_match to return bool.
2023-12-14gdb/options: fix copy&paste error in string_option_defAndrew Burgess1-1/+1
Spotted what appears to be a copy&paste error in string_option_def, the code for string handling writes the address fetching callback function into the option_def::var_address::enumeration location, rather than option_def::var_address::string. Of course, this works just fine as option_def::var_address is a union, and all of its members are function pointers, so they're going to be the same size on every target GDB cares about. But it doesn't hurt to be correct, so fixed in this commit. There should be no user visible changes after this commit.
2023-12-14gdb/testsuite: add tests for unwinding of pseudo registersSimon Marchi12-0/+796
This patch adds tests to exercise the previous patches' changes. All three tests: - aarch64-pseudo-unwind - amd64-pseudo-unwind - arm-pseudo-unwind follow the same pattern, just with different registers. The other test, arm-pseudo-unwind-legacy, tests the special case where the unwind information contains an entry for a register considered a pseudo-register by GDB. Change-Id: Ic29ac040c5eb087b4a0d79f9d02f65b7979df30f Reviewed-By: John Baldwin <jhb@FreeBSD.org> Reviewed-by: Luis Machado <luis.machado@arm.com> Approved-By: Luis Machado <luis.machado@arm.com> (aarch64/arm) Tested-By: Luis Machado <luis.machado@arm.com> (aarch64/arm)
2023-12-14gdb: migrate arm to new gdbarch_pseudo_register_writeSimon Marchi1-26/+36
Make arm use the new gdbarch_pseudo_register_write. This fixes writing pseudo registers to non-current frames for that architecture. Change-Id: Icb2a649ab6394817844230e9e94c3d0564d2f765 Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-by: Luis Machado <luis.machado@arm.com>
2023-12-14gdb: migrate arm to gdbarch_pseudo_register_read_valueSimon Marchi1-32/+44
Make arm use the "newer" gdbarch_pseudo_register_read_value. This fixes reading pseudo registers in non-current frames on that architecture. Change-Id: Ic4d3d5d96957a4addfa3443c7b567dc4a31794a9 Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-by: Luis Machado <luis.machado@arm.com>
2023-12-14gdb: migrate aarch64 to new gdbarch_pseudo_register_writeSimon Marchi1-58/+70
Make aarch64 use the new gdbarch_pseudo_register_write. This fixes writing pseudo registers to non-current frames on this architecture. Change-Id: Ic012a0b95ae728d45a7121f77a79d604c23a849e Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-By: Luis Machado <luis.machado@arm.com> Tested-By: Luis Machado <luis.machado@arm.com>
2023-12-14gdb: add missing raw register read in aarch64_sme_pseudo_register_writeSimon Marchi1-0/+1
It seems like the intention here is to read the contents of the ZA register and only write part of it. However, there's no actual read of the ZA register, so it looks like we'll write uninitialized bytes to the target, for the portion of the raw register where we don't write the pseudo register. Add a call to raw_read to fix this. I don't know how to test this though. Change-Id: I7548240bd4324f6a3b729a1ebf7502fae5a46e9e Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-by: Luis Machado <luis.machado@arm.com>
2023-12-14gdb: make aarch64_za_offsets_from_regnum return za_offsetsSimon Marchi1-9/+10
This is not necessary, but it seems more natural to me to make aarch64_za_offsets_from_regnum return a za_offsets object, rather than fill an instance passed by parameter. Change-Id: I40a185f055727da887ce7774be193eef1f4b9147 Approved-by: Luis Machado <luis.machado@arm.com> Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: migrate i386 and amd64 to the new gdbarch_pseudo_register_writeSimon Marchi3-130/+61
Make i386 and amd64 use the new gdbarch_pseudo_register_write. This fixes writing to pseudo registers in non-current frames for those architectures. Change-Id: I4977e8fe12d2cef116f8834c34cdf6fec618554f Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: add gdbarch_pseudo_register_write that takes a frameSimon Marchi7-2/+167
Add a new variant of gdbarch_pseudo_register_write that takes a frame_info in order to write raw registers. Use this new method when available: - in put_frame_register, when trying to write a pseudo register to a given frame - in regcache::cooked_write No implementation is migrated to use this new method (that will come in subsequent patches), so no behavior change is expected here. The objective is to fix writing pseudo registers to non-current frames. See previous commit "gdb: read pseudo register through frame" for a more detailed explanation. Change-Id: Ie7fe364a15a4d86c2ecb09de2b4baa08c45555ac Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: rename gdbarch_pseudo_register_write to ↵Simon Marchi28-54/+90
gdbarch_deprecated_pseudo_register_write The next patch introduces a new variant of gdbarch_pseudo_register_write that takes a frame instead of a regcache for implementations to write raw registers. Rename to old one to make it clear it's deprecated. Change-Id: If8872c89c6f8a1edfcab983eb064248fd5ff3115 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: change parameter name in frame_unwind_register_unsigned declarationSimon Marchi1-1/+1
For consistency with the declarations around. Change-Id: I398266a61eae6e93fb7e306923009da9dd7f8fc4 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: read pseudo register through frameSimon Marchi12-285/+322
Change gdbarch_pseudo_register_read_value to take a frame instead of a regcache. The frame (and formerly the regcache) is used to read raw registers needed to make up the pseudo register value. The problem with using the regcache is that it always provides raw register values for the current frame (frame 0). Let's say the user wants to read the ebx register on amd64. ebx is a pseudo register, obtained by reading the bottom half (bottom 4 bytes) of the rbx register, which is a raw register. If the currently selected frame is frame 0, it works fine: (gdb) frame 0 #0 break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:36 36 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $1 = 0x24252627 (gdb) p/x $rbx $2 = 0x2021222324252627 But if the user is looking at another frame, and the raw register behind the pseudo register has been saved at some point in the call stack, then we get a wrong answer: (gdb) frame 1 #1 0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:56 56 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $3 = 0x24252627 (gdb) p/x $rbx $4 = 0x1011121314151617 Here, the value of ebx was computed using the value of rbx in frame 0 (through the regcache), it should have been computed using the value of rbx in frame 1. In other to make this work properly, make the following changes: - Make dwarf2_frame_prev_register return nullptr if it doesn't know how to unwind a register and that register is a pseudo register. Previously, it returned `frame_unwind_got_register`, meaning, in our example, "the value of ebx in frame 1 is the same as the value of ebx in frame 0", which is obviously false. Return nullptr as a way to say "I don't know". - In frame_unwind_register_value, when prev_register (for instance dwarf2_frame_prev_register) returns nullptr, and we are trying to read a pseudo register, try to get the register value through gdbarch_pseudo_register_read_value or gdbarch_pseudo_register_read. If using gdbarch_pseudo_register_read, the behavior is known to be broken. Implementations should be migrated to use gdbarch_pseudo_register_read_value to fix that. - Change gdbarch_pseudo_register_read_value to take a frame_info instead of a regcache, update implementations (aarch64, amd64, i386). In i386-tdep.c, I made a copy of i386_mmx_regnum_to_fp_regnum that uses a frame instead of a regcache. The version using the regcache is still used by i386_pseudo_register_write. It will get removed in a subsequent patch. - Add some helpers in value.{c,h} to implement the common cases of pseudo registers: taking part of a raw register and concatenating multiple raw registers. - Update readable_regcache::{cooked_read,cooked_read_value} to pass the current frame to gdbarch_pseudo_register_read_value. Passing the current frame will give the same behavior as before: for frame 0, raw registers will be read from the current thread's regcache. Notes: - I do not plan on changing gdbarch_pseudo_register_read to receive a frame instead of a regcache. That method is considered deprecated. Instead, we should be working on migrating implementations to use gdbarch_pseudo_register_read_value instead. - In frame_unwind_register_value, we still ask the unwinder to try to unwind pseudo register values. It's apparently possible for the debug info to provide information about [1] pseudo registers, so we want to try that first, before falling back to computing them ourselves. [1] https://inbox.sourceware.org/gdb-patches/20180528174715.A954AD804AD@oc3748833570.ibm.com/ Change-Id: Id6ef1c64e19090a183dec050e4034d8c2394e7ca Reviewed-by: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: add value::allocate_registerSimon Marchi3-5/+24
Add value::allocate_register, to facilitate allocating a value representing a register in a given frame (or rather, in the given frame's previous frame). It will be used in a subsequent patch. I changed one relatively obvious spot that could use it, to at least exercise the code path. Change-Id: Icd4960f5e471a74b657bb3596c88d89679ef3772 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: make get_frame_register_bytes take the next frameSimon Marchi10-55/+50
Similar to the previous patches, change get_frame_register_bytes to take the "next frame" instead of "this frame". Change-Id: Ie8f35042bfa6e93565fcefaee71b6b3903f0fe9f Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: make put_frame_register_bytes take the next frameSimon Marchi5-36/+31
Similar to the previous patches, change put_frame_register_bytes to take the "next frame" instead of "this frame". Change-Id: I27bcb26573686d99b231230823cff8db6405a788 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: make put_frame_register take the next frameSimon Marchi9-19/+24
Similar to the previous patches, change put_frame_register to take the "next frame" instead of "this frame". Change-Id: I062fd4663b8f54f0fc7bbf39c860b7341363821b Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: remove frame_registerSimon Marchi1-31/+8
I was going to change frame_register to take the "next frame", but I realized that doing so would make it a useless wrapper around frame_register_unwind. So, just remove frame_register and replace uses with frame_register_unwind. Change-Id: I185868bc69f8e098124775d0550d069220a4678a Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: change value_of_register and value_of_register_lazy to take the next frameSimon Marchi17-49/+53
Some functions related to the handling of registers in frames accept "this frame", for which we want to read or write the register values, while other functions accept "the next frame", which is the frame next to that. The later is needed because we sometimes need to read register values for a frame that does not exist yet (usually when trying to unwind that frame-to-be). value_of_register and value_of_register_lazy both take "this frame", even if what they ultimately want internally is "the next frame". This is annoying if you are in a spot that currently has "the next frame" and need to call one of these functions (which happens later in this series). You need to get the previous frame only for those functions to get the next frame again. This is more manipulations, more chances of mistake. I propose to change these functions (and a few more functions in the subsequent patches) to operate on "the next frame". Things become a bit less awkward when all these functions agree on which frame they take. So, in this patch, change value_of_register_lazy and value_of_register to take "the next frame" instead of "this frame". This adds a lot of get_next_frame_sentinel_okay, but if we convert the user registers API to also use "the next frame" instead of "this frame", it will get simple again. Change-Id: Iaa24815e648fbe5ae3c214c738758890a91819cd Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: make put_frame_register take an array_viewSimon Marchi9-24/+35
Change put_frame_register to take an array_view instead of a raw pointer. Add an assertion to verify that the number of bytes we try to write matches the length of the register. Change-Id: Ib75a9c8a12b47e203097621643eaa2c1830591ae Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: fix bugs in {get,put}_frame_register_bytesSimon Marchi1-40/+23
I found this only by inspection: the myaddr pointer in {get,put}_frame_register_bytes is reset to `buffer.data ()` at each iteration. This means that we will always use the bytes at the beginning of `buffer` to read or write to the registers, instead of progressing in `buffer`. Fix this by re-writing the functions to chip away the beginning of the buffer array_view as we progress in reading or writing the data. These bugs was introduced almost 3 years ago [1], and yet nobody complained. I'm wondering which architecture relies on that register "overflow" behavior (reading or writing multiple consecutive registers with one {get,put}_frame_register_bytes calls), and in which situation. I find these functions a bit dangerous, if a caller mis-calculates things, it could end up silently reading or writing to the next register, even if it's not the intent. If I could change it, I would prefer to have functions specifically made for that ({get,put}_frame_register_bytes_consecutive or something like that) and make {get,put}_frame_register_bytes only able to write within a single register (which I presume represents most of the use cases of the current {get,put}_frame_register_bytes). If a caller mis-calculates things and an overflow occurs while calling {get,put}_frame_register_bytes, it would hit an assert. The problem is knowing which callers rely on the overflow behavior and which don't. [1] https://gitlab.com/gnutools/binutils-gdb/-/commit/bdec2917b1e94c7198ba39919f45060067952f43 Change-Id: I43bd4a9f7fa8419d388a2b20bdc57d652688ddf8 Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-12-14gdb: change regcache interface to use array_viewSimon Marchi4-244/+383
Change most of regcache (and base classes) to use array_view when possible, instead of raw pointers. By propagating the use of array_view further, it enables having some runtime checks to make sure the what we read from or write to regcaches has the expected length (such as the one in the `copy(array_view, array_view)` function. It also integrates well when connecting with other APIs already using gdb::array_view. Add some overloads of the methods using raw pointers to avoid having to change all call sites at once (which is both a lot of work and risky). I tried to do this change in small increments, but since many of these functions use each other, it ended up simpler to do it in one shot than having a lot of intermediary / transient changes. This change extends into gdbserver as well, because there is some part of the regcache interface that is shared. Changing the reg_buffer_common interface to use array_view caused some build failures in nat/aarch64-scalable-linux-ptrace.c. That file currently "takes advantage" of the fact that reg_buffer_common::{raw_supply,raw_collect} operates on `void *`, which IMO is dangerous. It uses raw_supply/raw_collect directly on uint64_t's, which I guess is fine because it is expected that native code will have the same endianness as the debugged process. To accomodate that, add some overloads of raw_collect and raw_supply that work on uint64_t. This file also uses raw_collect and raw_supply on `char` pointers. Change it to use `gdb_byte` pointers instead. Add overloads of raw_collect and raw_supply that work on `gdb_byte *` and make an array_view on the fly using the register's size. Those call sites could be converted to use array_view with not much work, in which case these overloads could be removed, but I didn't want to do it in this patch, to avoid starting to dig in arch-specific code. During development, I inadvertently changed reg_buffer::raw_compare's behavior to not accept an offset equal to the register size. This behavior (effectively comparing 0 bytes, returning true) change was caught by the AArch64 SME core tests. Add a selftest to make sure that this raw_compare behavior is preserved in the future. Change-Id: I9005f04114543ddff738949e12d85a31855304c2 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: simplify conditions in regcache::{read,write,raw_collect,raw_supply}_partSimon Marchi1-12/+12
Make a few simplifications in these functions. 1. When checking if we need to do nothing, if the length is 0, we don't need to do anything, regardless of the value of offset. Remove the offset check. 2. When check if transferring the whole register, if the length is equal to the register size, then we transfer the whole register, no need to check the offset. Remove the offset check. 3. In the gdb_asserts, it is unnecessary to check for: offset <= reg_size given that right after we check for: len >= 0 && offset + len <= reg_size If `offset + len` is <= reg_size and len is >= 0, then necessarily offset is <= reg_size. Remove the `offset <= reg_size` check. Change-Id: I30a73acdc7bf432c45a07f5f177224d1cdc298e8 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: make store_integer take an array_viewSimon Marchi2-17/+38
Change store_integer, store_signed_integer and store_unsigned_integer to accept an array_view. Add some backwards compatibility overloads to avoid changing all callers at once. Change-Id: Ibb1381228ab1cb65fc7e2e4b92cf9ab1047cdc03 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: use reg_buffer_common throughout gdbsupport/common-regcache.hSimon Marchi9-27/+31
Right now, gdbsupport/common-regcache.h contains two abstractons for a regcache. An opaque type `regcache` (gdb and gdbserver both have their own regcache that is the concrete version of this) and an abstract base class `reg_buffer_common`, that is the base of regcaches on both sides. These abstractions allow code to be written for both gdb and gdbserver, for instance in the gdb/arch sub-directory. However, having two different abstractions is impractical. If some common code has a regcache, and wants to use an operation defined on reg_buffer_common, it can't. It would be better to have just one. Change all instances of `regcache *` in gdbsupport/common-regcache.h to be `reg_buffer_common *`, then fix fallouts. Implementations in gdb and gdbserver now need to down-cast (using gdb::checked_static_cast) from reg_buffer_common to their concrete regcache type. Some of them could be avoided by changing free functions (like regcache_register_size) to be virtual methods on reg_buffer_common. I tried it, it seems to work, but I did not include it in this series to avoid adding unnecessary changes. Change-Id: Ia5503adb6b5509a0f4604bd2a68b4642cc5283fd Reviewed-by: John Baldwin <jhb@FreeBSD.org>