This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Deliver signal in hardware single step


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5b061e98860ad84315704c732a1a43525f494946

commit 5b061e98860ad84315704c732a1a43525f494946
Author: Yao Qi <yao.qi@linaro.org>
Date:   Fri Apr 22 11:59:18 2016 +0100

    Deliver signal in hardware single step
    
    GDBserver doesn't deliver signal when stepping over a breakpoint even
    hardware single step is used.  When GDBserver started to step over
    (thread creation) breakpoint for mutlit-threaded debugging in 2002 [1],
    GDBserver behaves this way.
    
    This behavior gets trouble on conditional breakpoints on branch to
    self instruction like this,
    
       0x00000000004005b6 <+29>:	jmp    0x4005b6 <main+29>
    
    and I set breakpoint
    
    $(gdb) break branch-to-self.c:43 if counter > 3
    
    and the variable counter will be set to 5 in SIGALRM signal handler.
    Since GDBserver keeps stepping over breakpoint, the SIGALRM can never
    be dequeued and delivered to the inferior, so the program can't stop.
    The test can be found in gdb.base/branch-to-self.exp.
    
    GDBserver didn't deliver signal when stepping over a breakpoint because
    a tracepoint is collected twice if GDBserver does so in the following
    scenario, which can be reproduced by gdb.trace/signal.exp.
    
     - program stops at tracepoint, and tracepoint is collected,
     - gdbserver starts a step-over,
     - a signal arrives, step-over is canceled, and signal should be passed,
     - gdbserver starts a new step-over again, pass the signal as well,
     - program stops at the entry of signal handler, step-over finished,
     - gdbserver proceeds,
     - program returns from the signal handler, again to the tracepoint,
       and thus is collected again.
    
    The spurious collection isn't that harmful, IMO, so it should be OK
    to let GDBserver deliver signal when stepping over a breakpoint.
    
    gdb/gdbserver:
    
    2016-04-22  Yao Qi  <yao.qi@linaro.org>
    
    	* linux-low.c (lwp_signal_can_be_delivered): Don't deliver
    	signal when stepping over breakpoint with software single
    	step.
    
    gdb/testsuite:
    
    2016-04-22  Yao Qi  <yao.qi@linaro.org>
    
    	* gdb.trace/signal.exp: Also pass if
    	$tracepoint_hits($i) > $iterations.

Diff:
---
 gdb/gdbserver/ChangeLog            |  6 ++++++
 gdb/gdbserver/linux-low.c          | 10 +++++++---
 gdb/testsuite/ChangeLog            |  5 +++++
 gdb/testsuite/gdb.trace/signal.exp | 12 ++++++++++--
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index db76e1a..e0ed616 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,9 @@
+2016-04-22  Yao Qi  <yao.qi@linaro.org>
+
+	* linux-low.c (lwp_signal_can_be_delivered): Don't deliver
+	signal when stepping over breakpoint with software single
+	step.
+
 2016-04-21  Pedro Alves  <palves@redhat.com>
 
 	* linux-s390-low.c (s390_collect_ptrace_register)
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 7630f9f..5cbd308 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -4119,13 +4119,17 @@ single_step (struct lwp_info* lwp)
 }
 
 /* The signal can be delivered to the inferior if we are not trying to
-   reinsert a breakpoint and not trying to finish a fast tracepoint
-   collect.  */
+   reinsert a breakpoint for software single step and not trying to
+   finish a fast tracepoint collect.  Since signal can be delivered in
+   the step-over, the program may go to signal handler and trap again
+   after return from the signal handler.  We can live with the spurious
+   double traps.  */
 
 static int
 lwp_signal_can_be_delivered (struct lwp_info *lwp)
 {
-  return (lwp->bp_reinsert == 0 && !lwp->collecting_fast_tracepoint);
+  return (!(lwp->bp_reinsert != 0 && can_software_single_step ())
+	  && !lwp->collecting_fast_tracepoint);
 }
 
 /* Resume execution of LWP.  If STEP is nonzero, single-step it.  If
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 29447af..249cbc0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2016-04-22  Yao Qi  <yao.qi@linaro.org>
 
+	* gdb.trace/signal.exp: Also pass if
+	$tracepoint_hits($i) > $iterations.
+
+2016-04-22  Yao Qi  <yao.qi@linaro.org>
+
 	* gdb.trace/signal.c: New file.
 	* gdb.trace/signal.exp: New file.
 
diff --git a/gdb/testsuite/gdb.trace/signal.exp b/gdb/testsuite/gdb.trace/signal.exp
index 7118a9f..48e495e 100644
--- a/gdb/testsuite/gdb.trace/signal.exp
+++ b/gdb/testsuite/gdb.trace/signal.exp
@@ -174,6 +174,14 @@ while { 1 } {
 # Step 3, check the number of collections on each tracepoint.
 
 for { set i $tpnum } { $i < [expr $tpnum + 2] } { incr i } {
-    gdb_assert { $tracepoint_hits($i) == $iterations } \
-	"tracepoint $i hit $iterations times"
+
+    if { $tracepoint_hits($i) == $iterations } {
+	pass "tracepoint $i hit $iterations times"
+    } elseif { $tracepoint_hits($i) > $iterations } {
+	# GDBserver deliver the signal while stepping over tracepoint,
+	# so it is possible that a tracepoint is collected twice.
+	pass "tracepoint $i hit $iterations times (spurious collection)"
+    } else {
+	fail "tracepoint $i hit $iterations times"
+    }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]