summaryrefslogtreecommitdiff
path: root/gdbserver/win32-low.cc
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2020-04-08 14:33:35 -0600
committerTom Tromey <tromey@adacore.com>2020-04-08 14:47:59 -0600
commit523d4f80c32f43a6b009645947b94f87df35f79f (patch)
tree244948a1e348e64a1d3e991fd0fa011c3a18dac7 /gdbserver/win32-low.cc
parente54e59297a747bb4f396345aa090d43f155b5576 (diff)
downloadbinutils-gdb-523d4f80c32f43a6b009645947b94f87df35f79f.tar.gz
Implement stopped_by_sw_breakpoint for Windows gdbserver
This changes the Windows gdbserver port to implement the stopped_by_sw_breakpoint target method. This is needed to support pending stops. This is a separate patch now, because Pedro suggested splitting it out for simpler bisecting, in the case that it introduces a bug. gdbserver/ChangeLog 2020-04-08 Tom Tromey <tromey@adacore.com> * win32-low.h (win32_process_target::stopped_by_sw_breakpoint) (win32_process_target::supports_stopped_by_sw_breakpoint): Declare. * win32-low.c (win32_supports_z_point_type): Always handle Z_PACKET_SW_BP. (win32_insert_point): Call insert_memory_breakpoint when needed. (win32_remove_point): Call remove_memory_breakpoint when needed. (win32_process_target::stopped_by_sw_breakpoint) (win32_process_target::supports_stopped_by_sw_breakpoint): New methods. (win32_target_ops): Update. (maybe_adjust_pc): New function. (win32_wait): Call maybe_adjust_pc.
Diffstat (limited to 'gdbserver/win32-low.cc')
-rw-r--r--gdbserver/win32-low.cc67
1 files changed, 55 insertions, 12 deletions
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 131eacb13c4..4312bb3ab7c 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -236,15 +236,18 @@ child_delete_thread (DWORD pid, DWORD tid)
bool
win32_process_target::supports_z_point_type (char z_type)
{
- return (the_low_target.supports_z_point_type != NULL
- && the_low_target.supports_z_point_type (z_type));
+ return (z_type == Z_PACKET_SW_BP
+ || (the_low_target.supports_z_point_type != NULL
+ && the_low_target.supports_z_point_type (z_type)));
}
int
win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp)
{
- if (the_low_target.insert_point != NULL)
+ if (type == raw_bkpt_type_sw)
+ return insert_memory_breakpoint (bp);
+ else if (the_low_target.insert_point != NULL)
return the_low_target.insert_point (type, addr, size, bp);
else
/* Unsupported (see target.h). */
@@ -255,7 +258,9 @@ int
win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp)
{
- if (the_low_target.remove_point != NULL)
+ if (type == raw_bkpt_type_sw)
+ return remove_memory_breakpoint (bp);
+ else if (the_low_target.remove_point != NULL)
return the_low_target.remove_point (type, addr, size, bp);
else
/* Unsupported (see target.h). */
@@ -1189,6 +1194,32 @@ windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
return false;
}
+/* A helper function that will, if needed, set
+ 'stopped_at_software_breakpoint' on the thread and adjust the
+ PC. */
+
+static void
+maybe_adjust_pc ()
+{
+ struct regcache *regcache = get_thread_regcache (current_thread, 1);
+ child_fetch_inferior_registers (regcache, -1);
+
+ windows_thread_info *th = thread_rec (current_thread_ptid (),
+ DONT_INVALIDATE_CONTEXT);
+ th->stopped_at_software_breakpoint = false;
+
+ if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+ && (current_event.u.Exception.ExceptionRecord.ExceptionCode
+ == EXCEPTION_BREAKPOINT)
+ && child_initialization_done)
+ {
+ th->stopped_at_software_breakpoint = true;
+ CORE_ADDR pc = regcache_read_pc (regcache);
+ CORE_ADDR sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break;
+ regcache_write_pc (regcache, sw_breakpoint_pc);
+ }
+}
+
/* Get the next event from the child. */
static int
@@ -1417,8 +1448,6 @@ ptid_t
win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
int options)
{
- struct regcache *regcache;
-
if (cached_status.kind != TARGET_WAITKIND_IGNORE)
{
/* The core always does a wait after creating the inferior, and
@@ -1446,12 +1475,12 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_SIGNALLED:
case TARGET_WAITKIND_LOADED:
- OUTMSG2 (("Child Stopped with signal = %d \n",
- ourstatus->value.sig));
-
- regcache = get_thread_regcache (current_thread, 1);
- child_fetch_inferior_registers (regcache, -1);
- return debug_event_ptid (&current_event);
+ {
+ OUTMSG2 (("Child Stopped with signal = %d \n",
+ ourstatus->value.sig));
+ maybe_adjust_pc ();
+ return debug_event_ptid (&current_event);
+ }
default:
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */
@@ -1659,6 +1688,20 @@ win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
return the_low_target.breakpoint;
}
+bool
+win32_process_target::stopped_by_sw_breakpoint ()
+{
+ windows_thread_info *th = thread_rec (current_thread_ptid (),
+ DONT_INVALIDATE_CONTEXT);
+ return th == nullptr ? false : th->stopped_at_software_breakpoint;
+}
+
+bool
+win32_process_target::supports_stopped_by_sw_breakpoint ()
+{
+ return true;
+}
+
CORE_ADDR
win32_process_target::read_pc (struct regcache *regcache)
{