[binutils-gdb] Improve attach on Windows
Pedro Alves via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3e17d19c890b262ebb62bcc0d40e38456dc408d1 commit 3e17d19c890b262ebb62bcc0d40e38456dc408d1 Author: Pedro Alves <[email protected]> Date: Wed Jun 11 22:05:23 2025 +0100 Improve attach on Windows Unlike most targets, on Windows, when you attach, GDB doesn't print the current stack frame. Vis: On GNU/Linux: attach 3340347 Attaching to program: /home/pedro/gdb/build/gdb/testsuite/outputs/gdb.base/attach/attach, process 3340347 Reading symbols from /lib/x86_64-linux-gnu/libc.so.6... Reading symbols from /usr/lib/debug/.build-id/d5/197096f709801829b118af1b7cf6631efa2dcd.debug... Reading symbols from /lib64/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/9c/b53985768bb99f138f48655f7b8bf7e420d13d.debug... [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 0x00005b3bf29be174 in main () at /home/pedro/gdb/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/attach.c:19 19 while (! should_exit) (gdb) PASS: gdb.base/attach.exp: do_attach_tests: attach1, after setting file On Cygwin: (gdb) attach 6692 Attaching to program: /home/alves/gdb/build-cygwin-testsuite/outputs/gdb.base/attach/attach, process 6692 [New Thread 6692.0x2e60] [New Thread 6692.0x2e9c] [New Thread 6692.0xd6c] [New Thread 6692.0x137c] [New Thread 6692.0x1270] (gdb) FAIL: gdb.base/attach.exp: do_attach_tests: attach1, after setting file On Linux, GDB prints the frame because after the target_attach, GDB goes back to the event loop, to wait for an initial stop event. The stop event arrives, and we process it, which sets the stop_print_frame global, and then we get to normal_stop, which prints the frame iff stop_print_frame is set, which it is. Windows OTOH, is a target_attach_no_wait target, so after target_attach, there is no going back to event loop. In infcmd.c:attach_command, we go straight to attach_post_wait which takes us to normal_stop. But this time, nothing set stop_print_frame to true, so no frame is printed. Actually, if the global happened to be true due to an earlier event from debugging a previous inferior, then we will print the frame. This patch makes GDB's behavior consistent, by making sure the globals normal_stop looks at are in a good state in the target_attach_no_wait path. With that alone, GDB now prints the frame: (gdb) attach 2915 Attaching to program: /usr/bin/sleep.exe, process 2832 [New Thread 2832.0x2a68] [New Thread 2832.0xb1c] [New Thread 2832.0x8ac] [Switching to Thread 2832.0x8ac] 0x00007ffec51d4a71 in ntdll!DbgBreakPoint () from C:/Windows/SYSTEM32/ntdll.dll This is still not ideal, IMHO, as the current thread is the thread that Windows injects to attach: (gdb) info threads Id Target Id Frame 1 Thread 2832.0x2100 "sleep" 0x00007ffec51d18d7 in ntdll!ZwWaitForMultipleObjects () from C:/Windows/SYSTEM32/ntdll.dll 2 Thread 2832.0x2a68 "sig" 0x00007ffec51d0e47 in ntdll!ZwReadFile () from C:/Windows/SYSTEM32/ntdll.dll 3 Thread 2832.0xb1c 0x00007ffec51d49d7 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:/Windows/SYSTEM32/ntdll.dll * 4 Thread 2832.0x8ac 0x00007ffec51d4a71 in ntdll!DbgBreakPoint () from C:/Windows/SYSTEM32/ntdll.dll Automatically switching to the main thread is IMHO more useful. That results in very similar output than what we see on Linux: attach 5164 Attaching to program: /home/alves/gdb/build-cygwin-testsuite/outputs/gdb.base/attach/attach, process 5164 [New Thread 5164.0x87c] [New Thread 5164.0x28f0] [New Thread 5164.0x376c] [New Thread 5164.0x2db4] [New Thread 5164.0xce4] main () at /home/alves/gdb/src/gdb/testsuite/gdb.base/attach.c:19 19 while (! should_exit) (gdb) If we do this, then we can simplify gdb.base/attach.exp a bit by removing a couple Cygwin special cases. The patch does all that, which results in the following gdb.base/attach.exp progressions: -FAIL: gdb.base/attach.exp: do_attach_tests: attach1, after setting file -FAIL: gdb.base/attach.exp: do_attach_tests: attach2, with no file -FAIL: gdb.base/attach.exp: do_attach_tests: load file manually, after attach2 (re-read) (got interactive prompt) -FAIL: gdb.base/attach.exp: do_attach_tests: attach when process' a.out not in cwd -FAIL: gdb.base/attach.exp: do_attach_failure_tests: first attach +PASS: gdb.base/attach.exp: do_attach_tests: attach1, after setting file +PASS: gdb.base/attach.exp: do_attach_tests: attach2, with no file +PASS: gdb.base/attach.exp: do_attach_tests: attach when process' a.out not in cwd +PASS: gdb.base/attach.exp: do_attach_failure_tests: first attach Change-Id: I359bdb25660c9a4d5d873e8771cfd1cd2a54c97b Diff: --- gdb/infcmd.c | 5 ++++- gdb/infrun.c | 13 +++++++++++++ gdb/infrun.h | 4 ++++ gdb/testsuite/gdb.base/attach.exp | 26 ++++++-------------------- gdb/windows-nat.c | 7 +++++++ 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 9fbee5aaba7..98b45f884b1 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2956,7 +2956,10 @@ attach_command (const char *args, int from_tty) return; } else - attach_post_wait (from_tty, mode); + { + set_normal_stop_state_just_attached (); + attach_post_wait (from_tty, mode); + } disable_commit_resumed.reset_and_commit (); } diff --git a/gdb/infrun.c b/gdb/infrun.c index 9864b5bbdec..6ca2a505299 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -407,6 +407,19 @@ static process_stratum_target *target_last_proc_target; static ptid_t target_last_wait_ptid; static struct target_waitstatus target_last_waitstatus; +/* See infrun.h. */ + +void +set_normal_stop_state_just_attached () +{ + stop_print_frame = true; + stopped_by_random_signal = 0; + + target_waitstatus status; + status.set_ignore (); + set_last_target_status (nullptr, minus_one_ptid, status); +} + void init_thread_stepping_state (struct thread_info *tss); static const char follow_fork_mode_child[] = "child"; diff --git a/gdb/infrun.h b/gdb/infrun.h index 0a7cdadf1fa..7e2b652e4f1 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -428,4 +428,8 @@ private: input. */ extern void reinstall_readline_callback_handler_cleanup (); +/* Set up state for normal_stop after we just attached, on + target_attach_no_wait targets. */ +extern void set_normal_stop_state_just_attached (); + #endif /* GDB_INFRUN_H */ diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp index c4274994b09..bffdfd9b1aa 100644 --- a/gdb/testsuite/gdb.base/attach.exp +++ b/gdb/testsuite/gdb.base/attach.exp @@ -159,16 +159,9 @@ proc_with_prefix do_attach_failure_tests {} { # Verify that we can't double attach to the process. - set test "first attach" - gdb_test_multiple "attach $testpid" "$test" { - -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*main.*at .*$srcfile:.*$gdb_prompt $" { - pass "$test" - } - -re "Attaching to program.*`?$escapedbinfile\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" { - # Response expected on Cygwin. - pass "$test" - } - } + gdb_test "attach $testpid" \ + "Attaching to program.*`?${escapedbinfile}(\.exe)?'?, process $testpid.*main.*at .*$srcfile:.*" \ + "first attach" gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2" gdb_test "inferior 2" "Switching to inferior 2.*" "switch to inferior 2" @@ -252,16 +245,9 @@ proc_with_prefix do_attach_tests {} { } } - set test "attach1, after setting file" - gdb_test_multiple "attach $testpid" "$test" { - -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*main.*at .*$srcfile:.*$gdb_prompt $" { - pass "$test" - } - -re "Attaching to program.*`?$escapedbinfile\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" { - # Response expected on Cygwin - pass "$test" - } - } + gdb_test "attach $testpid" \ + "Attaching to program.*`?${escapedbinfile}(\.exe)?'?, process $testpid.*main.*at .*$srcfile:.*" \ + "attach1, after setting file" # Verify that we can "see" the variable "should_exit" in the # program, and that it is zero. diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 3d1a75d1cc8..d1328375e55 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1412,6 +1412,13 @@ windows_nat_target::attach (const char *args, int from_tty) #endif do_initial_windows_stuff (pid, 1); + + /* The thread that reports the initial breakpoint, and thus ends up + as the selected thread when we get here, was injected into the + inferior by DebugActiveProcess. Switch to the main thread, which + is normally more useful to the user than the injected thread. */ + switch_to_thread (first_thread_of_inferior (current_inferior ())); + target_terminal::ours (); }