gdbserver: redo stepping over breakpoint that was on top of a permanent breakpoint

I'm going to add an alternate mechanism of breakpoint trap
identification to 'check_stopped_by_breakpoint' that does not rely on
checking the instruction at PC.  The mechanism currently used to tell
whether we're stepping over a permanent breakpoint doesn't fit in that
new method.  This patch redoes the whole logic in a different way that
works with both old and new methods, in essence moving the "stepped
permanent breakpoint" detection "one level up".  It makes lower level
check_stopped_by_breakpoint always the adjust the PC, and then has
linux_wait_1 advance the PC past the breakpoint if necessary.  This
ends up being better also because this now handles
non-decr_pc_after_break targets too.  Before, such targets would get
stuck forever reexecuting the breakpoint instruction.

Tested on x86_64 Fedora 20.

gdb/gdbserver/ChangeLog:
2015-02-23  Pedro Alves  <palves@redhat.com>

	* linux-low.c (check_stopped_by_breakpoint): Don't check if the
	thread was doing a step-over; always adjust the PC if
	we stepped over a permanent breakpoint.
	(linux_wait_1): If we stepped over breakpoint that was on top of a
	permanent breakpoint, manually advance the PC past it.
This commit is contained in:
Pedro Alves 2015-02-23 18:59:38 +00:00
parent d8b901edd1
commit 8090aef2bf
2 changed files with 45 additions and 8 deletions

View File

@ -1,3 +1,11 @@
2015-02-23 Pedro Alves <palves@redhat.com>
* linux-low.c (check_stopped_by_breakpoint): Don't check if the
thread was doing a step-over; always adjust the PC if
we stepped over a permanent breakpoint.
(linux_wait_1): If we stepped over breakpoint that was on top of a
permanent breakpoint, manually advance the PC past it.
2015-02-23 Pedro Alves <palves@redhat.com>
* linux-x86-low.c (REGSIZE): Define in both 32-bit and 64-bit

View File

@ -507,14 +507,8 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
/* We may have just stepped a breakpoint instruction. E.g., in
non-stop mode, GDB first tells the thread A to step a range, and
then the user inserts a breakpoint inside the range. In that
case, we need to report the breakpoint PC. But, when we're
trying to step past one of our own breakpoints, that happens to
have been placed on top of a permanent breakpoint instruction, we
shouldn't adjust the PC, otherwise the program would keep
trapping the permanent breakpoint forever. */
if ((!lwp->stepping
|| (!ptid_equal (ptid_of (current_thread), step_over_bkpt)
&& lwp->stop_pc == sw_breakpoint_pc))
case we need to report the breakpoint PC. */
if ((!lwp->stepping || lwp->stop_pc == sw_breakpoint_pc)
&& (*the_low_target.breakpoint_at) (sw_breakpoint_pc))
{
if (debug_threads)
@ -2552,6 +2546,41 @@ linux_wait_1 (ptid_t ptid,
return ptid_of (current_thread);
}
/* If step-over executes a breakpoint instruction, it means a
gdb/gdbserver breakpoint had been planted on top of a permanent
breakpoint. The PC has been adjusted by
check_stopped_by_breakpoint to point at the breakpoint address.
Advance the PC manually past the breakpoint, otherwise the
program would keep trapping the permanent breakpoint forever. */
if (!ptid_equal (step_over_bkpt, null_ptid)
&& event_child->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
{
unsigned int increment_pc;
if (the_low_target.breakpoint_len > the_low_target.decr_pc_after_break)
increment_pc = the_low_target.breakpoint_len;
else
increment_pc = the_low_target.decr_pc_after_break;
if (debug_threads)
{
debug_printf ("step-over for %s executed software breakpoint\n",
target_pid_to_str (ptid_of (current_thread)));
}
if (increment_pc != 0)
{
struct regcache *regcache
= get_thread_regcache (current_thread, 1);
event_child->stop_pc += increment_pc;
(*the_low_target.set_pc) (regcache, event_child->stop_pc);
if (!(*the_low_target.breakpoint_at) (event_child->stop_pc))
event_child->stop_reason = LWP_STOPPED_BY_NO_REASON;
}
}
/* If this event was not handled before, and is not a SIGTRAP, we
report it. SIGILL and SIGSEGV are also treated as traps in case
a breakpoint is inserted at the current PC. If this target does