public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Yao Qi <qiyaoltc@gmail.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH 3/8] Deliver signal in hardware single step
Date: Thu, 17 Mar 2016 12:12:00 -0000	[thread overview]
Message-ID: <56EA9F45.7050409@redhat.com> (raw)
In-Reply-To: <86io0mya1n.fsf@gmail.com>

On 03/16/2016 10:47 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
> Hi Pedro,
> 
>> - If there's a signal handler installed, we'll stop at its entry,
>>    but we haven't stepped over the original breakpoint yet.  If we
>>    were already stopped at the entry of the signal handler, and it
>>    nested, we'll find the program stopped at the same PC it had
>>    started at.  But we won't know whether the step-over finished
>>    successfully (could be a "jmp $pc" instruction), or if instead we're
>>    in a new handler invocation, and thus this is a new,
>>    separate breakpoint hit.
> 
> GDBserver doesn't have to tell the program stopped at the same PC
> it had started at when step over is finished.  When step over, GDBserver
> uninsert breakpoint, resumes the lwp, and wait the next event from the
> lwp.  Once the event from the lwp arrives, GDBserver reinsert breakpoint
> and thinks step over is finished.  That is all ...
> 
>>
>>    A signal handler that segfaults in the first instruction
>>    would be the easiest way to reproduce this that I can think of.
>>    (If it's crashing, you'd expect the user might try putting a
>>    breakpoint there.)
> 
> I write a case like this, set the conditional breakpoint on the first
> instruction of handler, and looks breakpoint condition in target side
> still works properly.
> 
> (gdb) disassemble handler
> Dump of assembler code for function handler:
>     0x0000000000400586 <+0>:     movb   $0x0,0x0
>     0x000000000040058e <+8>:     retq
> 
> (gdb) p/x $rsp
> $1 = 0x7fffffffde00
> (gdb) b *handler if $rsp < 0x7fffffffde00 - 3300
> 
> the condition like this can guarantee that the condition will be true
> after several recursions.
> 
>>
>>    Now, if after stepping into the handler, we immediately reinsert the
>>    breakpoint and continue, we'll retrap it, it ends up OK.
> 
> breakpoint is reinserted after stepping into the handler, because
> GDBserver thinks step over is finished, as I said above.
> 
>>    But if we immediately instead start a new step-over for the same
>>    breakpoint address, we will miss the new hit, and nest a new handler,
>>    on and on.
> 
> This won't happen.  After hardware single step with signal delivered,
> the program stops at the entry of handler, and GDBserver gets an event.
> Then, GDBserver thinks step over is finished, and then proceed all lwps.
> However, the thread still stopped at the breakpoint (of different
> stack frames), so it needs step over again. 

> The loop like this will go
> on until the breakpoint condition is true, need_step_over_p decides to
> resume rather than step over.  The program will hit the breakpoint, and
> GDBserver reports the event back to GDB.
> 
> Note in my experiment with the test case above, I don't let GDBserver
> treat SIGSEGV as SIGTRAP, otherwise SIGSEGV will be reported back to GDB.
> 

OK.

We need to think of unconditional tracepoints as well,
not just conditional breakpoints, however.

Here's a likely scenario, that I think will happen:

#1 - tracepoint set at 0xf00.
#2 - Program stops at 0xf00, tracepoint is collected.
#3 - gdbserver starts a step-over
#4 - instead, a signal arrives, step-over cancelled.
#5 - signal should be passed, not reported to gdb.
#6 - gdbserver starts a new step-over, passing signal as well.
#7 - step lands in handler. step over finished.
#8 - gdbserver proceeds/continues
#9 - signal handler returns, again to 0xf00, tracepoint
     traps again and is thus collected again. This is a
     spurious collection.

gdb avoids the spurious double-hit in #9 by remembering that
it was stepping over a breakpoint when a signal arrived, in
order to continue the step over once the handler returns
(tp->step_after_step_resume_breakpoint).  This only works if the handler 
doesn't cause some other unrelated user-visible stop -- in that case,
then the next time the user continues the program, and the
handler returns to the original breakpoint address, we'll still
report a new breakpoint hit.  I think.

Maybe we can just not bother and live with the spurious double
tracepoint hit/collect in gdbserver.  (Likewise dprintf.)
Dunno, but I'm now starting to lean toward that.

Thanks,
Pedro Alves

  reply	other threads:[~2016-03-17 12:12 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-04 10:44 [PATCH 0/8] Step over instruction branches to itself Yao Qi
2016-03-04 10:44 ` [PATCH 7/8] Resume the inferior with signal rather than stepping over Yao Qi
2016-03-11 12:04   ` Pedro Alves
2016-03-21  9:40     ` Yao Qi
2016-03-04 10:44 ` [PATCH 4/8] Force to insert software single step breakpoint Yao Qi
2016-03-11 11:49   ` Pedro Alves
2016-03-16 11:47     ` Yao Qi
2016-03-17 12:40       ` Pedro Alves
2016-03-18 14:25         ` Yao Qi
2016-03-18 15:03           ` Pedro Alves
2016-03-04 10:44 ` [PATCH 6/8] [GDBserver] Don't error in reinsert_raw_breakpoint if bp->inserted Yao Qi
2016-03-04 10:44 ` [PATCH 2/8] Check LWP_SIGNAL_CAN_BE_DELIVERED for enqueue/dequeue pending signals Yao Qi
2016-03-11 10:55   ` Pedro Alves
2016-03-17  8:40     ` Yao Qi
2016-03-17 11:07       ` Pedro Alves
2016-03-18 14:36         ` Yao Qi
2016-03-16 17:02   ` Luis Machado
2016-03-04 10:44 ` [PATCH 3/8] Deliver signal in hardware single step Yao Qi
2016-03-11 11:05   ` Pedro Alves
2016-03-11 11:09     ` Pedro Alves
2016-03-11 11:37       ` Pedro Alves
2016-03-16 10:47         ` Yao Qi
2016-03-17 12:12           ` Pedro Alves [this message]
2016-03-04 10:44 ` [PATCH 1/8] Set signal to 0 after enqueue_pending_signal Yao Qi
2016-03-11 10:53   ` Pedro Alves
2016-03-18 14:36     ` Yao Qi
2016-03-04 10:45 ` [PATCH 5/8] Insert breakpoint even when the raw breakpoint is found Yao Qi
2016-03-11 11:54   ` Pedro Alves
2016-03-04 10:45 ` [PATCH 8/8] New test case gdb.base/branch-to-self.exp Yao Qi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56EA9F45.7050409@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=qiyaoltc@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).