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.
This commit is contained in:
parent
e54e59297a
commit
523d4f80c3
3 changed files with 75 additions and 12 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2020-04-08 Tom Tromey <tromey@adacore.com>
|
2020-04-08 Tom Tromey <tromey@adacore.com>
|
||||||
|
|
||||||
* win32-low.h (struct win32_target_ops) <decr_pc_after_break>: New
|
* win32-low.h (struct win32_target_ops) <decr_pc_after_break>: New
|
||||||
|
|
|
@ -236,15 +236,18 @@ child_delete_thread (DWORD pid, DWORD tid)
|
||||||
bool
|
bool
|
||||||
win32_process_target::supports_z_point_type (char z_type)
|
win32_process_target::supports_z_point_type (char z_type)
|
||||||
{
|
{
|
||||||
return (the_low_target.supports_z_point_type != NULL
|
return (z_type == Z_PACKET_SW_BP
|
||||||
&& the_low_target.supports_z_point_type (z_type));
|
|| (the_low_target.supports_z_point_type != NULL
|
||||||
|
&& the_low_target.supports_z_point_type (z_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
|
win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
|
||||||
int size, raw_breakpoint *bp)
|
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);
|
return the_low_target.insert_point (type, addr, size, bp);
|
||||||
else
|
else
|
||||||
/* Unsupported (see target.h). */
|
/* Unsupported (see target.h). */
|
||||||
|
@ -255,7 +258,9 @@ int
|
||||||
win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
|
win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
|
||||||
int size, raw_breakpoint *bp)
|
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);
|
return the_low_target.remove_point (type, addr, size, bp);
|
||||||
else
|
else
|
||||||
/* Unsupported (see target.h). */
|
/* Unsupported (see target.h). */
|
||||||
|
@ -1189,6 +1194,32 @@ windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
|
||||||
return false;
|
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. */
|
/* Get the next event from the child. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1417,8 +1448,6 @@ ptid_t
|
||||||
win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
||||||
int options)
|
int options)
|
||||||
{
|
{
|
||||||
struct regcache *regcache;
|
|
||||||
|
|
||||||
if (cached_status.kind != TARGET_WAITKIND_IGNORE)
|
if (cached_status.kind != TARGET_WAITKIND_IGNORE)
|
||||||
{
|
{
|
||||||
/* The core always does a wait after creating the inferior, and
|
/* 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_STOPPED:
|
||||||
case TARGET_WAITKIND_SIGNALLED:
|
case TARGET_WAITKIND_SIGNALLED:
|
||||||
case TARGET_WAITKIND_LOADED:
|
case TARGET_WAITKIND_LOADED:
|
||||||
|
{
|
||||||
OUTMSG2 (("Child Stopped with signal = %d \n",
|
OUTMSG2 (("Child Stopped with signal = %d \n",
|
||||||
ourstatus->value.sig));
|
ourstatus->value.sig));
|
||||||
|
maybe_adjust_pc ();
|
||||||
regcache = get_thread_regcache (current_thread, 1);
|
|
||||||
child_fetch_inferior_registers (regcache, -1);
|
|
||||||
return debug_event_ptid (¤t_event);
|
return debug_event_ptid (¤t_event);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
|
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
@ -1659,6 +1688,20 @@ win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
|
||||||
return the_low_target.breakpoint;
|
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
|
CORE_ADDR
|
||||||
win32_process_target::read_pc (struct regcache *regcache)
|
win32_process_target::read_pc (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
|
|
|
@ -155,6 +155,10 @@ public:
|
||||||
CORE_ADDR read_pc (regcache *regcache) override;
|
CORE_ADDR read_pc (regcache *regcache) override;
|
||||||
|
|
||||||
void write_pc (regcache *regcache, CORE_ADDR pc) override;
|
void write_pc (regcache *regcache, CORE_ADDR pc) override;
|
||||||
|
|
||||||
|
bool stopped_by_sw_breakpoint () override;
|
||||||
|
|
||||||
|
bool supports_stopped_by_sw_breakpoint () override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Retrieve the context for this thread, if not already retrieved. */
|
/* Retrieve the context for this thread, if not already retrieved. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue