From 7be2bb4f47b7b25d4f60b52f6ebaade0644827f2 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 24 Apr 2020 06:48:01 -0600 Subject: [PATCH] Fix Windows debugging regression The updated pending stop series introduced a regression in Windows debugging. When stopped at a software breakpoint, we would adjust the PC each time it was requested -- however, more than a single adjustment is incorrect. This patch introduces a new flag that is used to ensure the adjustment only happens a single time. No similar change is needed in gdbserver, because it adjusts the PC in a different way. I still can't run the gdb test suite on Windows, but I can run the internal AdaCore test suite there; and this fixes the regressions there. gdb/ChangeLog 2020-04-24 Tom Tromey * nat/windows-nat.h (struct windows_thread_info) : New member. * windows-nat.c (windows_fetch_one_register): Check pc_adjusted. (windows_nat_target::get_windows_debug_event) (windows_nat_target::wait): Set pc_adjusted. --- gdb/ChangeLog | 9 +++++++++ gdb/nat/windows-nat.h | 5 +++++ gdb/windows-nat.c | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c2dc2b6ba80..102edfcbc1f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2020-04-24 Tom Tromey + + * nat/windows-nat.h (struct windows_thread_info) + : New member. + * windows-nat.c (windows_fetch_one_register): Check + pc_adjusted. + (windows_nat_target::get_windows_debug_event) + (windows_nat_target::wait): Set pc_adjusted. + 2020-04-24 Tom de Vries * contrib/cc-with-tweaks.sh: Remove .gdb-index file handling. diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h index 8d0fa9bd216..80c652b22a7 100644 --- a/gdb/nat/windows-nat.h +++ b/gdb/nat/windows-nat.h @@ -93,6 +93,11 @@ struct windows_thread_info breakpoint. This is used to offset the PC when needed. */ bool stopped_at_software_breakpoint = false; + /* True if we've adjusted the PC after hitting a software + breakpoint, false otherwise. This lets us avoid multiple + adjustments if the registers are read multiple times. */ + bool pc_adjusted = false; + /* The name of the thread, allocated by xmalloc. */ gdb::unique_xmalloc_ptr name; }; diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index b857f82eb89..f52af9a1274 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -604,6 +604,7 @@ windows_fetch_one_register (struct regcache *regcache, else { if (th->stopped_at_software_breakpoint + && !th->pc_adjusted && r == gdbarch_pc_regnum (gdbarch)) { int size = register_size (gdbarch, r); @@ -622,6 +623,8 @@ windows_fetch_one_register (struct regcache *regcache, value -= gdbarch_decr_pc_after_break (gdbarch); memcpy (context_offset, &value, size); } + /* Make sure we only rewrite the PC a single time. */ + th->pc_adjusted = true; } regcache->raw_supply (r, context_offset); } @@ -1757,6 +1760,7 @@ windows_nat_target::get_windows_debug_event (int pid, ptid_t ptid = ptid_t (current_event.dwProcessId, thread_id, 0); th = thread_rec (ptid, INVALIDATE_CONTEXT); th->stopped_at_software_breakpoint = true; + th->pc_adjusted = false; } pending_stops.push_back ({thread_id, *ourstatus, current_event}); thread_id = 0; @@ -1835,7 +1839,11 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, || (current_event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) && windows_initialization_done) - current_windows_thread->stopped_at_software_breakpoint = true; + { + current_windows_thread->stopped_at_software_breakpoint + = true; + current_windows_thread->pc_adjusted = false; + } } return result; -- 2.30.2