public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 00/23] All-stop on top of non-stop
@ 2015-04-07 12:49 Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
                   ` (24 more replies)
  0 siblings, 25 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:49 UTC (permalink / raw)
  To: gdb-patches

This is v2 of the series first posted at:
  https://sourceware.org/ml/gdb-patches/2015-04/msg00073.html

While v1 had only been tested on x86-64 GNU/Linux, v2 was tested on:

     x86-64 GNU/Linux
     x86-64 GNU/Linux on top of software single-step branch
     PPC64 GNU/Linux
     S/390 GNU/Linux

The extra testing showed a few problems, mostly exposing prexisting
problems with displaced stepping support, but it caught a few bugs in
new code too here and there.  As a result, the series grew a few new
patches:

 - Patches #1, #8, #9 #10, #20, #21 and #22 are new in v2.

 - Old v1 patch #3 has been pushed to master meanwhile.

I tried to mention the differences to v1 in each patch that had
changes, if any (scroll past ChangeLog).

Due to extra testing and fixing I'm also much more confident in this
series.

Note most of these patches can go in without the final bits that
actually do all-stop-on-top-of-non-stop, as they fix problems that
exist e.g., with "set non-stop on" or "set displaced-stepping on" too.

I've (force) pushed this to users/palves/all-stop-non-stop for review
convenience.

Series-intro proper follows:

This series implements user-visible all-stop mode running with the
target_ops backend always in non-stop mode.  This is a stepping stone
towards finer-grained control of threads, being able to do interesting
things like inferior and thread groups/sets (itsets), associating
groups with breakpoints (which threads cause a stop, which threads are
implicitly paused when a breakpoint triggers), etc.  From the user's
perspective, all-stop mode is really just a special case of being able
to stop and resume specific sets of threads, so it makes sense to do
this step first.

After this series, even in all-stop mode ("set non-stop off", the
default) the target is no longer in charge of stopping all threads
before reporting an event to the core -- the core takes care of it
when it sees fit.  For example, when "next"- or "step"-ing, we can
avoid stopping and resuming all threads at each internal single-step,
and instead only stop all threads when we're about to present the stop
to the user.

In order to get there, the series teaches GDB to do non-stop mode even
without displaced stepping (stop all threads, step over breakpoint,
restart threads), as displaced stepping isn't implemented everywhere,
and doesn't work in some scenarios (as in, we can't use it, not that
it's buggy).

And then it fixes all testsuite regressions (on native x86-64
GNU/Linux) this new mode causes, compared to all-stop ("set non-stop
off") with the target backend in all-stop mode too (i.e., the current
default).  Making "target remote" work in always non-stop mode is
deferred for later (this will be even more useful for remote as the
all-stop mode RSP variant can't really do asynchronous debugging).

Tested on x86_64 Fedora 20, native, with and without "set displaced
off", and with and without "maint set target-non-stop on"; and also
against gdbserver.  Tested on x86-64 GNU/Linux native on top of x86
software single-step branch.  Tested on PPC64 Fedora 18.  Tested on
S/390 RHEL 7.1.

Pedro Alves (23):
  Fix gdb.base/sigstep.exp with displaced stepping on software
    single-step targets
  Fix and test "checkpoint" in non-stop mode
  PR13858 - Can't do displaced stepping with no symbols
  Change adjust_pc_after_break's prototype
  remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and
    TARGET_WNOHANG
  Make thread_still_needs_step_over consider stepping_over_watchpoint
    too
  Embed the pending step-over chain in thread_info objects
  Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with
    displaced stepping
  Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86
  PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping
    on
  Use keep_going in proceed and start_step_over too
  Misc switch_back_to_stepped_thread cleanups
  Factor out code to re-resume stepped thread
  Teach non-stop to do in-line step-overs (stop all, step, restart)
  Implement all-stop on top of a target running non-stop mode
  Fix signal-while-stepping-over-bp-other-thread.exp on targets always
    in non-stop
  Fix interrupt-noterm.exp on targets always in non-stop
  Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race
  Disable displaced stepping if trying it fails
  PPC64: symbol-file + exec-file results in broken displaced stepping
  PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with displaced stepping
  S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions
  native Linux: enable always non-stop by default

 gdb/NEWS                                           |    6 +
 gdb/breakpoint.c                                   |   11 +-
 gdb/darwin-nat.c                                   |    6 +-
 gdb/doc/gdb.texinfo                                |   24 +
 gdb/gdbthread.h                                    |   57 +-
 gdb/gnu-nat.c                                      |    7 -
 gdb/inf-ptrace.c                                   |    6 +-
 gdb/infcmd.c                                       |    6 +-
 gdb/inferior.h                                     |    8 +
 gdb/infrun.c                                       | 2199 +++++++++++++++-----
 gdb/infrun.h                                       |    3 +
 gdb/linux-nat.c                                    |   33 +-
 gdb/monitor.c                                      |    4 +-
 gdb/nto-procfs.c                                   |   14 +-
 gdb/procfs.c                                       |    4 +-
 gdb/remote-m32r-sdi.c                              |    6 +-
 gdb/remote-sim.c                                   |   20 +-
 gdb/remote.c                                       |   57 +-
 gdb/rs6000-tdep.c                                  |   68 +-
 gdb/s390-linux-tdep.c                              |  115 +-
 gdb/symfile.c                                      |   21 +
 gdb/target-delegates.c                             |   59 +
 gdb/target.c                                       |   83 +
 gdb/target.h                                       |   24 +-
 gdb/target/waitstatus.h                            |    5 +-
 gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp       |   50 +-
 gdb/testsuite/gdb.base/checkpoint-ns.exp           |   27 +
 gdb/testsuite/gdb.base/checkpoint.exp              |   31 +-
 gdb/testsuite/gdb.base/sigstep.exp                 |   86 +-
 gdb/testsuite/gdb.base/step-over-no-symbols.exp    |   88 +
 gdb/testsuite/gdb.base/symbol-file-exec-file.c     |   30 +
 gdb/testsuite/gdb.base/symbol-file-exec-file.exp   |  126 ++
 gdb/testsuite/gdb.base/valgrind-disp-step.c        |   32 +
 gdb/testsuite/gdb.base/valgrind-disp-step.exp      |  131 ++
 .../signal-while-stepping-over-bp-other-thread.exp |   20 +-
 .../gdb.threads/step-over-lands-on-breakpoint.c    |   17 +-
 .../gdb.threads/step-over-lands-on-breakpoint.exp  |   24 +-
 .../gdb.threads/step-over-trips-on-watchpoint.c    |   19 +-
 .../gdb.threads/step-over-trips-on-watchpoint.exp  |   65 +-
 gdb/thread.c                                       |  206 +-
 gdb/windows-nat.c                                  |    6 +-
 41 files changed, 3036 insertions(+), 768 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/checkpoint-ns.exp
 create mode 100644 gdb/testsuite/gdb.base/step-over-no-symbols.exp
 create mode 100644 gdb/testsuite/gdb.base/symbol-file-exec-file.c
 create mode 100644 gdb/testsuite/gdb.base/symbol-file-exec-file.exp
 create mode 100644 gdb/testsuite/gdb.base/valgrind-disp-step.c
 create mode 100644 gdb/testsuite/gdb.base/valgrind-disp-step.exp

-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 12/23] Misc switch_back_to_stepped_thread cleanups
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (2 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 02/23] Fix and test "checkpoint" in non-stop mode Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 20/23] PPC64: symbol-file + exec-file results in broken displaced stepping Pedro Alves
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Several misc cleanups that prepare the tail end of this function, the
part that actually re-resumes the stepped thread.

The most non-obvious would be the currently_stepping change, I guess.
That's because it isn't ever correct to pass step=1 to target_resume
on software single-step targets, and currently_stepping works at a
conceptual higher level, it returns step=true even on software step
targets.  It doesn't really matter on hardware step targets, as the
breakpoint will be hit immediately, but it's just wrong on software
step targets.  I tested it against my x86 software single-step branch,
and it indeed fixes failed assertions (that catch spurious
PTRACE_SINGLESTEP requests) there.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (switch_back_to_stepped_thread): Use ecs->ptid instead
	pf inferior_ptid.  If the stepped thread vanished, return 0
	instead of resuming here.  Use reset_ecs.  Print the prev_pc and
	the current stop_pc in log message.  Clear trap_expected if the
	thread advanced.  Don't pass currently_stepping to
	do_target_resume.
---
 gdb/infrun.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 3e64c99..87bbe03 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5722,7 +5722,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
         {
 	  /* Ignore threads of processes we're not resuming.  */
 	  if (!sched_multi
-	      && ptid_get_pid (tp->ptid) != ptid_get_pid (inferior_ptid))
+	      && ptid_get_pid (tp->ptid) != ptid_get_pid (ecs->ptid))
 	    continue;
 
 	  /* When stepping over a breakpoint, we lock all threads
@@ -5786,19 +5786,17 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 				    "stepped thread, it has vanished\n");
 
 	      delete_thread (tp->ptid);
-	      keep_going (ecs);
-	      return 1;
+	      return 0;
 	    }
 
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog,
 				"infrun: switching back to stepped thread\n");
 
-	  ecs->event_thread = tp;
-	  ecs->ptid = tp->ptid;
-	  context_switch (ecs->ptid);
+	  reset_ecs (ecs, tp);
+	  switch_to_thread (tp->ptid);
 
-	  stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+	  stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
 	  frame = get_current_frame ();
 	  gdbarch = get_frame_arch (frame);
 
@@ -5822,23 +5820,28 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
 	      if (debug_infrun)
 		fprintf_unfiltered (gdb_stdlog,
-				    "infrun: expected thread advanced also\n");
+				    "infrun: expected thread advanced also "
+				    "(%s -> %s)\n",
+				    paddress (target_gdbarch (), tp->prev_pc),
+				    paddress (target_gdbarch (), stop_pc));
 
 	      /* Clear the info of the previous step-over, as it's no
-		 longer valid.  It's what keep_going would do too, if
-		 we called it.  Must do this before trying to insert
-		 the sss breakpoint, otherwise if we were previously
-		 trying to step over this exact address in another
-		 thread, the breakpoint ends up not installed.  */
+		 longer valid (if the thread was trying to step over a
+		 breakpoint, it has already succeeded).  It's what
+		 keep_going would do too, if we called it.  Do this
+		 before trying to insert the sss breakpoint, otherwise
+		 if we were previously trying to step over this exact
+		 address in another thread, the breakpoint is
+		 skipped.  */
 	      clear_step_over_info ();
+	      tp->control.trap_expected = 0;
 
 	      insert_single_step_breakpoint (get_frame_arch (frame),
 					     get_frame_address_space (frame),
 					     stop_pc);
 
 	      resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
-	      do_target_resume (resume_ptid,
-				currently_stepping (tp), GDB_SIGNAL_0);
+	      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
 	      prepare_to_wait (ecs);
 	    }
 	  else
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 04/23] Change adjust_pc_after_break's prototype
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (6 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 11/23] Use keep_going in proceed and start_step_over too Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 22/23] S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions Pedro Alves
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Prepare to use it in contexts without an ecs handy.  Follow up patches
will make use of this.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <pedro@codesourcery.com>

	* infrun.c (adjust_pc_after_break): Now takes thread_info and
	waitstatus pointers instead of an ecs.  Adjust.
	(handle_inferior_event): Adjust caller.
---
 gdb/infrun.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 48da790..1e8ee4f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3450,8 +3450,14 @@ context_switch (ptid_t ptid)
   switch_to_thread (ptid);
 }
 
+/* If the target can't tell whether we've hit breakpoints
+   (target_supports_stopped_by_sw_breakpoint), and we got a SIGTRAP,
+   check whether that could have been caused by a breakpoint.  If so,
+   adjust the PC, per gdbarch_decr_pc_after_break.  */
+
 static void
-adjust_pc_after_break (struct execution_control_state *ecs)
+adjust_pc_after_break (struct thread_info *thread,
+		       struct target_waitstatus *ws)
 {
   struct regcache *regcache;
   struct gdbarch *gdbarch;
@@ -3479,10 +3485,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      target with both of these set in GDB history, and it seems unlikely to be
      correct, so gdbarch_have_nonsteppable_watchpoint is not checked here.  */
 
-  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
+  if (ws->kind != TARGET_WAITKIND_STOPPED)
     return;
 
-  if (ecs->ws.value.sig != GDB_SIGNAL_TRAP)
+  if (ws->value.sig != GDB_SIGNAL_TRAP)
     return;
 
   /* In reverse execution, when a breakpoint is hit, the instruction
@@ -3528,7 +3534,7 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 
   /* If this target does not decrement the PC after breakpoints, then
      we have nothing to do.  */
-  regcache = get_thread_regcache (ecs->ptid);
+  regcache = get_thread_regcache (thread->ptid);
   gdbarch = get_regcache_arch (regcache);
 
   decr_pc = gdbarch_decr_pc_after_break (gdbarch);
@@ -3582,10 +3588,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 	 software breakpoint.  In this case (prev_pc == breakpoint_pc),
 	 we also need to back up to the breakpoint address.  */
 
-      if (thread_has_single_step_breakpoints_set (ecs->event_thread)
-	  || !currently_stepping (ecs->event_thread)
-	  || (ecs->event_thread->stepped_breakpoint
-	      && ecs->event_thread->prev_pc == breakpoint_pc))
+      if (thread_has_single_step_breakpoints_set (thread)
+	  || !currently_stepping (thread)
+	  || (thread->stepped_breakpoint
+	      && thread->prev_pc == breakpoint_pc))
 	regcache_write_pc (regcache, breakpoint_pc);
 
       do_cleanups (old_cleanups);
@@ -3766,7 +3772,7 @@ handle_inferior_event (struct execution_control_state *ecs)
     }
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
-  adjust_pc_after_break (ecs);
+  adjust_pc_after_break (ecs->event_thread, &ecs->ws);
 
   /* Dependent on the current PC value modified by adjust_pc_after_break.  */
   reinit_frame_cache ();
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 11/23] Use keep_going in proceed and start_step_over too
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (5 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with " Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 04/23] Change adjust_pc_after_break's prototype Pedro Alves
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

The main motivation of this patch is sharing more code between the
proceed (starting the inferior for the first time) and keep_going
(restarting the inferior after handling an event) paths and using the
step_over_chain queue now embedded in the thread_info object for
in-line step-overs too (instead of just for displaced stepping).

So this commit:

 - splits out a new keep_going_pass function out of keep_going that is
   just like keep_going except for the bits that clear the signal to
   pass if the signal is set to "handle nopass".

 - makes proceed use keep_going too.

 - Makes start_step_over use keep_going_pass instead of lower level
   displaced stepping things.

One user visible change.  If inserting breakpoints while trying to
proceed fails, we now get:

  (gdb) si
  Warning:
  Could not insert hardware watchpoint 7.
  Could not insert hardware breakpoints:
  You may have requested too many hardware breakpoints/watchpoints.

  Command aborted.
  (gdb)

while before we only saw warnings with no indication that the command
was cancelled:

  (gdb) si
  Warning:
  Could not insert hardware watchpoint 7.
  Could not insert hardware breakpoints:
  You may have requested too many hardware breakpoints/watchpoints.

  (gdb)

Tested on x86_64 Fedora 20, and PPC64 Fedora 18.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdbthread.h (struct thread_info) <prev_pc>: Extend comment.
	* infrun.c (struct execution_control_state): Move higher up in the
	file.
	(reset_ecs): New function.
	(start_step_over_inferior): Now returns int.  Rewrite to use
	keep_going_pass instead of manually starting a displaced step.
	(start_step_over): Now returns int.
	(do_target_resume): Assert the thread isn't THREAD_EXITED.
	(resume): Assert the thread isn't in the step-over chain.  Don't
	call set_running here.  If displaced stepping can't start, clear
	trap_expected.
	(find_thread_needs_step_over): Delete function.
	(proceed): Set up finish_thread_state_cleanup.  Call set_running.
	If the current thread needs a step over, push it in the step-over
	chain.  Don't set insert breakpoints nor call resume directly
	here.  Instead rewrite to use start_step_over and keep_going_pass.
	(finish_step_over): New function.
	(handle_signal_stop): Call finish_step_over instead of
	start_step_over.
	(handle_signal_stop) <random signal>: No need to clear the signal
	if calling keep_going.  Clear step-over info before inserting a
	step-resume breakpoint.
	(switch_back_to_stepped_thread): If the event thread needs another
	step-over do that first.  Use start_step_over.
	(keep_going_pass): New function, factored out from ...
	(keep_going): ... here.
	(_initialize_infrun): Comment moved here.
	* thread.c (set_running_thread): New function.
	(set_running, finish_thread_state): Use set_running_thread.

v2:

- Testing on x86_64 with software single-step revealed v1 missed
  setting prev_pc on proceed, for switch_back_to_stepped_thread.
  Rewrite tail end of proceed to fix that.  This ends up simplifying
  later patches in the series.
---
 gdb/gdbthread.h |   6 +-
 gdb/infrun.c    | 590 ++++++++++++++++++++++++++++----------------------------
 gdb/thread.c    |  52 +++--
 3 files changed, 330 insertions(+), 318 deletions(-)

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index e654432..f15cbc4 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -208,8 +208,10 @@ struct thread_info
 
   /* Internal stepping state.  */
 
-  /* Record the pc of the thread the last time it stopped.  This is
-     maintained by proceed and keep_going, and used in
+  /* Record the pc of the thread the last time it was resumed.  (It
+     can't be done on stop as the PC may change since the last stop,
+     e.g., "return" command, or "p $pc = 0xf000").  This is maintained
+     by proceed and keep_going, and among other things, it's used in
      adjust_pc_after_break to distinguish a hardware single-step
      SIGTRAP from a breakpoint SIGTRAP.  */
   CORE_ADDR prev_pc;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index fac0beb..3e64c99 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1844,112 +1844,127 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
   displaced->step_ptid = null_ptid;
 }
 
-/* Are there any pending step-over requests for INF?  */
+/* Data to be passed around while handling an event.  This data is
+   discarded between events.  */
+struct execution_control_state
+{
+  ptid_t ptid;
+  /* The thread that got the event, if this was a thread event; NULL
+     otherwise.  */
+  struct thread_info *event_thread;
+
+  struct target_waitstatus ws;
+  int stop_func_filled_in;
+  CORE_ADDR stop_func_start;
+  CORE_ADDR stop_func_end;
+  const char *stop_func_name;
+  int wait_some_more;
+
+  /* True if the event thread hit the single-step breakpoint of
+     another thread.  Thus the event doesn't cause a stop, the thread
+     needs to be single-stepped past the single-step breakpoint before
+     we can switch back to the original stepping thread.  */
+  int hit_singlestep_breakpoint;
+};
+
+/* Clear ECS and set it to point at TP.  */
 
 static void
+reset_ecs (struct execution_control_state *ecs, struct thread_info *tp)
+{
+  memset (ecs, 0, sizeof (*ecs));
+  ecs->event_thread = tp;
+  ecs->ptid = tp->ptid;
+}
+
+static void keep_going_pass (struct execution_control_state *ecs);
+static void prepare_to_wait (struct execution_control_state *ecs);
+static int thread_still_needs_step_over (struct thread_info *tp);
+
+/* Are there any pending step-over requests for INF?  If so, run one
+   now and return true.  Otherwise, return false.  */
+
+static int
 start_step_over_inferior (struct inferior *inf)
 {
   /* Don't start a new step-over if we already have a displaced step
      operation ongoing.  */
   if (displaced_step_in_progress (inf->pid))
-    return;
+    return 0;
 
   while (inf->step_over_queue_head != NULL)
     {
-      ptid_t ptid;
-      struct displaced_step_inferior_state *displaced;
-      struct regcache *regcache;
-      struct gdbarch *gdbarch;
-      CORE_ADDR actual_pc;
-      struct address_space *aspace;
       struct thread_info *tp;
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs = &ecss;
 
       tp = inf->step_over_queue_head;
-      displaced = get_displaced_stepping_state (inf->pid);
 
       step_over_chain_dequeue (&inf->step_over_queue_head);
 
-      ptid = tp->ptid;
-      context_switch (ptid);
-
-      regcache = get_thread_regcache (ptid);
-      actual_pc = regcache_read_pc (regcache);
-      aspace = get_regcache_aspace (regcache);
-
-      if (breakpoint_here_p (aspace, actual_pc))
+      if (tp->control.trap_expected || tp->executing)
 	{
-	  if (debug_displaced)
-	    fprintf_unfiltered (gdb_stdlog,
-				"displaced: stepping queued %s now\n",
-				target_pid_to_str (ptid));
+	  internal_error (__FILE__, __LINE__,
+			  "[%s] has inconsistent state: "
+			  "trap_expected=%d, executing=%d\n",
+			  target_pid_to_str (tp->ptid),
+			  tp->control.trap_expected,
+			  tp->executing);
+	}
 
-	  displaced_step_prepare (ptid);
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: resuming [%s] for step-over\n",
+			    target_pid_to_str (tp->ptid));
+
+      /* keep_going_pass skips the step-over if the breakpoint is no
+	 longer inserted.  In all-stop, we want to keep looking for a
+	 that needs a step-over instead of resuming TP, because we
+	 wouldn't be able to resume anything else until the target
+	 stops again.  In non-stop, the resume always resumes only TP,
+	 so it's OK to let the thread resume freely.  */
+      if (!non_stop && !thread_still_needs_step_over (tp))
+	continue;
 
-	  gdbarch = get_regcache_arch (regcache);
+      switch_to_thread (tp->ptid);
+      reset_ecs (ecs, tp);
+      keep_going_pass (ecs);
 
-	  if (debug_displaced)
-	    {
-	      CORE_ADDR actual_pc = regcache_read_pc (regcache);
-	      gdb_byte buf[4];
+      if (!ecs->wait_some_more)
+	error (_("Command aborted."));
 
-	      fprintf_unfiltered (gdb_stdlog, "displaced: run %s: ",
-				  paddress (gdbarch, actual_pc));
-	      read_memory (actual_pc, buf, sizeof (buf));
-	      displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
+      if (tp->control.trap_expected)
+	{
+	  if (inf->step_over_queue_head == NULL)
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: step-over queue of process %d "
+				    "now empty\n", inf->pid);
 	    }
-
-	  if (gdbarch_displaced_step_hw_singlestep (gdbarch,
-						    displaced->step_closure))
-	    target_resume (ptid, 1, GDB_SIGNAL_0);
-	  else
-	    target_resume (ptid, 0, GDB_SIGNAL_0);
-
-	  /* Done, we're stepping a thread.  */
-	  break;
+	  return 1;
 	}
       else
 	{
-	  int step;
-	  struct thread_info *tp = inferior_thread ();
-
-	  /* The breakpoint we were sitting under has since been
-	     removed.  */
-	  tp->control.trap_expected = 0;
-
-	  /* Go back to what we were trying to do.  */
-	  step = currently_stepping (tp);
-
-	  if (debug_displaced)
-	    fprintf_unfiltered (gdb_stdlog,
-				"displaced: breakpoint is gone: %s, step(%d)\n",
-				target_pid_to_str (tp->ptid), step);
-
-	  target_resume (ptid, step, GDB_SIGNAL_0);
-	  tp->suspend.stop_signal = GDB_SIGNAL_0;
-
-	  /* This request was discarded.  See if there's any other
-	     thread waiting for its turn.  */
+	  /* In all-stop, we shouldn't have resumed unless we needed a
+	     step over.  */
+	  gdb_assert (non_stop);
 	}
     }
 
-  if (inf->step_over_queue_head == NULL)
-    {
-      if (debug_infrun)
-	fprintf_unfiltered (gdb_stdlog,
-			    "infrun: step-over queue of process %d now empty\n",
-			    inf->pid);
-    }
+  return 0;
 }
 
 /* Are there any pending step-over requests for the inferior of
-   EVENT_PTID?  */
+   EVENT_PTID?  If so, run one now and return true.  Otherwise return
+   false.  */
 
-static void
+static int
 start_step_over (ptid_t event_ptid)
 {
   struct inferior *inf = find_inferior_ptid (event_ptid);
 
-  start_step_over_inferior (inf);
+  return start_step_over_inferior (inf);
 }
 
 /* Update global variables holding ptids to hold NEW_PTID if they were
@@ -2147,6 +2162,8 @@ resume (enum gdb_signal sig)
 
   tp->stepped_breakpoint = 0;
 
+  gdb_assert (tp->step_over_next == NULL);
+
   QUIT;
 
   /* Depends on stepped_breakpoint.  */
@@ -2277,16 +2294,11 @@ resume (enum gdb_signal sig)
 
       if (!displaced_step_prepare (inferior_ptid))
 	{
-	  /* Got placed in displaced stepping queue.  Will be resumed
-	     later when all the currently queued displaced stepping
-	     requests finish.  The thread is not executing at this
-	     point, and the call to set_executing will be made later.
-	     But we need to call set_running here, since from the
-	     user/frontend's point of view, threads were set running.
-	     Unless we're calling an inferior function, as in that
-	     case we pretend the inferior doesn't run at all.  */
-	  if (!tp->control.in_infcall)
-	    set_running (user_visible_resume_ptid (user_step), 1);
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"Got placed in displaced stepping queue\n");
+
+	  tp->control.trap_expected = 0;
 	  discard_cleanups (old_cleanups);
 	  return;
 	}
@@ -2361,14 +2373,6 @@ resume (enum gdb_signal sig)
      by applying increasingly restricting conditions.  */
   resume_ptid = user_visible_resume_ptid (user_step);
 
-  /* Even if RESUME_PTID is a wildcard, and we end up resuming less
-     (e.g., we might need to step over a breakpoint), from the
-     user/frontend's point of view, all threads in RESUME_PTID are now
-     running.  Unless we're calling an inferior function, as in that
-     case pretend we inferior doesn't run at all.  */
-  if (!tp->control.in_infcall)
-    set_running (resume_ptid, 1);
-
   /* Maybe resume a single thread after all.  */
   if ((step || thread_has_single_step_breakpoints_set (tp))
       && tp->control.trap_expected)
@@ -2591,48 +2595,6 @@ schedlock_applies (struct thread_info *tp)
 	      && tp->control.stepping_command));
 }
 
-/* Look a thread other than EXCEPT that has previously reported a
-   breakpoint event, and thus needs a step-over in order to make
-   progress.  Returns NULL is none is found.  */
-
-static struct thread_info *
-find_thread_needs_step_over (struct thread_info *except)
-{
-  struct thread_info *tp, *current;
-
-  /* With non-stop mode on, threads are always handled individually.  */
-  gdb_assert (! non_stop);
-
-  current = inferior_thread ();
-
-  /* If scheduler locking applies, we can avoid iterating over all
-     threads.  */
-  if (schedlock_applies (except))
-    {
-      if (except != current
-	  && thread_still_needs_step_over (current))
-	return current;
-
-      return NULL;
-    }
-
-  ALL_NON_EXITED_THREADS (tp)
-    {
-      /* Ignore the EXCEPT thread.  */
-      if (tp == except)
-	continue;
-      /* Ignore threads of processes we're not resuming.  */
-      if (!sched_multi
-	  && ptid_get_pid (tp->ptid) != ptid_get_pid (inferior_ptid))
-	continue;
-
-      if (thread_still_needs_step_over (tp))
-	return tp;
-    }
-
-  return NULL;
-}
-
 /* Basic routine for continuing the program in various fashions.
 
    ADDR is the address to resume at, or -1 for resume where stopped.
@@ -2653,6 +2615,12 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   struct thread_info *tp;
   CORE_ADDR pc;
   struct address_space *aspace;
+  ptid_t resume_ptid;
+  struct execution_control_state ecss;
+  struct execution_control_state *ecs = &ecss;
+  struct cleanup *old_chain;
+  struct thread_info *current;
+  int started;
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
      "set follow-fork-mode" command; otherwise, we'll just proceed
@@ -2674,6 +2642,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   aspace = get_regcache_aspace (regcache);
   pc = regcache_read_pc (regcache);
   tp = inferior_thread ();
+  current = tp;
 
   /* Fill in with reasonable starting values.  */
   init_thread_stepping_state (tp);
@@ -2716,7 +2685,23 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      (next/step/etc.), we'll want to print stop event output to the MI
      console channel (the stepped-to line, etc.), as if the user
      entered the execution command on a real GDB console.  */
-  inferior_thread ()->control.command_interp = command_interp ();
+  tp->control.command_interp = command_interp ();
+
+  resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+
+  /* If an exception is thrown from this point on, make sure to
+     propagate GDB's knowledge of the executing state to the
+     frontend/user running state.  */
+  old_chain = make_cleanup (finish_thread_state_cleanup, &resume_ptid);
+
+  /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
+     threads (e.g., we might need to set threads stepping over
+     breakpoints first), from the user/frontend's point of view, all
+     threads in RESUME_PTID are now running.  Unless we're calling an
+     inferior function, as in that case we pretend the inferior
+     doesn't run at all.  */
+  if (!tp->control.in_infcall)
+   set_running (resume_ptid, 1);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
@@ -2724,93 +2709,91 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 			paddress (gdbarch, addr),
 			gdb_signal_to_symbol_string (siggnal));
 
-  if (non_stop)
-    /* In non-stop, each thread is handled individually.  The context
-       must already be set to the right thread here.  */
-    ;
-  else
+  annotate_starting ();
+
+  /* Make sure that output from GDB appears before output from the
+     inferior.  */
+  gdb_flush (gdb_stdout);
+
+  /* In a multi-threaded task we may select another thread and
+     then continue or step.
+
+     But if a thread that we're resuming had stopped at a breakpoint,
+     it will immediately cause another breakpoint stop without any
+     execution (i.e. it will report a breakpoint hit incorrectly).  So
+     we must step over it first.
+
+     Look for threads other than the current (TP) that reported a
+     breakpoint hit and haven't been resumed yet since.  */
+
+  /* If scheduler locking applies, we can avoid iterating over all
+     threads.  */
+  if (!non_stop && !schedlock_applies (tp))
     {
-      struct thread_info *step_over;
+      ALL_NON_EXITED_THREADS (tp)
+        {
+	  /* Ignore the current thread here.  It's handled
+	     afterwards.  */
+	  if (tp == current)
+	    continue;
+
+	  /* Ignore threads of processes we're not resuming.  */
+	  if (!ptid_match (tp->ptid, resume_ptid))
+	    continue;
 
-      /* In a multi-threaded task we may select another thread and
-	 then continue or step.
+	  if (!thread_still_needs_step_over (tp))
+	    continue;
 
-	 But if the old thread was stopped at a breakpoint, it will
-	 immediately cause another breakpoint stop without any
-	 execution (i.e. it will report a breakpoint hit incorrectly).
-	 So we must step over it first.
+	  gdb_assert (tp->step_over_next == NULL);
+	  gdb_assert (tp->step_over_prev == NULL);
 
-	 Look for a thread other than the current (TP) that reported a
-	 breakpoint hit and hasn't been resumed yet since.  */
-      step_over = find_thread_needs_step_over (tp);
-      if (step_over != NULL)
-	{
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog,
 				"infrun: need to step-over [%s] first\n",
-				target_pid_to_str (step_over->ptid));
+				target_pid_to_str (tp->ptid));
 
-	  /* Store the prev_pc for the stepping thread too, needed by
-	     switch_back_to_stepped_thread.  */
-	  tp->prev_pc = regcache_read_pc (get_current_regcache ());
-	  switch_to_thread (step_over->ptid);
-	  tp = step_over;
+	  thread_step_over_chain_enqueue (tp);
 	}
-    }
-
-  /* If we need to step over a breakpoint, and we're not using
-     displaced stepping to do so, insert all breakpoints (watchpoints,
-     etc.) but the one we're stepping over, step one instruction, and
-     then re-insert the breakpoint when that step is finished.  */
-  if (tp->stepping_over_breakpoint
-      && !use_displaced_stepping_now_p (gdbarch,
-					tp->suspend.stop_signal))
-    {
-      struct regcache *regcache = get_current_regcache ();
 
-      set_step_over_info (get_regcache_aspace (regcache),
-			  regcache_read_pc (regcache), 0);
+      tp = current;
     }
-  else
-    clear_step_over_info ();
 
-  insert_breakpoints ();
+  /* Enqueue the current thread last, so that we move all other
+     threads over their breakpoints first.  */
+  if (tp->stepping_over_breakpoint)
+    thread_step_over_chain_enqueue (tp);
 
-  tp->control.trap_expected = tp->stepping_over_breakpoint;
+  /* If the thread isn't started, we'll still need to set its prev_pc,
+     so that switch_back_to_stepped_thread knows the thread hasn't
+     advanced.  Must do this before resuming any thread, as in
+     all-stop/remote, once we resume we can't send any other packet
+     until the target stops again.  */
+  tp->prev_pc = regcache_read_pc (regcache);
 
-  annotate_starting ();
+  started = start_step_over (tp->ptid);
 
-  /* Make sure that output from GDB appears before output from the
-     inferior.  */
-  gdb_flush (gdb_stdout);
+  if (step_over_info_valid_p ())
+    {
+      /* Either this thread started a new in-line step over, or some
+	 other thread was already doing one.  In either case, don't
+	 resume anything else until the step-over is finished.  */
+    }
+  else if (started && !non_stop)
+    {
+      /* A new displaced stepping sequence was started.  In all-stop,
+	 we can't talk to the target anymore until it next stops.  */
+    }
+  else if (!tp->executing && tp->step_over_next == NULL)
+    {
+      /* The thread wasn't started, and isn't queued, run it now.  */
+      reset_ecs (ecs, tp);
+      switch_to_thread (tp->ptid);
+      keep_going_pass (ecs);
+      if (!ecs->wait_some_more)
+	error ("Command aborted.");
+    }
 
-  /* Refresh prev_pc value just prior to resuming.  This used to be
-     done in stop_waiting, however, setting prev_pc there did not handle
-     scenarios such as inferior function calls or returning from
-     a function via the return command.  In those cases, the prev_pc
-     value was not set properly for subsequent commands.  The prev_pc value 
-     is used to initialize the starting line number in the ecs.  With an 
-     invalid value, the gdb next command ends up stopping at the position
-     represented by the next line table entry past our start position.
-     On platforms that generate one line table entry per line, this
-     is not a problem.  However, on the ia64, the compiler generates
-     extraneous line table entries that do not increase the line number.
-     When we issue the gdb next command on the ia64 after an inferior call
-     or a return command, we often end up a few instructions forward, still 
-     within the original line we started.
-
-     An attempt was made to refresh the prev_pc at the same time the
-     execution_control_state is initialized (for instance, just before
-     waiting for an inferior event).  But this approach did not work
-     because of platforms that use ptrace, where the pc register cannot
-     be read unless the inferior is stopped.  At that point, we are not
-     guaranteed the inferior is stopped and so the regcache_read_pc() call
-     can fail.  Setting the prev_pc value here ensures the value is updated
-     correctly when the inferior is stopped.  */
-  tp->prev_pc = regcache_read_pc (get_current_regcache ());
-
-  /* Resume inferior.  */
-  resume (tp->suspend.stop_signal);
+  discard_cleanups (old_chain);
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
@@ -2878,28 +2861,6 @@ init_wait_for_inferior (void)
 }
 
 \f
-/* Data to be passed around while handling an event.  This data is
-   discarded between events.  */
-struct execution_control_state
-{
-  ptid_t ptid;
-  /* The thread that got the event, if this was a thread event; NULL
-     otherwise.  */
-  struct thread_info *event_thread;
-
-  struct target_waitstatus ws;
-  int stop_func_filled_in;
-  CORE_ADDR stop_func_start;
-  CORE_ADDR stop_func_end;
-  const char *stop_func_name;
-  int wait_some_more;
-
-  /* True if the event thread hit the single-step breakpoint of
-     another thread.  Thus the event doesn't cause a stop, the thread
-     needs to be single-stepped past the single-step breakpoint before
-     we can switch back to the original stepping thread.  */
-  int hit_singlestep_breakpoint;
-};
 
 static void handle_inferior_event (struct execution_control_state *ecs);
 
@@ -2913,7 +2874,6 @@ static void check_exception_resume (struct execution_control_state *,
 
 static void end_stepping_range (struct execution_control_state *ecs);
 static void stop_waiting (struct execution_control_state *ecs);
-static void prepare_to_wait (struct execution_control_state *ecs);
 static void keep_going (struct execution_control_state *ecs);
 static void process_event_stop_test (struct execution_control_state *ecs);
 static int switch_back_to_stepped_thread (struct execution_control_state *ecs);
@@ -4280,6 +4240,34 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
     }
 }
 
+/* Called when we get an event that may finish an in-line or
+   out-of-line (displaced stepping) step-over started previously.  */
+
+static void
+finish_step_over (struct execution_control_state *ecs)
+{
+  displaced_step_fixup (ecs->ptid,
+			ecs->event_thread->suspend.stop_signal);
+
+  if (step_over_info_valid_p ())
+    {
+      /* If we're stepping over a breakpoint with all threads locked,
+	 then only the thread that was stepped should be reporting
+	 back an event.  */
+      gdb_assert (ecs->event_thread->control.trap_expected);
+
+      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+	clear_step_over_info ();
+    }
+
+  if (!non_stop)
+    return;
+
+  /* Start a new step-over in another thread if there's one that
+     needs it.  */
+  start_step_over (ecs->ptid);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -4296,9 +4284,7 @@ handle_signal_stop (struct execution_control_state *ecs)
   /* Do we need to clean up the state of a thread that has
      completed a displaced single-step?  (Doing so usually affects
      the PC, so do it here, before we set stop_pc.)  */
-  displaced_step_fixup (ecs->ptid,
-			ecs->event_thread->suspend.stop_signal);
-  start_step_over (ecs->ptid);
+  finish_step_over (ecs);
 
   /* If we either finished a single-step or hit a breakpoint, but
      the user wanted this thread to be stopped, pretend we got a
@@ -5647,7 +5633,6 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
     {
       struct thread_info *tp;
       struct thread_info *stepping_thread;
-      struct thread_info *step_over;
 
       /* If any thread is blocked on some internal breakpoint, and we
 	 simply need to step over that breakpoint to get it going
@@ -5690,14 +5675,20 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 	 return 1;
        }
 
-      /* Otherwise, we no longer expect a trap in the current thread.
-	 Clear the trap_expected flag before switching back -- this is
-	 what keep_going does as well, if we call it.  */
-      ecs->event_thread->control.trap_expected = 0;
-
-      /* Likewise, clear the signal if it should not be passed.  */
-      if (!signal_program[ecs->event_thread->suspend.stop_signal])
-	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+      /* If this thread needs yet another step-over (e.g., stepping
+	 through a delay slot), do it first before moving on to
+	 another thread.  */
+      if (thread_still_needs_step_over (ecs->event_thread))
+	{
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: thread [%s] still needs step-over\n",
+				  target_pid_to_str (ecs->event_thread->ptid));
+	    }
+	  keep_going (ecs);
+	  return 1;
+	}
 
       /* If scheduler locking applies even if not stepping, there's no
 	 need to walk over threads.  Above we've checked whether the
@@ -5707,12 +5698,26 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
       if (schedlock_applies (ecs->event_thread))
 	return 0;
 
-      /* Look for the stepping/nexting thread, and check if any other
-	 thread other than the stepping thread needs to start a
-	 step-over.  Do all step-overs before actually proceeding with
+      /* Otherwise, we no longer expect a trap in the current thread.
+	 Clear the trap_expected flag before switching back -- this is
+	 what keep_going does as well, if we call it.  */
+      ecs->event_thread->control.trap_expected = 0;
+
+      /* Likewise, clear the signal if it should not be passed.  */
+      if (!signal_program[ecs->event_thread->suspend.stop_signal])
+	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+
+      /* Do all pending step-overs before actually proceeding with
 	 step/next/etc.  */
+      if (start_step_over (ecs->ptid))
+	{
+	  prepare_to_wait (ecs);
+	  return 1;
+	}
+
+      /* Look for the stepping/nexting thread.  */
       stepping_thread = NULL;
-      step_over = NULL;
+
       ALL_NON_EXITED_THREADS (tp)
         {
 	  /* Ignore threads of processes we're not resuming.  */
@@ -5744,37 +5749,6 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
 	      stepping_thread = tp;
 	    }
-	  else if (thread_still_needs_step_over (tp))
-	    {
-	      step_over = tp;
-
-	      /* At the top we've returned early if the event thread
-		 is stepping.  If some other thread not the event
-		 thread is stepping, then scheduler locking can't be
-		 in effect, and we can resume this thread.  No need to
-		 keep looking for the stepping thread then.  */
-	      break;
-	    }
-	}
-
-      if (step_over != NULL)
-	{
-	  tp = step_over;
-	  if (debug_infrun)
-	    {
-	      fprintf_unfiltered (gdb_stdlog,
-				  "infrun: need to step-over [%s]\n",
-				  target_pid_to_str (tp->ptid));
-	    }
-
-	  /* Only the stepping thread should have this set.  */
-	  gdb_assert (tp->control.step_range_end == 0);
-
-	  ecs->ptid = tp->ptid;
-	  ecs->event_thread = tp;
-	  switch_to_thread (ecs->ptid);
-	  keep_going (ecs);
-	  return 1;
 	}
 
       if (stepping_thread != NULL)
@@ -5873,7 +5847,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 		fprintf_unfiltered (gdb_stdlog,
 				    "infrun: expected thread still "
 				    "hasn't advanced\n");
-	      keep_going (ecs);
+	      keep_going_pass (ecs);
 	    }
 
 	  return 1;
@@ -6288,24 +6262,32 @@ stop_waiting (struct execution_control_state *ecs)
   ecs->wait_some_more = 0;
 }
 
-/* Called when we should continue running the inferior, because the
-   current event doesn't cause a user visible stop.  This does the
-   resuming part; waiting for the next event is done elsewhere.  */
+/* Like keep_going, but passes the signal to the inferior, even if the
+   signal is set to nopass.  */
 
 static void
-keep_going (struct execution_control_state *ecs)
+keep_going_pass (struct execution_control_state *ecs)
 {
   /* Make sure normal_stop is called if we get a QUIT handled before
      reaching resume.  */
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
 
+  gdb_assert (ptid_equal (ecs->event_thread->ptid, inferior_ptid));
+
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
     = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
-  if (ecs->event_thread->control.trap_expected
-      && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP)
+  if (ecs->event_thread->control.trap_expected)
     {
+      struct thread_info *tp = ecs->event_thread;
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: %s has trap_expected set, "
+			    "resuming to collect trap\n",
+			    target_pid_to_str (tp->ptid));
+
       /* We haven't yet gotten our trap, and either: intercepted a
 	 non-signal event (e.g., a fork); or took a signal which we
 	 are supposed to pass through to the inferior.  Simply
@@ -6318,7 +6300,7 @@ keep_going (struct execution_control_state *ecs)
       struct regcache *regcache = get_current_regcache ();
       int remove_bp;
       int remove_wps;
-      enum gdb_signal signo;
+      enum gdb_signal signo = ecs->event_thread->suspend.stop_signal;
       enum step_over_what step_what;
 
       /* Either the trap was not expected, but we are continuing
@@ -6340,22 +6322,6 @@ keep_going (struct execution_control_state *ecs)
 	 instruction, and then re-insert the breakpoint when that step
 	 is finished.  */
 
-      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
-	 explicitly specifies that such a signal should be delivered
-	 to the target program).  Typically, that would occur when a
-	 user is debugging a target monitor on a simulator: the target
-	 monitor sets a breakpoint; the simulator encounters this
-	 breakpoint and halts the simulation handing control to GDB;
-	 GDB, noting that the stop address doesn't map to any known
-	 breakpoint, returns control back to the simulator; the
-	 simulator then delivers the hardware equivalent of a
-	 GDB_SIGNAL_TRAP to the program being debugged.	 */
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-	  && !signal_program[ecs->event_thread->suspend.stop_signal])
-	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-
-      signo = ecs->event_thread->suspend.stop_signal;
-
       step_what = thread_still_needs_step_over (ecs->event_thread);
 
       remove_bp = (ecs->hit_singlestep_breakpoint
@@ -6400,6 +6366,22 @@ keep_going (struct execution_control_state *ecs)
   prepare_to_wait (ecs);
 }
 
+/* Called when we should continue running the inferior, because the
+   current event doesn't cause a user visible stop.  This does the
+   resuming part; waiting for the next event is done elsewhere.  */
+
+static void
+keep_going (struct execution_control_state *ecs)
+{
+  if (ecs->event_thread->control.trap_expected
+      && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+    ecs->event_thread->control.trap_expected = 0;
+
+  if (!signal_program[ecs->event_thread->suspend.stop_signal])
+    ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+  keep_going_pass (ecs);
+}
+
 /* This function normally comes after a resume, before
    handle_inferior_event exits.  It takes care of any last bits of
    housekeeping, and sets the all-important wait_some_more flag.  */
@@ -7916,9 +7898,21 @@ leave it stopped or free to run as needed."),
       signal_catch[i] = 0;
     }
 
-  /* Signals caused by debugger's own actions
-     should not be given to the program afterwards.  */
+  /* Signals caused by debugger's own actions should not be given to
+     the program afterwards.
+
+     Do not deliver GDB_SIGNAL_TRAP by default, except when the user
+     explicitly specifies that it should be delivered to the target
+     program.  Typically, that would occur when a user is debugging a
+     target monitor on a simulator: the target monitor sets a
+     breakpoint; the simulator encounters this breakpoint and halts
+     the simulation handing control to GDB; GDB, noting that the stop
+     address doesn't map to any known breakpoint, returns control back
+     to the simulator; the simulator then delivers the hardware
+     equivalent of a GDB_SIGNAL_TRAP to the program being
+     debugged.  */
   signal_program[GDB_SIGNAL_TRAP] = 0;
+
   signal_program[GDB_SIGNAL_INT] = 0;
 
   /* Signals that are not errors should not normally enter the debugger.  */
diff --git a/gdb/thread.c b/gdb/thread.c
index d5c9896..a01f5d8 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -848,44 +848,62 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
   observer_notify_thread_ptid_changed (old_ptid, new_ptid);
 }
 
+/* Helper for set_running, that marks one thread either running or
+   stopped.  */
+
+static int
+set_running_thread (struct thread_info *tp, int running)
+{
+  int started = 0;
+
+  if (running && tp->state == THREAD_STOPPED)
+    started = 1;
+  tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
+
+  if (!running)
+    {
+      /* If the thread is now marked stopped, remove it from
+	 the step-over queue, so that we don't try to resume
+	 it until the user wants it to.  */
+      if (tp->step_over_next != NULL)
+	thread_step_over_chain_remove (tp);
+    }
+
+  return started;
+}
+
 void
 set_running (ptid_t ptid, int running)
 {
   struct thread_info *tp;
   int all = ptid_equal (ptid, minus_one_ptid);
+  int any_started = 0;
 
   /* We try not to notify the observer if no thread has actually changed 
      the running state -- merely to reduce the number of messages to 
      frontend.  Frontend is supposed to handle multiple *running just fine.  */
   if (all || ptid_is_pid (ptid))
     {
-      int any_started = 0;
-
       for (tp = thread_list; tp; tp = tp->next)
 	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
 	  {
 	    if (tp->state == THREAD_EXITED)
 	      continue;
-	    if (running && tp->state == THREAD_STOPPED)
+
+	    if (set_running_thread (tp, running))
 	      any_started = 1;
-	    tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
 	  }
-      if (any_started)
-	observer_notify_target_resumed (ptid);
     }
   else
     {
-      int started = 0;
-
       tp = find_thread_ptid (ptid);
-      gdb_assert (tp);
+      gdb_assert (tp != NULL);
       gdb_assert (tp->state != THREAD_EXITED);
-      if (running && tp->state == THREAD_STOPPED)
- 	started = 1;
-      tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
-      if (started)
-  	observer_notify_target_resumed (ptid);
+      if (set_running_thread (tp, running))
+	any_started = 1;
     }
+  if (any_started)
+    observer_notify_target_resumed (ptid);
 }
 
 static int
@@ -1004,9 +1022,8 @@ finish_thread_state (ptid_t ptid)
   	    continue;
 	  if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid))
 	    {
-	      if (tp->executing && tp->state == THREAD_STOPPED)
+	      if (set_running_thread (tp, tp->executing))
 		any_started = 1;
-	      tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED;
 	    }
 	}
     }
@@ -1016,9 +1033,8 @@ finish_thread_state (ptid_t ptid)
       gdb_assert (tp);
       if (tp->state != THREAD_EXITED)
 	{
-	  if (tp->executing && tp->state == THREAD_STOPPED)
+	  if (set_running_thread (tp, tp->executing))
 	    any_started = 1;
-	  tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED;
 	}
     }
 
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 16/23] Fix signal-while-stepping-over-bp-other-thread.exp on targets always in non-stop
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 02/23] Fix and test "checkpoint" in non-stop mode Pedro Alves
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

With "maint set target-non-stop on" we get:

 -PASS: gdb.threads/signal-while-stepping-over-bp-other-thread.exp: step
 +FAIL: gdb.threads/signal-while-stepping-over-bp-other-thread.exp: step

The issue is simply that switch_back_to_stepped_thread is not used in
non-stop mode, thus infrun doesn't output the expected "signal arrived
while stepping over breakpoint" log.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* signal-while-stepping-over-bp-other-thread.exp: Use
	gdb_test_sequence.  Expect "restart threads" as alternative to
	"switching back to stepped thread".
---
 .../signal-while-stepping-over-bp-other-thread.exp   | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/signal-while-stepping-over-bp-other-thread.exp b/gdb/testsuite/gdb.threads/signal-while-stepping-over-bp-other-thread.exp
index bb00c50..1d5eabd 100644
--- a/gdb/testsuite/gdb.threads/signal-while-stepping-over-bp-other-thread.exp
+++ b/gdb/testsuite/gdb.threads/signal-while-stepping-over-bp-other-thread.exp
@@ -95,19 +95,19 @@ gdb_test "set scheduler-locking off"
 # Make sure we're exercising the paths we want to.
 gdb_test "set debug infrun 1"
 
-gdb_test \
-    "step" \
-    ".*need to step-over.*resume \\(step=1.*signal arrived while stepping over breakpoint.*switching back to stepped thread.*stepped to a different line.*callme.*" \
-    "step"
+set test "step"
+gdb_test_sequence $test $test {
+    "need to step-over \[^\r\n\]* first"
+    "resume \\(step=1"
+    "Program received signal SIGUSR1"
+    "(restart threads|signal arrived while stepping over breakpoint)"
+    "stepped to a different line"
+    "callme \\(\\);"
+}
 
 set cnt_after [get_value "args\[$my_number\]" "get count after step"]
 
 # Test that GDB doesn't inadvertently resume the stepped thread when a
 # signal arrives while stepping over a breakpoint in another thread.
 
-set test "stepped thread under control"
-if { $cnt_before + 1 == $cnt_after } {
-    pass $test
-} else {
-    fail $test
-}
+gdb_assert { $cnt_before + 1 == $cnt_after } "stepped thread under control"
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 02/23] Fix and test "checkpoint" in non-stop mode
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 16/23] Fix signal-while-stepping-over-bp-other-thread.exp on targets always in non-stop Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 12/23] Misc switch_back_to_stepped_thread cleanups Pedro Alves
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Letting a "checkpoint" run to exit with "set non-stop on" behaves
differently compared to the default all-stop mode ("set non-stop
off").

Currently, in non-stop mode:

  (gdb) start
  Temporary breakpoint 1 at 0x40086b: file src/gdb/testsuite/gdb.base/checkpoint.c, line 28.
  Starting program: build/gdb/testsuite/gdb.base/checkpoint

  Temporary breakpoint 1, main () at src/gdb/testsuite/gdb.base/checkpoint.c:28
  28        char *tmp = &linebuf[0];
  (gdb) checkpoint
  checkpoint 1: fork returned pid 24948.
  (gdb) c
  Continuing.
  Copy complete.
  Deleting copy.
  [Inferior 1 (process 24944) exited normally]
  [Switching to process 24948]
  (gdb) info threads
    Id   Target Id         Frame
    1    process 24948 "checkpoint" (running)

  No selected thread.  See `help thread'.
  (gdb) c
  The program is not being run.
  (gdb)

Two issues above:

 1. Thread 1 got stuck in "(running)" state (it isn't really running)

 2. While checkpoints try to preserve the illusion that the thread is
    still the same when the process exits, GDB switched to "No thread
    selected." instead of staying with thread 1 selected.

Problem #1 is caused by handle_inferior_event and normal_stop not
considering that when a
TARGET_WAITKIND_SIGNALLED/TARGET_WAITKIND_EXITED event is reported,
and the inferior is mourned, the target may still have execution.

Problem #2 is caused by the make_cleanup_restore_current_thread
cleanup installed by fetch_inferior_event not being able to find the
original thread 1's ptid in the thread list, thus not being able to
restore thread 1 as selected thread.  The fix is to make the cleanup
installed by make_cleanup_restore_current_thread aware of thread ptid
changes, by installing a thread_ptid_changed observer that adjusts the
cleanup's data.

After the patch, we get the same in all-stop and non-stop modes:

  (gdb) c
  Continuing.
  Copy complete.
  Deleting copy.
  [Inferior 1 (process 25109) exited normally]
  [Switching to process 25113]
  (gdb) info threads
    Id   Target Id         Frame
  * 1    process 25113 "checkpoint" main () at src/gdb/testsuite/gdb.base/checkpoint.c:28
  (gdb)

Turns out the whole checkpoints.exp file can run in non-stop mode
unmodified.  I thought of moving most of the test file's contents to a
procedure that can be called twice, once in non-stop mode and another
in all-stop mode.  But then, the test already takes over 30 seconds to
run on my machine, so I thought it'd be nicer to run all-stop and
non-stop mode in parallel.  Thus I added a new checkpoint-ns.exp file
that just sources checkpoint.exp, and sets a knob that checkpoint.exp
reads to know it should test non-stop mode.  No other test in the tree
currently uses this mechanism, but I can't see a reason we shouldn't
do this.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (handle_inferior_event): If we get
	TARGET_WAITKIND_SIGNALLED or TARGET_WAITKIND_EXITED in non-stop
	mode, mark all threads of the exiting process as not-executing.
	(normal_stop): If we get TARGET_WAITKIND_SIGNALLED or
	TARGET_WAITKIND_EXITED in non-stop mode, finish all threads of the
	exiting process, if inferior_ptid still points at a process.
	* thread.c (struct current_thread_cleanup) <next>: New field.
	(current_thread_cleanup_chain): New global.
	(restore_current_thread_ptid_changed): New function.
	(restore_current_thread_cleanup_dtor): Remove the cleanup from the
	current_thread_cleanup_chain list.
	(make_cleanup_restore_current_thread): Add the cleanup data to the
	current_thread_cleanup_chain list.
	(_initialize_thread): Install restore_current_thread_ptid_changed
	as thread_ptid_changed observer.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.base/checkpoint-ns.exp: New file.
	* gdb.base/checkpoint.exp (checkpoint_non_stop): New input
	variable.  If set, test in non-stop mode.  Pass explicit
	"checkpoint.c" to standard_testfile.
---
 gdb/infrun.c                             | 31 +++++++++++++++++++++-----
 gdb/testsuite/gdb.base/checkpoint-ns.exp | 27 +++++++++++++++++++++++
 gdb/testsuite/gdb.base/checkpoint.exp    | 31 +++++++++++++++++++++-----
 gdb/thread.c                             | 38 ++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+), 10 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/checkpoint-ns.exp

diff --git a/gdb/infrun.c b/gdb/infrun.c
index a270ca9..466bc4a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3796,8 +3796,18 @@ handle_inferior_event (struct execution_control_state *ecs)
      any other process were left running.  */
   if (!non_stop)
     set_executing (minus_one_ptid, 0);
-  else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
-	   && ecs->ws.kind != TARGET_WAITKIND_EXITED)
+  else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
+	   && ecs->ws.kind == TARGET_WAITKIND_EXITED)
+    {
+      ptid_t pid_ptid;
+
+      /* Some targets still have execution when a process exits.
+	 E.g., for "checkpoint", when when a fork exits and is
+	 mourned, linux-fork.c switches to another fork.  */
+      pid_ptid = pid_to_ptid (ptid_get_pid (ecs->ptid));
+      set_executing (pid_ptid, 0);
+    }
+  else
     set_executing (ecs->ptid, 0);
 
   switch (ecs->ws.kind)
@@ -6536,6 +6546,7 @@ normal_stop (void)
   struct target_waitstatus last;
   ptid_t last_ptid;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+  ptid_t pid_ptid;
 
   get_last_target_status (&last_ptid, &last);
 
@@ -6545,9 +6556,19 @@ normal_stop (void)
      here, so do this before any filtered output.  */
   if (!non_stop)
     make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
-  else if (last.kind != TARGET_WAITKIND_SIGNALLED
-	   && last.kind != TARGET_WAITKIND_EXITED
-	   && last.kind != TARGET_WAITKIND_NO_RESUMED)
+  else if (last.kind == TARGET_WAITKIND_SIGNALLED
+	   || last.kind == TARGET_WAITKIND_EXITED)
+    {
+      /* Some targets still have execution when a process exits.
+	 E.g., for "checkpoint", when when a fork exits and is
+	 mourned, linux-fork.c switches to another fork.  */
+      if (!ptid_equal (inferior_ptid, null_ptid))
+	{
+	  pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+	  make_cleanup (finish_thread_state_cleanup, &pid_ptid);
+	}
+    }
+  else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
     make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
 
   /* As we're presenting a stop, and potentially removing breakpoints,
diff --git a/gdb/testsuite/gdb.base/checkpoint-ns.exp b/gdb/testsuite/gdb.base/checkpoint-ns.exp
new file mode 100644
index 0000000..03a1747
--- /dev/null
+++ b/gdb/testsuite/gdb.base/checkpoint-ns.exp
@@ -0,0 +1,27 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# Test gdb checkpoint and restart in non-stop mode.
+
+# We drive non-stop mode from a separate file because the whole test
+# takes a while to run.  This way, we can test both modes in parallel.
+
+# checkpoint.exp reads this variable.
+set checkpoint_non_stop 1
+
+source $srcdir/$subdir/checkpoint.exp
+
+# Unset to avoid problems with non-parallel mode.
+unset checkpoint_non_stop
diff --git a/gdb/testsuite/gdb.base/checkpoint.exp b/gdb/testsuite/gdb.base/checkpoint.exp
index 6d94ab6..c297b50 100644
--- a/gdb/testsuite/gdb.base/checkpoint.exp
+++ b/gdb/testsuite/gdb.base/checkpoint.exp
@@ -13,6 +13,20 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#
+# This tests gdb checkpoint and restart.
+#
+
+# Note this file is also sourced by checkpoint-ns.exp to run all the
+# tests below in non-stop mode.  That's driven by a separate file so
+# testing both all-stop and non-stop can be done in parallel.
+
+# This is the variable checkpoint-ns.exp sets to request non-stop
+# mode.  When not set, default to all-stop mode.
+if {![info exists checkpoint_non_stop]} {
+    set checkpoint_non_stop 0
+}
+
 if { [is_remote target] || ![isnative] } then {
     continue
 }
@@ -24,8 +38,10 @@ if {![istarget "*-*-linux*"]} then {
     continue
 }
 
-
-standard_testfile .c
+# Must name the source file explicitly, otherwise when driven by
+# checkpoints-ns.exp, we'd try compiling checkpoints-ns.c, which
+# doesn't exist.
+standard_testfile checkpoint.c
 
 set pi_txt [gdb_remote_download host ${srcdir}/${subdir}/pi.txt]
 if {[is_remote host]} {
@@ -42,9 +58,9 @@ if {[prepare_for_testing ${testfile}.exp $testfile $srcfile \
 
 global gdb_prompt
 
-#
-# This tests gdb checkpoint and restart.
-#
+if {$checkpoint_non_stop} {
+    gdb_test_no_output "set non-stop on"
+}
 
 runto_main
 set break1_loc [gdb_get_line_number "breakpoint 1"]
@@ -327,6 +343,11 @@ gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
 
+if {$checkpoint_non_stop} {
+    gdb_test_no_output "set non-stop on" \
+	"set non-stop on, for many checkpoints"
+}
+
 runto_main
 gdb_breakpoint $break1_loc
 
diff --git a/gdb/thread.c b/gdb/thread.c
index ec398f5..db631c9 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1266,8 +1266,16 @@ restore_selected_frame (struct frame_id a_frame_id, int frame_level)
     }
 }
 
+/* Data used by the cleanup installed by
+   'make_cleanup_restore_current_thread'.  */
+
 struct current_thread_cleanup
 {
+  /* Next in list of currently installed 'struct
+     current_thread_cleanup' cleanups.  See
+     'current_thread_cleanup_chain' below.  */
+  struct current_thread_cleanup *next;
+
   ptid_t inferior_ptid;
   struct frame_id selected_frame_id;
   int selected_frame_level;
@@ -1276,6 +1284,29 @@ struct current_thread_cleanup
   int was_removable;
 };
 
+/* A chain of currently installed 'struct current_thread_cleanup'
+   cleanups.  Restoring the previously selected thread looks up the
+   old thread in the thread list by ptid.  If the thread changes ptid,
+   we need to update the cleanup's thread structure so the look up
+   succeeds.  */
+static struct current_thread_cleanup *current_thread_cleanup_chain;
+
+/* A thread_ptid_changed observer.  Update all currently installed
+   current_thread_cleanup cleanups that want to switch back to
+   OLD_PTID to switch back to NEW_PTID instead.  */
+
+static void
+restore_current_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
+{
+  struct current_thread_cleanup *it;
+
+  for (it = current_thread_cleanup_chain; it != NULL; it = it->next)
+    {
+      if (ptid_equal (it->inferior_ptid, old_ptid))
+	it->inferior_ptid = new_ptid;
+    }
+}
+
 static void
 do_restore_current_thread_cleanup (void *arg)
 {
@@ -1316,6 +1347,8 @@ restore_current_thread_cleanup_dtor (void *arg)
   struct thread_info *tp;
   struct inferior *inf;
 
+  current_thread_cleanup_chain = current_thread_cleanup_chain->next;
+
   tp = find_thread_ptid (old->inferior_ptid);
   if (tp)
     tp->refcount--;
@@ -1349,6 +1382,9 @@ make_cleanup_restore_current_thread (void)
   old->inf_id = current_inferior ()->num;
   old->was_removable = current_inferior ()->removable;
 
+  old->next = current_thread_cleanup_chain;
+  current_thread_cleanup_chain = old;
+
   if (!ptid_equal (inferior_ptid, null_ptid))
     {
       old->was_stopped = is_stopped (inferior_ptid);
@@ -1803,4 +1839,6 @@ Show printing of thread events (such as thread start and exit)."), NULL,
          &setprintlist, &showprintlist);
 
   create_internalvar_type_lazy ("_thread", &thread_funcs, NULL);
+
+  observer_attach_thread_ptid_changed (restore_current_thread_ptid_changed);
 }
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 19/23] Disable displaced stepping if trying it fails
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (12 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 23/23] native Linux: enable always non-stop by default Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets Pedro Alves
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Running the testsuite with "maint set target-non-stop on" shows:

 (gdb) PASS: gdb.base/valgrind-infcall.exp: continue #98 (false warning)
 continue
 Continuing.
 dl_main (phdr=<optimized out>..., auxv=<optimized out>) at rtld.c:2302
 2302      LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
 Cannot access memory at address 0x400532
 (gdb) PASS: gdb.base/valgrind-infcall.exp: continue #99 (false warning)
 p gdb_test_infcall ()
 $1 = 1
 (gdb) FAIL: gdb.base/valgrind-infcall.exp: p gdb_test_infcall ()

Even though that was a native GNU/Linux test run, this test spawns
Valgrind and connects to it with "target remote".  The error above is
actually orthogonal to target-non-stop.  The real issue is that that
enables displaced stepping, and displaced stepping doesn't work with
Valgrind, because we can't write to the inferior memory (thus can't
copy the instruction to the scratch pad area).

I'm sure there will be other targets with the same issue, so trying to
identify Valgrind wouldn't be sufficient.  The fix is to try setting
up the displaced step anyway.  If we get a MEMORY_ERROR, we disable
displaced stepping for that inferior, and fall back to doing an
in-line step-over.  If "set displaced-stepping" is "on" (as opposed to
"auto), GDB warns displaced stepping failed ("on" is mainly useful for
the testsuite, not for users).

Tested on x86_64 Fedora 20.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* inferior.h (struct inferior) <displaced_stepping_failed>: New
	field.
	* infrun.c (use_displaced_stepping_now_p): New parameter 'inf'.
	Return false if dispaced stepping failed before.
	(resume): Pass the current inferior to
	use_displaced_stepping_now_p.  Wrap displaced_step_prepare in
	TRY/CATCH.  If we get a MEMORY_ERROR, set the inferior's
	displaced_stepping_failed flag, and fall back to an in-line
	step-over.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.base/valgrind-disp-step.c: New file.
	* gdb.base/valgrind-disp-step.exp: New file.

In v2:

   - warn if displaced stepping fails, and "set displaced-stepping" is
     "on" (but not "auto").
---
 gdb/inferior.h                                |   4 +
 gdb/infrun.c                                  |  76 ++++++++++++---
 gdb/testsuite/gdb.base/valgrind-disp-step.c   |  32 +++++++
 gdb/testsuite/gdb.base/valgrind-disp-step.exp | 131 ++++++++++++++++++++++++++
 4 files changed, 230 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/valgrind-disp-step.c
 create mode 100644 gdb/testsuite/gdb.base/valgrind-disp-step.exp

diff --git a/gdb/inferior.h b/gdb/inferior.h
index 3cec101..d831c90 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -414,6 +414,10 @@ struct inferior
      operation to get past e.g., a breakpoint.  */
   struct thread_info *step_over_queue_head;
 
+  /* True if preparing a displaced step ever failed.  If so, we won't
+     try displaced stepping for this inferior again.  */
+  int displaced_stepping_failed;
+
   /* Per inferior data-pointers required by other GDB modules.  */
   REGISTRY_FIELDS;
 };
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8da97fc..2f288a0 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1617,7 +1617,7 @@ can_use_displaced_stepping_p (struct gdbarch *gdbarch)
    over a breakpoint in the current thread.  */
 
 static int
-use_displaced_stepping_now_p (struct gdbarch *gdbarch,
+use_displaced_stepping_now_p (struct inferior *inf, struct gdbarch *gdbarch,
 			      enum gdb_signal sig)
 {
   CORE_ADDR retval;
@@ -1626,7 +1626,8 @@ use_displaced_stepping_now_p (struct gdbarch *gdbarch,
      the comments for displaced_step_prepare explain why.  The
      comments in the handle_inferior event for dealing with 'random
      signals' explain what we do instead.  */
-  return  (sig == GDB_SIGNAL_0
+  return  (!inf->displaced_stepping_failed
+	   && sig == GDB_SIGNAL_0
 	   && can_use_displaced_stepping_p (gdbarch)
 	   && entry_point_address_query (&retval));
 }
@@ -1926,6 +1927,7 @@ static void keep_going_pass (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
 static int keep_going_stepped_thread (struct thread_info *tp);
 static int thread_still_needs_step_over (struct thread_info *tp);
+static void stop_all_threads (void);
 
 /* Are there any pending step-over requests for INF?  If so, run one
    now and return true.  Otherwise, return false.  */
@@ -2373,11 +2375,40 @@ resume (enum gdb_signal sig)
      instruction at a different address.  */
   if (tp->control.trap_expected
       && !step_over_info_valid_p ()
-      && use_displaced_stepping_now_p (gdbarch, sig))
+      && use_displaced_stepping_now_p (current_inferior (), gdbarch, sig))
     {
-      struct displaced_step_inferior_state *displaced;
+      int prepared = -1;
 
-      if (!displaced_step_prepare (inferior_ptid))
+      TRY
+	{
+	  prepared = displaced_step_prepare (inferior_ptid);
+	}
+      CATCH (ex, RETURN_MASK_ERROR)
+	{
+	  if (ex.error != MEMORY_ERROR)
+	    throw_exception (ex);
+
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: disabling displaced stepping: %s\n",
+				  ex.message);
+	    }
+
+	  /* Be verbose if "set displaced-stepping" is "on", silent if
+	     "auto".  */
+	  if (can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
+	    {
+	      warning (_("disabling displaced stepping: %s\n"),
+		       ex.message);
+	    }
+
+	  /* Disable further displaced stepping attempts.  */
+	  current_inferior ()->displaced_stepping_failed = 1;
+	}
+      END_CATCH
+
+      if (prepared == 0)
 	{
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog,
@@ -2388,14 +2419,32 @@ resume (enum gdb_signal sig)
 	  discard_cleanups (old_cleanups);
 	  return;
 	}
+      else if (prepared < 0)
+	{
+	  /* Fallback to stepping over the breakpoint in-line.  */
 
-      /* Update pc to reflect the new address from which we will execute
-	 instructions due to displaced stepping.  */
-      pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+	  if (target_is_non_stop_p ())
+	    stop_all_threads ();
 
-      displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
-      step = gdbarch_displaced_step_hw_singlestep (gdbarch,
-						   displaced->step_closure);
+	  set_step_over_info (get_regcache_aspace (regcache),
+			      regcache_read_pc (regcache), 0);
+
+	  step = maybe_software_singlestep (gdbarch, pc);
+
+	  insert_breakpoints ();
+	}
+      else if (prepared > 0)
+	{
+	  struct displaced_step_inferior_state *displaced;
+
+	  /* Update pc to reflect the new address from which we will
+	     execute instructions due to displaced stepping.  */
+	  pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+
+	  displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+	  step = gdbarch_displaced_step_hw_singlestep (gdbarch,
+						       displaced->step_closure);
+	}
     }
 
   /* Do we need to do it the hard way, w/temp breakpoints?  */
@@ -2525,7 +2574,7 @@ resume (enum gdb_signal sig)
   if (debug_displaced
       && tp->control.trap_expected
       && !step_over_info_valid_p ()
-      && use_displaced_stepping_now_p (gdbarch, sig))
+      && use_displaced_stepping_now_p (current_inferior (), gdbarch, sig))
     {
       struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
       struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
@@ -7179,7 +7228,8 @@ keep_going_pass (struct execution_control_state *ecs)
       else if (remove_wps)
 	set_step_over_info (NULL, 0, remove_wps);
       else if (remove_bp
-	       && !use_displaced_stepping_now_p (get_regcache_arch (regcache),
+	       && !use_displaced_stepping_now_p (current_inferior (),
+						 get_regcache_arch (regcache),
 						 signo))
 	{
 	  set_step_over_info (get_regcache_aspace (regcache),
diff --git a/gdb/testsuite/gdb.base/valgrind-disp-step.c b/gdb/testsuite/gdb.base/valgrind-disp-step.c
new file mode 100644
index 0000000..baba74e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/valgrind-disp-step.c
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+static int
+foo (void)
+{
+}
+
+int
+main (void)
+{
+  foo (); /* stop 0 */
+  foo (); /* stop 1 */
+  foo (); /* stop 2 */
+  foo (); /* stop 3 */
+  foo (); /* stop 4 */
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/valgrind-disp-step.exp b/gdb/testsuite/gdb.base/valgrind-disp-step.exp
new file mode 100644
index 0000000..ded1ff7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/valgrind-disp-step.exp
@@ -0,0 +1,131 @@
+# Copyright 2012-2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Step over breakpoints with displaced stepping off/on.  We can't
+# really use displaced stepping with Valgrind, so what this really
+# tests is that GDB falls back to in-line stepping automatically
+# instead of getting stuck or crashing.
+
+if [is_remote target] {
+    # The test always runs locally.
+    return 0
+}
+
+standard_testfile .c
+if {[build_executable "failed to build" $testfile $srcfile {debug}] == -1} {
+    return -1
+}
+
+set test "spawn valgrind"
+set cmd "valgrind --vgdb-error=0 $binfile"
+set res [remote_spawn host $cmd]
+if { $res < 0 || $res == "" } {
+    verbose -log "Spawning $cmd failed."
+    unsupported $test
+    return -1
+}
+pass $test
+# Declare GDB now as running.
+set gdb_spawn_id $res
+
+# GDB started by vgdb stops already after the startup is executed, like with
+# non-extended gdbserver.  It is also not correct to run/attach the inferior.
+set use_gdb_stub 1
+
+set test "valgrind started"
+# The trailing '.' differs for different memcheck versions.
+gdb_test_multiple "" $test {
+    -re "Memcheck, a memory error detector\\.?\r\n" {
+	pass $test
+    }
+    -re "valgrind: failed to start tool 'memcheck' for platform '.*': No such file or directory" {
+	unsupported $test
+	return -1
+    }
+    -re "valgrind: wrong ELF executable class" {
+	unsupported $test
+	return -1
+    }
+    -re "command not found" {
+	# The spawn succeeded, but then valgrind was not found - e.g. if
+	# we spawned SSH to a remote system.
+	unsupported $test
+	return -1
+    }
+    -re "valgrind: Bad option.*--vgdb-error=0" {
+	# valgrind is not >= 3.7.0.
+	unsupported $test
+	return -1
+    }
+}
+
+set test "vgdb prompt"
+# The trailing '.' differs for different memcheck versions.
+gdb_test_multiple "" $test {
+    -re "  (target remote | \[^\r\n\]*/vgdb \[^\r\n\]*)\r\n" {
+	set vgdbcmd $expect_out(1,string)
+	pass $test
+    }
+}
+
+# Do not kill valgrind.
+set valgrind_pid [exp_pid -i [board_info host fileid]]
+unset gdb_spawn_id
+set board [host_info name]
+unset_board_info fileid
+
+clean_restart $testfile
+
+gdb_test "$vgdbcmd" " in \\.?_start .*" "target remote for vgdb"
+
+gdb_test "monitor v.set gdb_output" "valgrind output will go to gdb.*"
+
+gdb_test_no_output "set displaced-stepping off"
+gdb_breakpoint "main" "breakpoint at main"
+gdb_test "continue" " stop 0 .*" "continue to main"
+delete_breakpoints
+
+set curr_stop 0
+foreach displaced { "off" "on" } {
+    with_test_prefix "displaced $displaced" {
+
+	gdb_test_no_output "set displaced-stepping $displaced"
+
+	foreach go { "once" "twice" } {
+	    with_test_prefix $go {
+		gdb_test "break" "Breakpoint .* at .*" "set breakpoint"
+
+		# Whether we should see a warning.
+		set should_warn [expr {$go == "once" && $displaced == "on"}]
+
+		incr curr_stop
+
+		set msg "step over breakpoint"
+		set pattern " stop $curr_stop .*$gdb_prompt $"
+		gdb_test_multiple "next" $msg {
+		    -re "warning: disabling displaced stepping.*$pattern" {
+			gdb_assert $should_warn $msg
+		    }
+		    -re "$pattern" {
+			gdb_assert !$should_warn $msg
+		    }
+		}
+	    }
+	}
+    }
+}
+
+# Only if valgrind got stuck.
+remote_exec host "kill -9 ${valgrind_pid}"
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 22/23] S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (7 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 04/23] Change adjust_pc_after_break's prototype Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 10/23] PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping on Pedro Alves
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

This adds displaced stepping support for the General-Instruction
Extension Facility instructions, which have a PC-relative displacement
(RIL-b/RIL-c).  We already handle RIL branches, but not others.

Currently, displaced stepping a breakpoint put on any of these
instructions results in the inferior crashing when or after the
instruction is executed out-of-line in the scratch pad.

This patch takes the easy route of patching the displacement in the
copy of the instruction in the scratch pad.  As the displacement is a
signed 32-bit field, it's possible that the stratch pad ends too far
that the needed displacement doesn't fit in the adjusted instruction,
as e.g., if stepping over a breakpoint in a shared library (the
scratch pad is around the main program's entry point).  That case is
detected and GDB falls back to stepping over the breakpoint in-line
(which involves pausing all threads momentarily).

(We could probably do something smarter, but I don't plan on doing it
myself.  This was already sufficient to get "maint set target-non-stop
on" working regression free on S/390.)

Tested on S/390 RHEL 7.1, where it fixes a few hundred FAILs when
testing with displaced stepping enabled, with the end result being no
regressions compared to a test run that doesn't force displaced
stepping.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* s390-linux-tdep.c (is_non_branch_ril)
	(s390_displaced_step_copy_insn): New functions.
	(s390_displaced_step_fixup): Update comment.
	(s390_gdbarch_init): Install s390_displaced_step_copy_insn as
	gdbarch_displaced_step_copy_insn hook.
---
 gdb/s390-linux-tdep.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 112 insertions(+), 3 deletions(-)

diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index cafa57b..bdbc7c2 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -1529,6 +1529,116 @@ s390_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 /* Displaced stepping.  */
 
+/* Return true if INSN is a non-branch RIL-b or RIL-c format
+   instruction.  */
+
+static int
+is_non_branch_ril (gdb_byte *insn)
+{
+  gdb_byte op1 = insn[0];
+
+  if (op1 == 0xc4)
+    {
+      gdb_byte op2 = insn[1] & 0x0f;
+
+      switch (op2)
+	{
+	case 0x02: /* llhrl */
+	case 0x04: /* lghrl */
+	case 0x05: /* lhrl */
+	case 0x06: /* llghrl */
+	case 0x07: /* sthrl */
+	case 0x08: /* lgrl */
+	case 0x0b: /* stgrl */
+	case 0x0c: /* lgfrl */
+	case 0x0d: /* lrl */
+	case 0x0e: /* llgfrl */
+	case 0x0f: /* strl */
+	  return 1;
+	}
+    }
+  else if (op1 == 0xc6)
+    {
+      gdb_byte op2 = insn[1] & 0x0f;
+
+      switch (op2)
+	{
+	case 0x00: /* exrl */
+	case 0x02: /* pfdrl */
+	case 0x04: /* cghrl */
+	case 0x05: /* chrl */
+	case 0x06: /* clghrl */
+	case 0x07: /* clhrl */
+	case 0x08: /* cgrl */
+	case 0x0a: /* clgrl */
+	case 0x0c: /* cgfrl */
+	case 0x0d: /* crl */
+	case 0x0e: /* clgfrl */
+	case 0x0f: /* clrl */
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+/* Implementation of gdbarch_displaced_step_copy_insn.  */
+
+static struct displaced_step_closure *
+s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
+			       CORE_ADDR from, CORE_ADDR to,
+			       struct regcache *regs)
+{
+  size_t len = gdbarch_max_insn_length (gdbarch);
+  gdb_byte *buf = xmalloc (len);
+  struct cleanup *old_chain = make_cleanup (xfree, buf);
+
+  read_memory (from, buf, len);
+
+  /* Adjust the displacement field of PC-relative RIL instructions,
+     except branches.  The latter are handled in the fixup hook.  */
+  if (is_non_branch_ril (buf))
+    {
+      LONGEST offset;
+
+      offset = extract_signed_integer (buf + 2, 4, BFD_ENDIAN_BIG);
+      offset = (from - to + offset * 2) / 2;
+
+      /* If the instruction is too far from the jump pad, punt.  This
+	 will usually happen with instructions in shared libraries.
+	 We could probably support these by rewriting them to be
+	 absolute or fully emulating them.  */
+      if (offset < INT32_MIN || offset > INT32_MAX)
+	{
+	  /* Let the core fall back to stepping over the breakpoint
+	     in-line.  */
+	  if (debug_displaced)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "displaced: can't displaced step "
+				  "RIL instruction: offset %s out of range\n",
+				  plongest (offset));
+	    }
+	  do_cleanups (old_chain);
+	  return NULL;
+	}
+
+      store_signed_integer (buf + 2, 4, BFD_ENDIAN_BIG, offset);
+    }
+
+  write_memory (to, buf, len);
+
+  if (debug_displaced)
+    {
+      fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
+                          paddress (gdbarch, from), paddress (gdbarch, to));
+      displaced_step_dump_bytes (gdb_stdlog, buf, len);
+    }
+
+  discard_cleanups (old_chain);
+  return (struct displaced_step_closure *) buf;
+}
+
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
@@ -1537,8 +1647,7 @@ s390_displaced_step_fixup (struct gdbarch *gdbarch,
 			   CORE_ADDR from, CORE_ADDR to,
 			   struct regcache *regs)
 {
-  /* Since we use simple_displaced_step_copy_insn, our closure is a
-     copy of the instruction.  */
+  /* Our closure is a copy of the instruction.  */
   gdb_byte *insn = (gdb_byte *) closure;
   static int s390_instrlen[] = { 2, 4, 4, 6 };
   int insnlen = s390_instrlen[insn[0] >> 6];
@@ -3291,7 +3400,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
-					simple_displaced_step_copy_insn);
+					s390_displaced_step_copy_insn);
   set_gdbarch_displaced_step_fixup (gdbarch, s390_displaced_step_fixup);
   set_gdbarch_displaced_step_free_closure (gdbarch,
 					   simple_displaced_step_free_closure);
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 09/23] Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (10 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 05/23] remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and TARGET_WNOHANG Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 23/23] native Linux: enable always non-stop by default Pedro Alves
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

This test is currently failing like this on PPC64 and s390x:

 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: with thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: with thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: next: next

gdb.log:

 (gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: set scheduler-locking off
 step
 wait_threads () at ../../../src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c:49
 49        return 1; /* in wait_threads */
 (gdb) FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: step

The problem is that the test assumes that both the "watch_me = 1;" and
the "other = 1;" lines compile to a single instruction each, which
happens to be true on x86, but no necessarily true everywhere else.
The result is that the test doesn't really test what it wants to test.

Fix it by looking for the instruction that triggers the watchpoint.

The test now fails in a different way on PPC, and only when displaced stepping:

 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: continue: continue (the program exited)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: continue: continue (the program exited)

And that's actually a GDB bug.  That is, the test is now effectively
doing its job on PPC64 too.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.threads/step-over-trips-on-watchpoint.c (child_function):
	Remove comment.
	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): Find
	both the address of the instruction that triggers the watchpoint
	and the address of the instruction immediately after, and use
	those addresses for the test.  Fix comment.
---
 .../gdb.threads/step-over-trips-on-watchpoint.c    |  2 +-
 .../gdb.threads/step-over-trips-on-watchpoint.exp  | 44 +++++++++++++++++++---
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
index 13404da..6cf97fb 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
@@ -36,7 +36,7 @@ child_function (void *arg)
       counter++;
 
       watch_me = 1; /* set breakpoint child here */
-      other = 1; /* set thread-specific breakpoint here */
+      other = 1;
       usleep (1);
     }
 
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
index 7a0fb79..3ccceae 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
@@ -37,6 +37,8 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
 # triggers the watchpoint.
 proc do_test { displaced with_bp } {
     global executable
+    global gdb_prompt
+    global hex
 
     if ${with_bp} {
 	set prefix "with thread-specific bp"
@@ -66,13 +68,44 @@ proc do_test { displaced with_bp } {
 		gdb_breakpoint [gdb_get_line_number "set breakpoint child here"]
 		gdb_test "thread 2" "Switching to .*"
 		gdb_continue_to_breakpoint "run to breakpoint in thread 2"
+
+		set address_triggers_watch "<invalid>"
+		set after_address_triggers_watch "<invalid>"
+
+		# Let the watchpoint trigger once (with the other
+		# thread locked), in order to find both the address of
+		# the instruction that triggers the watchpoint and the
+		# address of the instruction immediately after.
+		with_test_prefix "find addresses" {
+		    gdb_test "p watch_me = 0" " = 0" "clear watch_me"
+		    gdb_test "watch watch_me" "Hardware watchpoint .*"
+
+		    gdb_test "continue" \
+			"Hardware watchpoint.*: watch_me.*New value = 1.*" \
+			"continue to watchpoint"
+
+		    set msg "find addresses"
+		    gdb_test_multiple "disassemble" $msg {
+			-re " ($hex) \[^\r\n\]*\r\n=> ($hex) .*$gdb_prompt $" {
+			    set address_triggers_watch $expect_out(1,string)
+			    set after_address_triggers_watch $expect_out(2,string)
+			    pass $msg
+			}
+		    }
+
+		    delete_breakpoints
+		}
+
+		gdb_breakpoint "*$address_triggers_watch"
+		gdb_continue_to_breakpoint \
+		    "run to instruction that triggers watch in thread 2"
+
 		gdb_test "p counter = 0" " = 0" "unbreak loop in thread 2"
 		gdb_test "p watch_me = 0" " = 0" "clear watch_me"
 		gdb_test "watch watch_me" "Hardware watchpoint .*"
 
 		if ${with_bp} {
-		    set linenum [gdb_get_line_number "set thread-specific breakpoint here"]
-		    gdb_test "b $linenum thread 1"
+		    gdb_test "b *$after_address_triggers_watch thread 1"
 		}
 
 		# Switch back to thread 1 and disable scheduler locking.
@@ -80,9 +113,10 @@ proc do_test { displaced with_bp } {
 		gdb_test_no_output "set scheduler-locking off"
 
 		# Thread 2 is still stopped at a breakpoint that needs to be
-		# stepped over before proceeding thread 1.  However, right
-		# where the step-over lands there's another breakpoint
-		# installed, which should trap and be reported to the user.
+		# stepped over before proceeding thread 1.  However, the
+		# instruction that is under the breakpoint triggers a
+		# watchpoint, which should trap and be reported to the
+		# user.
 		gdb_test "$command" "Hardware watchpoint.*: watch_me.*New value = 1.*"
 	    }
 	}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 13:36   ` Eli Zaretskii
  2015-04-08  9:34   ` Yao Qi
  2015-04-07 12:50 ` [PATCH v2 16/23] Fix signal-while-stepping-over-bp-other-thread.exp on targets always in non-stop Pedro Alves
                   ` (23 subsequent siblings)
  24 siblings, 2 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

This finally implements user-visible all-stop mode running with the
target_ops backend always in non-stop mode.  This is a stepping stone
towards finer-grained control of threads, being able to do interesting
things like thread groups, associating groups with breakpoints, etc.
From the user's perspective, all-stop mode is really just a special
case of being able to stop and resume specific sets of threads, so it
makes sense to do this step first.

With this, even in all-stop, the target is no longer in charge of
stopping all threads before reporting an event to the core -- the core
takes care of it when it sees fit.  For example, when "next"- or
"step"-ing, we can avoid stopping and resuming all threads at each
internal single-step, and instead only stop all threads when we're
about to present the stop to the user.

The implementation is almost straight forward, as the heavy lifting
has been done already in previous patches.  Basically, we replace
checks for "set non-stop on/off" (the non_stop global), with calls to
a new target_is_non_stop_p function.  In a few places, if "set
non-stop off", we stop all threads explicitly, and in a few other
places we resume all threads explicitly, making use of existing
methods that were added for teaching non-stop to step over breakpoints
without displaced stepping.

This adds a new "maint set target-non-stop on/off/auto" knob that
allows both disabling the feature if we find problems, and
force-enable it for development (useful when teaching a target about
this.  The default is "auto", which means the feature is enabled if a
new target method says it should be enabled.  The patch implements the
method in linux-nat.c, just for illustration, because it still returns
false.  We'll need a few follow up fixes before turning it on by
default.  This is a separate target method from indicating regular
non-stop support, because e.g., while e.g., native linux-nat.c is
close to regression free with all-stop-non-stop (with following
patches will fixing the remaining regressions), remote.c+gdbserver
will still need more fixing, even though it supports "set non-stop
on".

Tested on x86_64 Fedora 20, native, with and without "set displaced
off", and with and without "maint set target-non-stop on"; and also
against gdbserver.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* NEWS: Mention "maint set/show target-non-stop".
	* breakpoint.c (update_global_location_list): Check
	target_is_non_stop_p instead of non_stop.
	* infcmd.c (attach_command_post_wait, attach_command): Likewise.
	* infrun.c (show_can_use_displaced_stepping)
	(can_use_displaced_stepping_p, start_step_over_inferior):
	Likewise.
	(resume): Always resume a single thread if the target is in
	non-stop mode.
	(proceed): Check target_is_non_stop_p instead of non_stop.  If in
	all-mode but the target is always in non-stop mode, start all the
	other threads that are implicitly resumed too.
	(for_each_just_stopped_thread, fetch_inferior_event)
	(adjust_pc_after_break, stop_all_threads): Check
	target_is_non_stop_p instead of non_stop.
	(handle_inferior_event): Likewise.  Handle detach-fork in all-stop
	with the target always in non-stop mode.
	(handle_signal_stop) <random signal>: If we get a signal while
	stepping over a breakpoint, and the target is always in non-stop
	mode, restart all threads.
	(switch_back_to_stepped_thread): Check target_is_non_stop_p
	instead of non_stop.
	(keep_going_stepped_thread): Always resume a single thread if the
	target is in non-stop mode.
	(stop_waiting): If in all-stop mode, and the target is in non-stop
	mode, stop all threads.
	(keep_going_pass): Likewise, when starting a new in-line step-over
	sequence.
	* linux-nat.c (get_pending_status, select_event_lwp)
	(linux_nat_filter_event, linux_nat_wait_1, linux_nat_wait): Check
	target_is_non_stop_p instead of non_stop.
	(linux_nat_always_non_stop_p): New function.
	(linux_nat_stop): Check target_is_non_stop_p instead of non_stop.
	(linux_nat_add_target): Install linux_nat_always_non_stop_p.
	* target-delegates.c: Regenerate.
	* target.c (target_is_non_stop_p): New function.
	(target_non_stop_enabled, target_non_stop_enabled_1): New globals.
	(maint_set_target_non_stop_command)
	(maint_show_target_non_stop_command): New functions.
	(_initilize_target): Install "maint set/show target-non-stop"
	commands.
	* target.h (struct target_ops) <to_always_non_stop_p>: New field.
	(target_non_stop_enabled): New declaration.
	(target_is_non_stop_p): New declaration.

gdb/doc/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (Maintenance Commands): Document "maint set/show
	target-non-stop".

v2:

 - Documentation adjusted per Eli's review.  NEWS entry added.
 - `proceed' change simplified, thanks to fixes in v2 of previous
   patches in the series.
---
 gdb/NEWS               |   6 +++
 gdb/breakpoint.c       |   2 +-
 gdb/doc/gdb.texinfo    |  24 +++++++++++
 gdb/infcmd.c           |   4 +-
 gdb/infrun.c           | 107 ++++++++++++++++++++++++++++++++++++++++---------
 gdb/linux-nat.c        |  25 ++++++++----
 gdb/target-delegates.c |  31 ++++++++++++++
 gdb/target.c           |  62 ++++++++++++++++++++++++++++
 gdb/target.h           |  13 ++++++
 9 files changed, 245 insertions(+), 29 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 884c381..0ff99ad 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -49,6 +49,12 @@ maint print symbol-cache-statistics
 maint flush-symbol-cache
   Flush the contents of the symbol cache.
 
+maint set target-non-stop (on|off|auto)
+maint show target-non-stop
+  Control whether GDB targets always operate in non-stop mode even if
+  "set non-stop" is "off".  The default is "auto", meaning non-stop
+  mode is enabled if supported by the target.
+
 record btrace bts
 record bts
   Start branch trace recording using Branch Trace Store (BTS) format.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 76c86f8..641d7f4 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -12346,7 +12346,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
 
       if (!found_object)
 	{
-	  if (removed && non_stop
+	  if (removed && target_is_non_stop_p ()
 	      && need_moribund_for_location_type (old_loc))
 	    {
 	      /* This location was removed from the target.  In
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d794893..57888fc 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -34108,6 +34108,30 @@ asynchronous mode (@pxref{Background Execution}).  Normally the
 default is asynchronous, if it is available; but this can be changed
 to more easily debug problems occurring only in synchronous mode.
 
+@kindex maint set target-non-stop @var{mode} [on|off|auto]
+@kindex maint show target-non-stop
+@item maint set target-non-stop
+@itemx maint show target-non-stop
+
+This controls whether @value{GDBN} targets always operate in non-stop
+mode even if @code{set non-stop} is @code{off} (@pxref{Non-Stop
+Mode}).  The default is @code{auto}, meaning non-stop mode is enabled
+if supported by the target.
+
+@table @code
+@item maint set target-non-stop auto
+This is the default mode.  @value{GDBN} controls the target in
+non-stop mode if the target supports it.
+
+@item maint set target-non-stop on
+@value{GDBN} controls the target in non-stop mode even if the target
+does not indicate support.
+
+@item maint set target-non-stop off
+@value{GDBN} does not control the target in non-stop mode even if the
+target supports it.
+@end table
+
 @kindex maint set per-command
 @kindex maint show per-command
 @item maint set per-command
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 1c70675..94d87214 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2565,7 +2565,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
 	 selected thread is stopped, others may still be executing.
 	 Be sure to explicitly stop all threads of the process.  This
 	 should have no effect on already stopped threads.  */
-      if (non_stop)
+      if (target_is_non_stop_p ())
 	target_stop (pid_to_ptid (inferior->pid));
 
       /* Tell the user/frontend where we're stopped.  */
@@ -2670,7 +2670,7 @@ attach_command (char *args, int from_tty)
   init_wait_for_inferior ();
   clear_proceed_status (0);
 
-  if (non_stop)
+  if (target_is_non_stop_p ())
     {
       /* If we find that the current thread isn't stopped, explicitly
 	 do so now, because we're going to install breakpoints and
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8e49fa2..8da97fc 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1593,7 +1593,7 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
     fprintf_filtered (file,
 		      _("Debugger's willingness to use displaced stepping "
 			"to step over breakpoints is %s (currently %s).\n"),
-		      value, non_stop ? "on" : "off");
+		      value, target_is_non_stop_p () ? "on" : "off");
   else
     fprintf_filtered (file,
 		      _("Debugger's willingness to use displaced stepping "
@@ -1606,7 +1606,8 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
 static int
 can_use_displaced_stepping_p (struct gdbarch *gdbarch)
 {
-  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO && non_stop)
+  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO
+	    && target_is_non_stop_p ())
 	   || can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
 	  && gdbarch_displaced_step_copy_insn_p (gdbarch)
 	  && find_record_target () == NULL);
@@ -1972,7 +1973,7 @@ start_step_over_inferior (struct inferior *inf)
 	 wouldn't be able to resume anything else until the target
 	 stops again.  In non-stop, the resume always resumes only TP,
 	 so it's OK to let the thread resume freely.  */
-      if (!non_stop && !thread_still_needs_step_over (tp))
+      if (!target_is_non_stop_p () && !thread_still_needs_step_over (tp))
 	continue;
 
       switch_to_thread (tp->ptid);
@@ -1997,7 +1998,7 @@ start_step_over_inferior (struct inferior *inf)
 	{
 	  /* In all-stop, we shouldn't have resumed unless we needed a
 	     step over.  */
-	  gdb_assert (non_stop);
+	  gdb_assert (target_is_non_stop_p ());
 	}
     }
 
@@ -2352,7 +2353,10 @@ resume (enum gdb_signal sig)
 	      insert_single_step_breakpoint (gdbarch, aspace, pc);
 	      insert_breakpoints ();
 
-	      resume_ptid = user_visible_resume_ptid (user_step);
+	      if (target_is_non_stop_p ())
+		resume_ptid = inferior_ptid;
+	      else
+		resume_ptid = user_visible_resume_ptid (user_step);
 	      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
 	      discard_cleanups (old_cleanups);
 	      return;
@@ -2456,8 +2460,14 @@ resume (enum gdb_signal sig)
   resume_ptid = user_visible_resume_ptid (user_step);
 
   /* Maybe resume a single thread after all.  */
-  if ((step || thread_has_single_step_breakpoints_set (tp))
-      && tp->control.trap_expected)
+  if (target_is_non_stop_p ())
+    {
+      /* If non-stop mode, threads are always controlled
+	 individually.  */
+      resume_ptid = inferior_ptid;
+    }
+  else if ((step || thread_has_single_step_breakpoints_set (tp))
+	   && tp->control.trap_expected)
     {
       /* We're allowing a thread to run past a breakpoint it has
 	 hit, by single-stepping the thread with the breakpoint
@@ -2902,11 +2912,51 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 	 other thread was already doing one.  In either case, don't
 	 resume anything else until the step-over is finished.  */
     }
-  else if (started && !non_stop)
+  else if (started && !target_is_non_stop_p ())
     {
       /* A new displaced stepping sequence was started.  In all-stop,
 	 we can't talk to the target anymore until it next stops.  */
     }
+  else if (!non_stop && target_is_non_stop_p ())
+    {
+      /* Start all other threads that are implicitly resumed too.  */
+      ALL_NON_EXITED_THREADS (tp)
+        {
+	  /* Ignore threads of processes we're not resuming.  */
+	  if (!ptid_match (tp->ptid, resume_ptid))
+	    continue;
+
+	  if (tp->executing)
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: proceed: [%s] executing\n",
+				    target_pid_to_str (tp->ptid));
+	      gdb_assert (tp->resumed);
+	      continue;
+	    }
+
+	  if (tp->step_over_next != NULL)
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: proceed: [%s] needs step-over\n",
+				    target_pid_to_str (tp->ptid));
+	      continue;
+	    }
+
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: proceed: resuming %s\n",
+				target_pid_to_str (tp->ptid));
+
+	  reset_ecs (ecs, tp);
+	  switch_to_thread (tp->ptid);
+	  keep_going_pass (ecs);
+	  if (!ecs->wait_some_more)
+	    error ("Command aborted.");
+	}
+    }
   else if (!tp->executing && tp->step_over_next == NULL)
     {
       /* The thread wasn't started, and isn't queued, run it now.  */
@@ -3132,7 +3182,7 @@ for_each_just_stopped_thread (for_each_just_stopped_thread_callback_func func)
   if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid))
     return;
 
-  if (non_stop)
+  if (target_is_non_stop_p ())
     {
       /* If in non-stop mode, only the current thread stopped.  */
       func (inferior_thread ());
@@ -3608,7 +3658,7 @@ fetch_inferior_event (void *client_data)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
   else
     ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
@@ -3847,7 +3897,8 @@ adjust_pc_after_break (struct thread_info *thread,
      to get the "stopped by SW BP and needs adjustment" info out of
      the target/kernel (and thus never reach here; see above).  */
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
-      || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
+      || (target_is_non_stop_p ()
+	  && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
       struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
@@ -4052,7 +4103,7 @@ stop_all_threads (void)
   ptid_t entry_ptid;
   struct cleanup *old_chain;
 
-  gdb_assert (non_stop);
+  gdb_assert (target_is_non_stop_p ());
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
@@ -4414,7 +4465,7 @@ handle_inferior_event (struct execution_control_state *ecs)
   {
     ptid_t mark_ptid;
 
-    if (!non_stop)
+    if (!target_is_non_stop_p ())
       mark_ptid = minus_one_ptid;
     else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
 	     && ecs->ws.kind == TARGET_WAITKIND_EXITED)
@@ -4717,7 +4768,8 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 	  child = ecs->ws.value.related_pid;
 
 	  /* In non-stop mode, also resume the other branch.  */
-	  if (non_stop && !detach_fork)
+	  if (!detach_fork && (non_stop
+			       || (sched_multi && target_is_non_stop_p ())))
 	    {
 	      if (follow_child)
 		switch_to_thread (parent);
@@ -4953,7 +5005,7 @@ finish_step_over (struct execution_control_state *ecs)
 	clear_step_over_info ();
     }
 
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     return;
 
   /* Start a new step-over in another thread if there's one that
@@ -5453,6 +5505,17 @@ handle_signal_stop (struct execution_control_state *ecs)
 	  /* Reset trap_expected to ensure breakpoints are re-inserted.  */
 	  ecs->event_thread->control.trap_expected = 0;
 
+	  if (!non_stop && target_is_non_stop_p ())
+	    {
+	      keep_going (ecs);
+
+	      /* We've canceled the step-over temporarily while the
+		 signal handler executes.  Let other threads run,
+		 according to schedlock.  */
+	      restart_threads (ecs->event_thread);
+	      return;
+	    }
+
 	  /* If we were nexting/stepping some other thread, switch to
 	     it, so that we don't continue it, losing control.  */
 	  if (!switch_back_to_stepped_thread (ecs))
@@ -6336,7 +6399,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 static int
 switch_back_to_stepped_thread (struct execution_control_state *ecs)
 {
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       struct thread_info *tp;
       struct thread_info *stepping_thread;
@@ -6587,7 +6650,10 @@ keep_going_stepped_thread (struct thread_info *tp)
 				     stop_pc);
 
       tp->resumed = 1;
-      resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+      if (target_is_non_stop_p ())
+	resume_ptid = inferior_ptid;
+      else
+	resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
       do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
     }
   else
@@ -7005,6 +7071,11 @@ stop_waiting (struct execution_control_state *ecs)
 
   /* Let callers know we don't want to wait for the inferior anymore.  */
   ecs->wait_some_more = 0;
+
+  /* If all-stop, but the target is always in non-stop mode, stop all
+     threads now that we're presenting the stop to the user.  */
+  if (!non_stop && target_is_non_stop_p ())
+    stop_all_threads ();
 }
 
 /* Like keep_going, but passes the signal to the inferior, even if the
@@ -7124,7 +7195,7 @@ keep_going_pass (struct execution_control_state *ecs)
 	 insert_breakpoints below, because that removes the breakpoint
 	 we're about to step over, otherwise other threads could miss
 	 it.  */
-      if (step_over_info_valid_p () && non_stop)
+      if (step_over_info_valid_p () && target_is_non_stop_p ())
 	stop_all_threads ();
 
       /* Stop stepping if inserting breakpoints fails.  */
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 04707dc..9de291e 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1375,13 +1375,13 @@ get_pending_status (struct lwp_info *lp, int *status)
     signo = GDB_SIGNAL_0; /* a pending ptrace event, not a real signal.  */
   else if (lp->status)
     signo = gdb_signal_from_host (WSTOPSIG (lp->status));
-  else if (non_stop && !is_executing (lp->ptid))
+  else if (target_is_non_stop_p () && !is_executing (lp->ptid))
     {
       struct thread_info *tp = find_thread_ptid (lp->ptid);
 
       signo = tp->suspend.stop_signal;
     }
-  else if (!non_stop)
+  else if (!target_is_non_stop_p ())
     {
       struct target_waitstatus last;
       ptid_t last_ptid;
@@ -2931,7 +2931,7 @@ select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status)
      having stepped the thread, wouldn't understand what the trap was
      for, and therefore would report it to the user as a random
      signal.  */
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       event_lp = iterate_over_lwps (filter,
 				    select_singlestep_lwp_callback, NULL);
@@ -3278,7 +3278,7 @@ linux_nat_filter_event (int lwpid, int status)
     {
       enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
 
-      if (!non_stop)
+      if (!target_is_non_stop_p ())
 	{
 	  /* Only do the below in all-stop, as we currently use SIGSTOP
 	     to implement target_stop (see linux_nat_stop) in
@@ -3544,7 +3544,7 @@ linux_nat_wait_1 (struct target_ops *ops,
   status = lp->status;
   lp->status = 0;
 
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       /* Now stop all other LWP's ...  */
       iterate_over_lwps (minus_one_ptid, stop_callback, NULL);
@@ -3586,7 +3586,7 @@ linux_nat_wait_1 (struct target_ops *ops,
      clears it.  */
   last_resume_kind = lp->last_resume_kind;
 
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       /* In all-stop, from the core's perspective, all LWPs are now
 	 stopped until a new resume action is sent over.  */
@@ -3719,7 +3719,7 @@ linux_nat_wait (struct target_ops *ops,
      specific_process, for example, see linux_nat_wait_1), and
      meanwhile the event became uninteresting.  Don't bother resuming
      LWPs we're not going to wait for if they'd stop immediately.  */
-  if (non_stop)
+  if (target_is_non_stop_p ())
     iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid);
 
   event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options);
@@ -4551,6 +4551,14 @@ linux_nat_supports_non_stop (struct target_ops *self)
   return 1;
 }
 
+/* to_always_non_stop_p implementation.  */
+
+static int
+linux_nat_always_non_stop_p (struct target_ops *self)
+{
+  return 0;
+}
+
 /* True if we want to support multi-process.  To be removed when GDB
    supports multi-exec.  */
 
@@ -4770,7 +4778,7 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 static void
 linux_nat_stop (struct target_ops *self, ptid_t ptid)
 {
-  if (non_stop)
+  if (target_is_non_stop_p ())
     iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
   else
     linux_ops->to_stop (linux_ops, ptid);
@@ -4868,6 +4876,7 @@ linux_nat_add_target (struct target_ops *t)
   t->to_can_async_p = linux_nat_can_async_p;
   t->to_is_async_p = linux_nat_is_async_p;
   t->to_supports_non_stop = linux_nat_supports_non_stop;
+  t->to_always_non_stop_p = linux_nat_always_non_stop_p;
   t->to_async = linux_nat_async;
   t->to_terminal_inferior = linux_nat_terminal_inferior;
   t->to_terminal_ours = linux_nat_terminal_ours;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 36eacbf..8a92acf 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -1744,6 +1744,33 @@ debug_supports_non_stop (struct target_ops *self)
 }
 
 static int
+delegate_always_non_stop_p (struct target_ops *self)
+{
+  self = self->beneath;
+  return self->to_always_non_stop_p (self);
+}
+
+static int
+tdefault_always_non_stop_p (struct target_ops *self)
+{
+  return 0;
+}
+
+static int
+debug_always_non_stop_p (struct target_ops *self)
+{
+  int result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_always_non_stop_p (...)\n", debug_target.to_shortname);
+  result = debug_target.to_always_non_stop_p (&debug_target);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_always_non_stop_p (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_int (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
+static int
 delegate_find_memory_regions (struct target_ops *self, find_memory_region_ftype arg1, void *arg2)
 {
   self = self->beneath;
@@ -4005,6 +4032,8 @@ install_delegators (struct target_ops *ops)
     ops->to_async = delegate_async;
   if (ops->to_supports_non_stop == NULL)
     ops->to_supports_non_stop = delegate_supports_non_stop;
+  if (ops->to_always_non_stop_p == NULL)
+    ops->to_always_non_stop_p = delegate_always_non_stop_p;
   if (ops->to_find_memory_regions == NULL)
     ops->to_find_memory_regions = delegate_find_memory_regions;
   if (ops->to_make_corefile_notes == NULL)
@@ -4232,6 +4261,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_is_async_p = tdefault_is_async_p;
   ops->to_async = tdefault_async;
   ops->to_supports_non_stop = tdefault_supports_non_stop;
+  ops->to_always_non_stop_p = tdefault_always_non_stop_p;
   ops->to_find_memory_regions = dummy_find_memory_regions;
   ops->to_make_corefile_notes = dummy_make_corefile_notes;
   ops->to_get_bookmark = tdefault_get_bookmark;
@@ -4380,6 +4410,7 @@ init_debug_target (struct target_ops *ops)
   ops->to_is_async_p = debug_is_async_p;
   ops->to_async = debug_async;
   ops->to_supports_non_stop = debug_supports_non_stop;
+  ops->to_always_non_stop_p = debug_always_non_stop_p;
   ops->to_find_memory_regions = debug_find_memory_regions;
   ops->to_make_corefile_notes = debug_make_corefile_notes;
   ops->to_get_bookmark = debug_get_bookmark;
diff --git a/gdb/target.c b/gdb/target.c
index e992a35..ab6c977 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3752,6 +3752,58 @@ maint_show_target_async_command (struct ui_file *file, int from_tty,
 		      "asynchronous mode is %s.\n"), value);
 }
 
+/* See target.h.  */
+
+int
+target_is_non_stop_p (void)
+{
+  return (non_stop
+	  || target_non_stop_enabled == AUTO_BOOLEAN_TRUE
+	  || (target_non_stop_enabled == AUTO_BOOLEAN_AUTO
+	      && current_target.to_always_non_stop_p (&current_target)));
+}
+
+/* Controls if targets can report that they always run in non-stop
+   mode.  This is just for maintainers to use when debugging gdb.  */
+enum auto_boolean target_non_stop_enabled = AUTO_BOOLEAN_AUTO;
+
+/* The set command writes to this variable.  If the inferior is
+   executing, target_non_stop_enabled is *not* updated.  */
+static enum auto_boolean target_non_stop_enabled_1 = AUTO_BOOLEAN_AUTO;
+
+/* Implementation of "maint set target-non-stop".  */
+
+static void
+maint_set_target_non_stop_command (char *args, int from_tty,
+				   struct cmd_list_element *c)
+{
+  if (have_live_inferiors ())
+    {
+      target_non_stop_enabled_1 = target_non_stop_enabled;
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  target_non_stop_enabled = target_non_stop_enabled_1;
+}
+
+/* Implementation of "maint show target-non-stop".  */
+
+static void
+maint_show_target_non_stop_command (struct ui_file *file, int from_tty,
+				    struct cmd_list_element *c,
+				    const char *value)
+{
+  if (target_non_stop_enabled == AUTO_BOOLEAN_AUTO)
+    fprintf_filtered (file,
+		      _("Whether the target is always in non-stop mode "
+			"is %s (currently %s).\n"), value,
+		      target_is_non_stop_p () ? "on" : "off");
+  else
+    fprintf_filtered (file,
+		      _("Whether the target is always in non-stop mode "
+			"is %s.\n"), value);
+}
+
 /* Temporary copies of permission settings.  */
 
 static int may_write_registers_1 = 1;
@@ -3854,6 +3906,16 @@ Tells gdb whether to control the inferior in asynchronous mode."),
 			   &maintenance_set_cmdlist,
 			   &maintenance_show_cmdlist);
 
+  add_setshow_auto_boolean_cmd ("target-non-stop", no_class,
+				&target_non_stop_enabled_1, _("\
+Set whether gdb always controls the inferior in non-stop mode."), _("\
+Show whether gdb always controls the inferior in non-stop mode."), _("\
+Tells gdb whether to control the inferior in non-stop mode."),
+			   maint_set_target_non_stop_command,
+			   maint_show_target_non_stop_command,
+			   &maintenance_set_cmdlist,
+			   &maintenance_show_cmdlist);
+
   add_setshow_boolean_cmd ("may-write-registers", class_support,
 			   &may_write_registers_1, _("\
 Set permission to write into registers."), _("\
diff --git a/gdb/target.h b/gdb/target.h
index 1f6dd98..2663db5 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -635,6 +635,10 @@ struct target_ops
        comment on 'to_can_run'.  */
     int (*to_supports_non_stop) (struct target_ops *)
       TARGET_DEFAULT_RETURN (0);
+    /* Return true if the target operates in non-stop mode even when
+       "set non-stop off".  */
+    int (*to_always_non_stop_p) (struct target_ops *)
+      TARGET_DEFAULT_RETURN (0);
     /* find_memory_regions support method for gcore */
     int (*to_find_memory_regions) (struct target_ops *,
 				   find_memory_region_ftype func, void *data)
@@ -1701,6 +1705,15 @@ extern int target_async_permitted;
 /* Enables/disabled async target events.  */
 extern void target_async (int enable);
 
+/* Whether support for controlling the target backends always in
+   non-stop mode is enabled.  */
+extern enum auto_boolean target_non_stop_enabled;
+
+/* Is the target in non-stop mode?  Some targets control the inferior
+   in non-stop mode even with "set non-stop off".  Always true if "set
+   non-stop" is on.  */
+extern int target_is_non_stop_p (void);
+
 #define target_execution_direction() \
   (current_target.to_execution_direction (&current_target))
 
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 23/23] native Linux: enable always non-stop by default
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (11 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 09/23] Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86 Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 19/23] Disable displaced stepping if trying it fails Pedro Alves
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

The testsuite shows no regressions with this forced on, on:

 - Native x86_64 Fedora 20, with and output "set displaced off".

 - Native x86_64 Fedora 20, on top of x86 software single-step series.

 - PPC64 Fedora 18.

 - S/390 RHEL 7.1.

Let's try making it the default.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* linux-nat.c (linux_nat_always_non_stop_p): Return 1.
---
 gdb/linux-nat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index d8001f9..4b08b31 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4556,7 +4556,7 @@ linux_nat_supports_non_stop (struct target_ops *self)
 static int
 linux_nat_always_non_stop_p (struct target_ops *self)
 {
-  return 0;
+  return 1;
 }
 
 /* True if we want to support multi-process.  To be removed when GDB
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (14 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-09 12:46   ` Pedro Alves
  2015-04-07 12:55 ` [PATCH v2 17/23] Fix interrupt-noterm.exp on targets always in non-stop Pedro Alves
                   ` (8 subsequent siblings)
  24 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Running break-interp.exp with the target always in non-stop mode trips
on PR13858, as enabling non-stop also enables displaced stepping.

The problem is that when GDB doesn't know where the entry point is, it
doesn't know where to put the displaced stepping scratch pad.  The
test added by this commit exercises this.  Without the fix, we get:

 (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: break *$pc
 set displaced-stepping on
 (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: set displaced-stepping on
 stepi
 0x00000000004005be in ?? ()
 Entry point address is not known.
 (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: stepi
 p /x $pc
 $2 = 0x4005be
 (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: get after PC
 FAIL: gdb.base/step-over-no-symbols.exp: displaced=on: advanced

The fix is to fall back to stepping over the breakpoint in-line if we
don't know where the entry point address is.

This is enough to fix all-stop + "set displaced on".  For non-stop,
we'll need to teach core gdb to pause all threads to be able to start
the in-line step-over (because then we need to remove the breakpoint
from the target temporarily).

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	PR gdb/13858
	* infrun.c (use_displaced_stepping): Rename to ...
	(can_use_displaced_stepping_p): ... this.
	(use_displaced_stepping_now_p): New function.
	(resume): Clear trap_expected if waiting for vfork-done.  Use
	use_displaced_stepping_now_p.
	(keep_going): Use use_displaced_stepping_now_p now.

gdb/testsuite/
2015-04-07  Pedro Alves  <palves@redhat.com>

	PR gdb/13858
	* gdb.base/step-over-no-symbols.exp: New file.
---
 gdb/infrun.c                                    | 83 +++++++++++++----------
 gdb/testsuite/gdb.base/step-over-no-symbols.exp | 88 +++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 33 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/step-over-no-symbols.exp

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 466bc4a..48da790 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1581,7 +1581,7 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
    over breakpoints.  */
 
 static int
-use_displaced_stepping (struct gdbarch *gdbarch)
+can_use_displaced_stepping_p (struct gdbarch *gdbarch)
 {
   return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO && non_stop)
 	   || can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
@@ -1589,6 +1589,24 @@ use_displaced_stepping (struct gdbarch *gdbarch)
 	  && find_record_target () == NULL);
 }
 
+/* Return non-zero if displaced stepping should be used to step
+   over a breakpoint in the current thread.  */
+
+static int
+use_displaced_stepping_now_p (struct gdbarch *gdbarch,
+			      enum gdb_signal sig)
+{
+  CORE_ADDR retval;
+
+  /* We can't use displaced stepping when we have a signal to deliver;
+     the comments for displaced_step_prepare explain why.  The
+     comments in the handle_inferior event for dealing with 'random
+     signals' explain what we do instead.  */
+  return  (sig == GDB_SIGNAL_0
+	   && can_use_displaced_stepping_p (gdbarch)
+	   && entry_point_address_query (&retval));
+}
+
 /* Clean out any stray displaced stepping state.  */
 static void
 displaced_step_clear (struct displaced_step_inferior_state *displaced)
@@ -2140,6 +2158,10 @@ resume (enum gdb_signal sig)
 	fprintf_unfiltered (gdb_stdlog,
 			    "infrun: resume : clear step\n");
       step = 0;
+
+      /* Likewise, make sure we don't use displaced stepping, which
+	 would poke the scratch buffer in the child.  */
+      tp->control.trap_expected = 0;
     }
 
   if (debug_infrun)
@@ -2235,20 +2257,8 @@ resume (enum gdb_signal sig)
     tp->control.may_range_step = 0;
 
   /* If enabled, step over breakpoints by executing a copy of the
-     instruction at a different address.
-
-     We can't use displaced stepping when we have a signal to deliver;
-     the comments for displaced_step_prepare explain why.  The
-     comments in the handle_inferior event for dealing with 'random
-     signals' explain what we do instead.
-
-     We can't use displaced stepping when we are waiting for vfork_done
-     event, displaced stepping breaks the vfork child similarly as single
-     step software breakpoint.  */
-  if (use_displaced_stepping (gdbarch)
-      && tp->control.trap_expected
-      && sig == GDB_SIGNAL_0
-      && !current_inferior ()->waiting_for_vfork_done)
+     instruction at a different address.  */
+  if (tp->control.trap_expected && use_displaced_stepping_now_p (gdbarch, sig))
     {
       struct displaced_step_inferior_state *displaced;
 
@@ -2391,8 +2401,8 @@ resume (enum gdb_signal sig)
     }
 
   if (debug_displaced
-      && use_displaced_stepping (gdbarch)
-      && tp->control.trap_expected)
+      && tp->control.trap_expected
+      && use_displaced_stepping_now_p (gdbarch, sig))
     {
       struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
       struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
@@ -2707,7 +2717,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      displaced stepping to do so, insert all breakpoints (watchpoints,
      etc.) but the one we're stepping over, step one instruction, and
      then re-insert the breakpoint when that step is finished.  */
-  if (tp->stepping_over_breakpoint && !use_displaced_stepping (gdbarch))
+  if (tp->stepping_over_breakpoint
+      && !use_displaced_stepping_now_p (gdbarch,
+					tp->suspend.stop_signal))
     {
       struct regcache *regcache = get_current_regcache ();
 
@@ -6255,6 +6267,7 @@ keep_going (struct execution_control_state *ecs)
       struct regcache *regcache = get_current_regcache ();
       int remove_bp;
       int remove_wps;
+      enum gdb_signal signo;
 
       /* Either the trap was not expected, but we are continuing
 	 anyway (if we got a signal, the user asked it be passed to
@@ -6280,7 +6293,25 @@ keep_going (struct execution_control_state *ecs)
       remove_wps = (ecs->event_thread->stepping_over_watchpoint
 		    && !target_have_steppable_watchpoint);
 
-      if (remove_bp && !use_displaced_stepping (get_regcache_arch (regcache)))
+      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
+	 explicitly specifies that such a signal should be delivered
+	 to the target program).  Typically, that would occur when a
+	 user is debugging a target monitor on a simulator: the target
+	 monitor sets a breakpoint; the simulator encounters this
+	 breakpoint and halts the simulation handing control to GDB;
+	 GDB, noting that the stop address doesn't map to any known
+	 breakpoint, returns control back to the simulator; the
+	 simulator then delivers the hardware equivalent of a
+	 GDB_SIGNAL_TRAP to the program being debugged.	 */
+      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+	  && !signal_program[ecs->event_thread->suspend.stop_signal])
+	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+
+      signo = ecs->event_thread->suspend.stop_signal;
+
+      if (remove_bp
+	  && !use_displaced_stepping_now_p (get_regcache_arch (regcache),
+					    signo))
 	{
 	  set_step_over_info (get_regcache_aspace (regcache),
 			      regcache_read_pc (regcache), remove_wps);
@@ -6306,20 +6337,6 @@ keep_going (struct execution_control_state *ecs)
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
-      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
-	 explicitly specifies that such a signal should be delivered
-	 to the target program).  Typically, that would occur when a
-	 user is debugging a target monitor on a simulator: the target
-	 monitor sets a breakpoint; the simulator encounters this
-	 breakpoint and halts the simulation handing control to GDB;
-	 GDB, noting that the stop address doesn't map to any known
-	 breakpoint, returns control back to the simulator; the
-	 simulator then delivers the hardware equivalent of a
-	 GDB_SIGNAL_TRAP to the program being debugged.	 */
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-	  && !signal_program[ecs->event_thread->suspend.stop_signal])
-	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-
       discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
diff --git a/gdb/testsuite/gdb.base/step-over-no-symbols.exp b/gdb/testsuite/gdb.base/step-over-no-symbols.exp
new file mode 100644
index 0000000..d7bfd64
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-over-no-symbols.exp
@@ -0,0 +1,88 @@
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that GDB can step past a breakpoint even if GDB doesn't have
+# symbols for the main binary.
+
+standard_testfile start.c
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+if { [build_executable "failed to build" ${testfile} $srcfile] } {
+    return -1
+}
+
+# Get the current PC.  MSG is used as test message.
+
+proc get_pc { msg } {
+    global hex gdb_prompt
+
+    set addr ""
+    gdb_test_multiple "p /x \$pc" "$msg" {
+	-re " = ($hex).*$gdb_prompt $" {
+	    set addr $expect_out(1,string)
+	    pass "$msg"
+	}
+    }
+
+    return $addr
+}
+
+# Test stepping past a breakpoint with no symbols.  DISPLACED is one
+# of the "set displaced-stepping" options.  GDB should be able to fall
+# back to stepping past the breakpoint using an in-line step-over.
+
+proc test_step_over {displaced} {
+    global hex
+    global binfile
+
+    clean_restart $binfile
+
+    if ![runto_main] {
+	fail "couldn't run to main"
+	untested "stepping over breakpoint with displaced=$displaced"
+	return -1
+    }
+
+    delete_breakpoints
+
+    set msg "purging symbols"
+    gdb_test_multiple "symbol-file" "$msg" {
+	-re "Discard symbol table.*y or n. $" {
+	    gdb_test "y" "No symbol file now." "$msg"
+	}
+    }
+
+    set before_addr [get_pc "get before PC"]
+
+    gdb_test "break *\$pc" "Breakpoint .* at $hex"
+
+    gdb_test_no_output "set displaced-stepping $displaced"
+
+    gdb_test "stepi" "$hex in \?\? .*"
+
+    set after_addr [get_pc "get after PC"]
+
+    gdb_assert {$before_addr != $after_addr} "advanced"
+}
+
+foreach displaced { "off" "on" "auto" } {
+    with_test_prefix "displaced=$displaced" {
+	test_step_over $displaced
+    }
+}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 05/23] remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and TARGET_WNOHANG
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (9 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 10/23] PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping on Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 09/23] Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86 Pedro Alves
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Even though "target remote" supports target-async, the all-stop
target_wait implementation ignores TARGET_WNOHANG.  If the core
happens to poll for events and we've already read the stop reply out
of the serial/socket, remote_wait_as hangs forever instead of
returning an indication that there aren't events to process.  This
can't happen currently, but later changes will trigger this.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* remote.c (remote_wait_as): If not waiting for a stop reply,
	return TARGET_WAITKIND_NO_RESUMED.  If TARGET_WNOHANG is
	requested, don't block waiting forever.
---
 gdb/remote.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/gdb/remote.c b/gdb/remote.c
index 69a67a8..0bf8b87 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5953,6 +5953,14 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
     {
       int ret;
       int is_notif;
+      int forever = ((options & TARGET_WNOHANG) == 0
+		     && wait_forever_enabled_p);
+
+      if (!rs->waiting_for_stop_reply)
+	{
+	  status->kind = TARGET_WAITKIND_NO_RESUMED;
+	  return minus_one_ptid;
+	}
 
       if (!target_is_async_p ())
 	{
@@ -5971,7 +5979,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
 	 However, before we do that we need to ensure that the caller
 	 knows how to take the target into/out of async mode.  */
       ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size,
-				  wait_forever_enabled_p, &is_notif);
+				  forever, &is_notif);
 
       if (!target_is_async_p ())
 	signal (SIGINT, ofunc);
@@ -5980,6 +5988,9 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
 	 not interesting.  */
       if (ret != -1 && is_notif)
 	return minus_one_ptid;
+
+      if (ret == -1 && (options & TARGET_WNOHANG) != 0)
+	return minus_one_ptid;
     }
 
   buf = rs->buf;
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with displaced stepping
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (4 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 20/23] PPC64: symbol-file + exec-file results in broken displaced stepping Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 11/23] Use keep_going in proceed and start_step_over too Pedro Alves
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

The ppc64 displaced step code can't handle atomic sequences.  Fallback
to stepping over the breakpoint in-line if we detect one.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (displaced_step_prepare): Return -1 if
	gdbarch_displaced_step_copy_insn returns NULL.
	(resume): When displaced stepping doesn't work, try software
	single-stepping.
	* rs6000-tdep.c (LWARX_MASK, LWARX_INSTRUCTION, LDARX_INSTRUCTION)
	(STWCX_MASK, STWCX_INSTRUCTION, STDCX_INSTRUCTION): Move higher up
	in file.
	(ppc_displaced_step_copy_insn): New function.
	(ppc_displaced_step_fixup): Update comment.
	(rs6000_gdbarch_init): Install ppc_displaced_step_copy_insn as
	gdbarch_displaced_step_copy_insn hook.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.arch/ppc64-atomic-inst.exp (do_test): New procedure, move
	tests here.
	(top level): Run do_test with and without displaced stepping.
---
 gdb/infrun.c                                 | 11 +++--
 gdb/rs6000-tdep.c                            | 68 +++++++++++++++++++++++-----
 gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp | 50 ++++++++++++--------
 3 files changed, 97 insertions(+), 32 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 2f288a0..8ba81ec 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1765,9 +1765,14 @@ displaced_step_prepare (ptid_t ptid)
 
   closure = gdbarch_displaced_step_copy_insn (gdbarch,
 					      original, copy, regcache);
-
-  /* We don't support the fully-simulated case at present.  */
-  gdb_assert (closure);
+  if (closure == NULL)
+    {
+      /* The architecture doesn't know how or want to displaced step
+	 this instruction or instruction sequence.  Fallback to
+	 stepping over the breakpoint in-line.  */
+      do_cleanups (old_cleanups);
+      return -1;
+    }
 
   /* Save the information we need to fix things up if the step
      succeeds.  */
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index a125000..6106029 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -974,6 +974,61 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
 #define BXL_INSN 0x4c000000
 #define BP_INSN 0x7C000008
 
+/* Instruction masks used during single-stepping of atomic
+   sequences.  */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+
+/* We can't displaces step atomic sequenes.  Otherwise this is just
+   simple_displaced_step_copy_insn.  */
+
+static struct displaced_step_closure *
+ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
+			      CORE_ADDR from, CORE_ADDR to,
+			      struct regcache *regs)
+{
+  size_t len = gdbarch_max_insn_length (gdbarch);
+  gdb_byte *buf = xmalloc (len);
+  struct cleanup *old_chain = make_cleanup (xfree, buf);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int insn;
+
+  read_memory (from, buf, len);
+
+  insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
+
+  /* Assume all atomic sequences start with a lwarx/ldarx instruction.  */
+  if ((insn & LWARX_MASK) == LWARX_INSTRUCTION
+      || (insn & LWARX_MASK) == LDARX_INSTRUCTION)
+    {
+      if (debug_displaced)
+	{
+	  fprintf_unfiltered (gdb_stdlog,
+			      "displaced: can't displaced step "
+			      "atomic sequence at %s\n",
+			      paddress (gdbarch, from));
+	}
+      do_cleanups (old_chain);
+      return NULL;
+    }
+
+  write_memory (to, buf, len);
+
+  if (debug_displaced)
+    {
+      fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
+                          paddress (gdbarch, from), paddress (gdbarch, to));
+      displaced_step_dump_bytes (gdb_stdlog, buf, len);
+    }
+
+  discard_cleanups (old_chain);
+  return (struct displaced_step_closure *) buf;
+}
+
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
@@ -983,8 +1038,7 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
 			  struct regcache *regs)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  /* Since we use simple_displaced_step_copy_insn, our closure is a
-     copy of the instruction.  */
+  /* Our closure is a copy of the instruction.  */
   ULONGEST insn  = extract_unsigned_integer ((gdb_byte *) closure,
 					      PPC_INSN_SIZE, byte_order);
   ULONGEST opcode = 0;
@@ -1077,14 +1131,6 @@ ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
   return 1;
 }
 
-/* Instruction masks used during single-stepping of atomic sequences.  */
-#define LWARX_MASK 0xfc0007fe
-#define LWARX_INSTRUCTION 0x7c000028
-#define LDARX_INSTRUCTION 0x7c0000A8
-#define STWCX_MASK 0xfc0007ff
-#define STWCX_INSTRUCTION 0x7c00012d
-#define STDCX_INSTRUCTION 0x7c0001ad
-
 /* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
    instruction and ending with a STWCX/STDCX instruction.  If such a sequence
    is found, attempt to step through it.  A breakpoint is placed at the end of 
@@ -5923,7 +5969,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Setup displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
-					simple_displaced_step_copy_insn);
+					ppc_displaced_step_copy_insn);
   set_gdbarch_displaced_step_hw_singlestep (gdbarch,
 					    ppc_displaced_step_hw_singlestep);
   set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
diff --git a/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp b/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp
index d251425..08518fb 100644
--- a/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp
+++ b/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp
@@ -32,27 +32,41 @@ if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug quiet}]
     return -1
 }
 
-if ![runto_main] then {
-    untested "could not run to main"
-    return -1
-}
+# The test proper.  DISPLACED is true if we should try with displaced
+# stepping.
+proc do_test { displaced } {
+    global decimal hex
+
+    if ![runto_main] then {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_test_no_output "set displaced-stepping $displaced"
 
-set bp1 [gdb_get_line_number "lwarx"]
-gdb_breakpoint "$bp1" "Breakpoint $decimal at $hex" \
-  "Set the breakpoint at the start of the lwarx/stwcx sequence"
+    set bp1 [gdb_get_line_number "lwarx"]
+    gdb_breakpoint "$bp1" "Breakpoint $decimal at $hex" \
+	"Set the breakpoint at the start of the lwarx/stwcx sequence"
 
-set bp2 [gdb_get_line_number "ldarx"]
-gdb_breakpoint "$bp2" "Breakpoint $decimal at $hex" \
-  "Set the breakpoint at the start of the ldarx/stdcx sequence"
+    set bp2 [gdb_get_line_number "ldarx"]
+    gdb_breakpoint "$bp2" "Breakpoint $decimal at $hex" \
+	"Set the breakpoint at the start of the ldarx/stdcx sequence"
 
-gdb_test continue "Continuing.*Breakpoint $decimal.*" \
-  "Continue until lwarx/stwcx start breakpoint"
+    gdb_test continue "Continuing.*Breakpoint $decimal.*" \
+	"Continue until lwarx/stwcx start breakpoint"
 
-gdb_test nexti "bne.*1b" \
-  "Step through the lwarx/stwcx sequence"
+    gdb_test nexti "bne.*1b" \
+	"Step through the lwarx/stwcx sequence"
 
-gdb_test continue "Continuing.*Breakpoint $decimal.*" \
-  "Continue until ldarx/stdcx start breakpoint"
+    gdb_test continue "Continuing.*Breakpoint $decimal.*" \
+	"Continue until ldarx/stdcx start breakpoint"
 
-gdb_test nexti "bne.*1b" \
-  "Step through the ldarx/stdcx sequence"
+    gdb_test nexti "bne.*1b" \
+	"Step through the ldarx/stdcx sequence"
+}
+
+foreach displaced { "off" "on" } {
+    with_test_prefix "displaced=$displaced" {
+	do_test $displaced
+    }
+}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (13 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 19/23] Disable displaced stepping if trying it fails Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-10  9:56   ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols Pedro Alves
                   ` (9 subsequent siblings)
  24 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

TL;DR:

When stepping over a breakpoint with displaced stepping, the core must
be notified of all signals, otherwise the displaced step fixup code
confuses a breakpoint trap in the signal handler for the expected trap
indicating the displaced instruction was single-stepped
normally/successfully.

Detailed version:

Running sigstep.exp with displaced stepping on, against my x86
software single-step branch, I got:

 FAIL: gdb.base/sigstep.exp: step on breakpoint, to handler: performing step
 FAIL: gdb.base/sigstep.exp: next on breakpoint, to handler: performing next
 FAIL: gdb.base/sigstep.exp: continue on breakpoint, to handler: performing continue

Turning on debug logs, we see:

 (gdb) step
 infrun: clear_proceed_status_thread (process 32147)
 infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
 infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=1, current thread [process 32147] at 0x400842
 displaced: stepping process 32147 now
 displaced: saved 0x400622: 49 89 d1 5e 48 89 e2 48 83 e4 f0 50 54 49 c7 c0
 displaced: %rip-relative addressing used.
 displaced: using temp reg 2, old value 0x3615eafd37, new value 0x40084c
 displaced: copy 0x400842->0x400622: c7 81 1c 08 20 00 00 00 00 00
 displaced: displaced pc to 0x400622
 displaced: run 0x400622: c7 81 1c 08
 LLR: Preparing to resume process 32147, 0, inferior_ptid process 32147
 LLR: PTRACE_CONT process 32147, 0 (resume event thread)
 linux_nat_wait: [process -1], [TARGET_WNOHANG]
 LLW: enter
 LNW: waitpid(-1, ...) returned 32147, No child processes
 LLW: waitpid 32147 received Alarm clock (stopped)
 LLW: PTRACE_CONT process 32147, Alarm clock (preempt 'handle')
 LNW: waitpid(-1, ...) returned 0, No child processes
 LLW: exit (ignore)
 sigchld
 infrun: target_wait (-1.0.0, status) =
 infrun:   -1.0.0 [process -1],
 infrun:   status->kind = ignore
 infrun: TARGET_WAITKIND_IGNORE
 infrun: prepare_to_wait
 linux_nat_wait: [process -1], [TARGET_WNOHANG]
 LLW: enter
 LNW: waitpid(-1, ...) returned 32147, No child processes
 LLW: waitpid 32147 received Trace/breakpoint trap (stopped)
 CSBB: process 32147 stopped by software breakpoint
 LNW: waitpid(-1, ...) returned 0, No child processes
 LLW: trap ptid is process 32147.
 LLW: exit
 infrun: target_wait (-1.0.0, status) =
 infrun:   32147.32147.0 [process 32147],
 infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
 infrun: TARGET_WAITKIND_STOPPED
 displaced: restored process 32147 0x400622
 displaced: fixup (0x400842, 0x400622), insn = 0xc7 0x81 ...
 displaced: restoring reg 2 to 0x3615eafd37
 displaced: relocated %rip from 0x400717 to 0x400937
 infrun: stop_pc = 0x400937
 infrun: delayed software breakpoint trap, ignoring
 infrun: no line number info
 infrun: stop_waiting
 0x0000000000400937 in __dso_handle ()
 1: x/i $pc
 => 0x400937:    and    %ah,0xa0d64(%rip)        # 0x4a16a1
 (gdb) FAIL: gdb.base/sigstep.exp: displaced=on: step on breakpoint, to handler: performing step


What should have happened is that the breakpoint hit in the signal
handler should have been presented to the user.  But note that
"preempt 'handle'" -- what happened instead is that
displaced_step_fixup confused the breakpoint in the signal handler for
the expected SIGTRAP indicating the displaced instruction was
single-stepped normally/successfully.

This should be affecting all software single-step targets in the same
way.

The fix is to make sure the core sees all signals when displaced
stepping, just like we already must see all signals when doing an
stepping over a breakpoint in-line.  We now get:

 infrun: target_wait (-1.0.0, status) =
 infrun:   570.570.0 [process 570],
 infrun:   status->kind = stopped, signal = GDB_SIGNAL_ALRM
 infrun: TARGET_WAITKIND_STOPPED
 displaced: restored process 570 0x400622
 infrun: stop_pc = 0x400842
 infrun: random signal (GDB_SIGNAL_ALRM)
 infrun: signal arrived while stepping over breakpoint
 infrun: inserting step-resume breakpoint at 0x400842
 infrun: resume (step=0, signal=GDB_SIGNAL_ALRM), trap_expected=0, current thread [process 570] at 0x400842
 LLR: Preparing to resume process 570, Alarm clock, inferior_ptid process 570
 LLR: PTRACE_CONT process 570, Alarm clock (resume event thread)
 infrun: prepare_to_wait
 linux_nat_wait: [process -1], [TARGET_WNOHANG]
 LLW: enter
 LNW: waitpid(-1, ...) returned 0, No child processes
 LLW: exit (ignore)
 infrun: target_wait (-1.0.0, status) =
 infrun:   -1.0.0 [process -1],
 infrun:   status->kind = ignore
 sigchld
 infrun: TARGET_WAITKIND_IGNORE
 infrun: prepare_to_wait
 linux_nat_wait: [process -1], [TARGET_WNOHANG]
 LLW: enter
 LNW: waitpid(-1, ...) returned 570, No child processes
 LLW: waitpid 570 received Trace/breakpoint trap (stopped)
 CSBB: process 570 stopped by software breakpoint
 LNW: waitpid(-1, ...) returned 0, No child processes
 LLW: trap ptid is process 570.
 LLW: exit
 infrun: target_wait (-1.0.0, status) =
 infrun:   570.570.0 [process 570],
 infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
 infrun: TARGET_WAITKIND_STOPPED
 infrun: stop_pc = 0x400717
 infrun: BPSTAT_WHAT_STOP_NOISY
 infrun: stop_waiting

 Breakpoint 3, handler (sig=14) at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/sigstep.c:35
 35        done = 1;

Hardware single-step targets already behave this way, because the
Linux backends (both native and gdbserver) always report signals to
the core if the thread was single-stepping.

As mentioned in the new comment in do_target_resume, we can't fix this
by instead making the displaced_step_fixup phase skip fixing up the PC
if the single step stopped somewhere we didn't expect.  Here's what
the backtrace would look like if we did that:

 Breakpoint 3, handler (sig=14) at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/sigstep.c:35
 35        done = 1;
 1: x/i $pc
 => 0x400717 <handler+7>:        movl   $0x1,0x200943(%rip)        # 0x601064 <done>
 (gdb) bt
 #0  handler (sig=14) at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/sigstep.c:35
 #1  <signal handler called>
 #2  0x0000000000400622 in _start ()
 (gdb) FAIL: gdb.base/sigstep.exp: displaced=on: step on breakpoint, to handler: backtrace

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (displaced_step_in_progress): New function.
	(do_target_resume): Advise target to report all signals if
	displaced stepping.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.base/sigstep.exp (breakpoint_to_handler)
	(breakpoint_to_handler_entry): New parameter 'displaced'.  Use it.
	Test "backtrace" in handler.
	(breakpoint_over_handler): New parameter 'displaced'.  Use it.
	(top level): Add new "displaced" test axis to
	breakpoint_to_handler, breakpoint_to_handler_entry and
	breakpoint_over_handler.
---
 gdb/infrun.c                       | 40 +++++++++++++++---
 gdb/testsuite/gdb.base/sigstep.exp | 86 ++++++++++++++++++++++++++++----------
 2 files changed, 98 insertions(+), 28 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 607a6e4..a270ca9 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1465,6 +1465,20 @@ get_displaced_stepping_state (int pid)
   return NULL;
 }
 
+/* Return true if process PID has a thread doing a displaced step.  */
+
+static int
+displaced_step_in_progress (int pid)
+{
+  struct displaced_step_inferior_state *displaced;
+
+  displaced = get_displaced_stepping_state (pid);
+  if (displaced != NULL && !ptid_equal (displaced->step_ptid, null_ptid))
+    return 1;
+
+  return 0;
+}
+
 /* Add a new displaced stepping state for process PID to the displaced
    stepping state list, or return a pointer to an already existing
    entry, if it already exists.  Never returns NULL.  */
@@ -2047,11 +2061,27 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
      happens to apply to another thread.  */
   tp->suspend.stop_signal = GDB_SIGNAL_0;
 
-  /* Advise target which signals may be handled silently.  If we have
-     removed breakpoints because we are stepping over one (in any
-     thread), we need to receive all signals to avoid accidentally
-     skipping a breakpoint during execution of a signal handler.  */
-  if (step_over_info_valid_p ())
+  /* Advise target which signals may be handled silently.
+
+     If we have removed breakpoints because we are stepping over one
+     in-line (in any thread), we need to receive all signals to avoid
+     accidentally skipping a breakpoint during execution of a signal
+     handler.
+
+     Likewise if we're displaced stepping, otherwise a trap for a
+     breakpoint in a signal handler might be confused with the
+     displaced step finishing.  We don't make the displaced_step_fixup
+     step distinguish the cases instead, because:
+
+     - a backtrace while stopped in the signal handler would show the
+       scratch pad as frame older than the signal handler, instead of
+       the real mainline code.
+
+     - when the thread is later resumed, the signal handler would
+       return to the scratch pad area, which would no longer be
+       valid.  */
+  if (step_over_info_valid_p ()
+      || displaced_step_in_progress (ptid_get_pid (tp->ptid)))
     target_pass_signals (0, NULL);
   else
     target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
diff --git a/gdb/testsuite/gdb.base/sigstep.exp b/gdb/testsuite/gdb.base/sigstep.exp
index c4f7e91..3c9454c 100644
--- a/gdb/testsuite/gdb.base/sigstep.exp
+++ b/gdb/testsuite/gdb.base/sigstep.exp
@@ -409,13 +409,19 @@ foreach cmd {"stepi" "nexti" "step" "next" "continue"} {
 
 # Try stepping when there's a signal pending, a pre-existing
 # breakpoint at the current instruction, and a breakpoint in the
-# handler.  Should advance to the signal handler.
+# handler.  Should advance to the signal handler.  DISPLACED indicates
+# whether to try with or without displaced stepping (to exercise the
+# different techniques of stepping over the breakpoint at the current
+# instruction).
 
-proc breakpoint_to_handler { cmd } {
+proc breakpoint_to_handler { displaced cmd } {
     global infinite_loop
 
-    with_test_prefix "$cmd on breakpoint, to handler" {
+    with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler" {
 	restart
+
+	gdb_test_no_output "set displaced-stepping $displaced"
+
 	# Use the real-time itimer, as otherwize the process never gets
 	# enough time to expire the timer.
 	gdb_test_no_output "set itimer = itimer_real"
@@ -430,11 +436,21 @@ proc breakpoint_to_handler { cmd } {
 	sleep 1
 
 	gdb_test "$cmd" " handler .*" "performing $cmd"
+
+	# Make sure we the displaced stepping scratch pad isn't in the
+	# backtrace.
+	gdb_test_sequence "bt" "backtrace" {
+	    "\[\r\n\]+.0 \[^\r\n\]* handler "
+	    "\[\r\n\]+.1  .signal handler called."
+	    "\[\r\n\]+.2 \[^\r\n\]* main "
+	}
     }
 }
 
-foreach cmd {"step" "next" "continue"} {
-    breakpoint_to_handler $cmd
+foreach displaced {"off" "on"} {
+    foreach cmd {"step" "next" "continue"} {
+	breakpoint_to_handler $displaced $cmd
+    }
 }
 
 # Try stepping when there's a signal pending, and a breakpoint at the
@@ -449,11 +465,17 @@ foreach cmd {"step" "next" "continue"} {
 # have been called by the trampoline code.  This test checks that it
 # is possible to stop the inferior, even at that first instruction.
 
-proc breakpoint_to_handler_entry { cmd } {
+# DISPLACED indicates whether to try with or without displaced
+# stepping (to exercise the different techniques of stepping over the
+# breakpoint at the current instruction).
+proc breakpoint_to_handler_entry { displaced cmd } {
     global infinite_loop
 
-    with_test_prefix "$cmd on breakpoint, to handler entry" {
+    with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler entry" {
 	restart
+
+	gdb_test_no_output "set displaced-stepping $displaced"
+
 	# Use the real-time itimer, as otherwize the process never gets
 	# enough time to expire the timer.
 	gdb_test_no_output "set itimer = itimer_real"
@@ -468,24 +490,37 @@ proc breakpoint_to_handler_entry { cmd } {
 	sleep 1
 
 	gdb_test "$cmd" " handler .*" "performing $cmd"
+
+	# Make sure we the displaced stepping scratch pad isn't in the
+	# backtrace.
+	gdb_test_sequence "bt" "backtrace" {
+	    "\[\r\n\]+.0 \[^\r\n\]* handler "
+	    "\[\r\n\]+.1  .signal handler called."
+	    "\[\r\n\]+.2 \[^\r\n\]* main "
+	}
     }
 }
 
-foreach cmd {"step" "next" "continue"} {
-    breakpoint_to_handler_entry $cmd
+foreach displaced {"off" "on"} {
+    foreach cmd {"step" "next" "continue"} {
+	breakpoint_to_handler_entry $displaced $cmd
+    }
 }
 
 # Try stepping when there's a signal pending, and a pre-existing
 # breakpoint at the current instruction, and no breakpoint in the
-# handler.  Should advance to the next line/instruction.  If SW_WATCH
-# is true, set a software watchpoint, which exercises stepping the
-# breakpoint instruction while delivering a signal at the same time.
-# If NO_HANDLER, arrange for the signal's handler be SIG_IGN, thus
-# when the software watchpoint is also set, testing stepping a
-# breakpoint instruction and immediately triggering the breakpoint
-# (exercises adjust_pc_after_break logic).
-
-proc breakpoint_over_handler { cmd with_sw_watch no_handler } {
+# handler.  Should advance to the next line/instruction.  DISPLACED
+# indicates whether to try with or without displaced stepping (to
+# exercise the different techniques of stepping over the breakpoint at
+# the current instruction).  If SW_WATCH is true, set a software
+# watchpoint, which exercises stepping the breakpoint instruction
+# while delivering a signal at the same time.  If NO_HANDLER, arrange
+# for the signal's handler be SIG_IGN, thus when the software
+# watchpoint is also set, testing stepping a breakpoint instruction
+# and immediately triggering the breakpoint (exercises
+# adjust_pc_after_break logic).
+
+proc breakpoint_over_handler { displaced cmd with_sw_watch no_handler } {
     global infinite_loop
     global clear_done
 
@@ -497,8 +532,11 @@ proc breakpoint_over_handler { cmd with_sw_watch no_handler } {
 	append prefix ", no handler"
     }
 
-    with_test_prefix "$prefix" {
+    with_test_prefix "displaced=$displaced: $prefix" {
 	restart
+
+	gdb_test_no_output "set displaced-stepping $displaced"
+
 	# Use the real-time itimer, as otherwize the process never gets
 	# enough time to expire the timer.
 	gdb_test_no_output "set itimer = itimer_real"
@@ -534,10 +572,12 @@ proc breakpoint_over_handler { cmd with_sw_watch no_handler } {
     }
 }
 
-foreach cmd {"stepi" "nexti" "step" "next" "continue"} {
-    foreach with_sw_watch {0 1} {
-	foreach no_handler {0 1} {
-	    breakpoint_over_handler $cmd $with_sw_watch $no_handler
+foreach displaced {"off" "on"} {
+    foreach cmd {"stepi" "nexti" "step" "next" "continue"} {
+	foreach with_sw_watch {0 1} {
+	    foreach no_handler {0 1} {
+		breakpoint_over_handler $displaced $cmd $with_sw_watch $no_handler
+	    }
 	}
     }
 }
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 10/23] PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping on
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (8 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 22/23] S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 05/23] remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and TARGET_WNOHANG Pedro Alves
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

PPC64 current fails this test like:

 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: no thread-specific bp: continue: continue (the program exited)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: step: step
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: next: next
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=on: with thread-specific bp: continue: continue (the program exited)

The problem is that PPC is a non-continuable watchpoints architecture
and the displaced stepping code isn't coping with that correctly.  On
such targets/architectures, a watchpoint traps _before_ the
instruction executes/completes.  On a watchpoint trap, the PC points
at the instruction that triggers the watchpoint (side effects haven't
happened yet).  In order to move past the watchpoint, GDB needs to
remove the watchpoint, single-step, and reinsert the watchpoint, just
like when stepping past a breakpoint.

The trouble is that if GDB is stepping over a breakpoint with
displaced stepping, and the instruction under the breakpoint triggers
a watchpoint, we get the watchpoint SIGTRAP, expecting a finished
(hard or software) step trap.  Even though the thread's PC hasn't
advanced yet (must remove watchpoint for that), since we get a
SIGTRAP, displaced_step_fixup thinks the single-step finished
successfuly anyway, and calls gdbarch_displaced_step_fixup, which then
adjusts the thread's registers incorrectly.

The fix is to cancel the displaced step if we trip on a watchpoint.
handle_inferior_event then processes the watchpoint event, and starts
a new step-over, but this time, since we have a watchpoint to step
over, watchpoints are removed from the target, so the step-over
succeeds.

The keep_going/resume changes are necessary because if we have a
watchpoint to step over, we need to remove it from the target -
displaced stepping doesn't help, the copy of the instruction in the
scratch pad reads/writes to the same addresses, thus triggers the
watchpoint too...  So without those changes we keep triggering the
watchpoint forever, never making progress.  With non-stop that means
we need to pause all threads momentarily.  We could avoid that by
removing the watchpoint _only_ from the thread that is moving past the
watchpoint, but GDB is not prepared for that today.  For remote
targets, that would need new packets, so good to have this as fallback
anyway.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (displaced_step_fixup): Switch to the event ptid
	earlier.  If the thread stopped for a watchpoint and the
	target/arch has non-continuable watchpoints, cancel the displaced
	step.
	(resume): Don't start a displaced step if in-line step-over info
	is valid.
---
 gdb/infrun.c | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 937a29d..fac0beb 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1792,6 +1792,8 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
   struct cleanup *old_cleanups;
   struct displaced_step_inferior_state *displaced
     = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+  struct regcache *regcache;
+  struct gdbarch *gdbarch;
 
   /* Was any thread of this process doing a displaced step?  */
   if (displaced == NULL)
@@ -1806,13 +1808,20 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
   displaced_step_restore (displaced, displaced->step_ptid);
 
+  /* Fixup may need to read memory/registers.  Switch to the thread
+     that we're fixing up.  Also, target_stopped_by_watchpoint checks
+     the current thread.  */
+  switch_to_thread (event_ptid);
+
+  regcache = get_thread_regcache (event_ptid);
+  gdbarch  = get_regcache_arch (regcache);
+
   /* Did the instruction complete successfully?  */
-  if (signal == GDB_SIGNAL_TRAP)
+  if (signal == GDB_SIGNAL_TRAP
+      && !(target_stopped_by_watchpoint ()
+	   && (target_have_steppable_watchpoint
+	       || gdbarch_have_nonsteppable_watchpoint (gdbarch))))
     {
-      /* Fixup may need to read memory/registers.  Switch to the
-	 thread that we're fixing up.  */
-      switch_to_thread (event_ptid);
-
       /* Fix up the resulting state.  */
       gdbarch_displaced_step_fixup (displaced->step_gdbarch,
                                     displaced->step_closure,
@@ -1824,7 +1833,6 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
     {
       /* Since the instruction didn't complete, all we can do is
          relocate the PC.  */
-      struct regcache *regcache = get_thread_regcache (event_ptid);
       CORE_ADDR pc = regcache_read_pc (regcache);
 
       pc = displaced->step_original + (pc - displaced->step_copy);
@@ -2261,7 +2269,9 @@ resume (enum gdb_signal sig)
 
   /* If enabled, step over breakpoints by executing a copy of the
      instruction at a different address.  */
-  if (tp->control.trap_expected && use_displaced_stepping_now_p (gdbarch, sig))
+  if (tp->control.trap_expected
+      && !step_over_info_valid_p ()
+      && use_displaced_stepping_now_p (gdbarch, sig))
     {
       struct displaced_step_inferior_state *displaced;
 
@@ -2405,6 +2415,7 @@ resume (enum gdb_signal sig)
 
   if (debug_displaced
       && tp->control.trap_expected
+      && !step_over_info_valid_p ()
       && use_displaced_stepping_now_p (gdbarch, sig))
     {
       struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
@@ -6351,15 +6362,18 @@ keep_going (struct execution_control_state *ecs)
 		   || (step_what & STEP_OVER_BREAKPOINT));
       remove_wps = (step_what & STEP_OVER_WATCHPOINT);
 
-      if (remove_bp
-	  && !use_displaced_stepping_now_p (get_regcache_arch (regcache),
-					    signo))
+      if (remove_wps && remove_bp)
+	set_step_over_info (get_regcache_aspace (regcache),
+			    regcache_read_pc (regcache), remove_wps);
+      else if (remove_wps)
+	set_step_over_info (NULL, 0, remove_wps);
+      else if (remove_bp
+	       && !use_displaced_stepping_now_p (get_regcache_arch (regcache),
+						 signo))
 	{
 	  set_step_over_info (get_regcache_aspace (regcache),
 			      regcache_read_pc (regcache), remove_wps);
 	}
-      else if (remove_wps)
-	set_step_over_info (NULL, 0, remove_wps);
       else
 	clear_step_over_info ();
 
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 20/23] PPC64: symbol-file + exec-file results in broken displaced stepping
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (3 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 12/23] Misc switch_back_to_stepped_thread cleanups Pedro Alves
@ 2015-04-07 12:50 ` Pedro Alves
  2015-04-07 12:50 ` [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with " Pedro Alves
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:50 UTC (permalink / raw)
  To: gdb-patches

Running gdb.base/dbx.exp with "set displaced-stepping on" on PPC64
fails like this:

 (gdb) run
 Starting program: build/gdb/testsuite/gdb.base/dbx

 Program received signal SIGSEGV, Segmentation fault.
 __GI__dl_debug_state () at dl-debug.c:75
 75      {
 (gdb) FAIL: gdb.base/dbx.exp: running to main

The problem is that GDB ended up with the wrong entry point address.
Displaced stepping puts the scratch pad at the entry point, thus the
crash.

Most other tests load the binary into GDB with "file", which is just a
wrapper for "exec-file + symbol-file".  However, this particular test
does the opposite: first "symbol-file", and then "exec-file".

symfile.c:init_entry_point_info makes certain that the entry point
address points at real code, and not a function descriptor, by calling
gdbarch_convert_from_func_ptr_addr.  However, ppc64's implementation
of gdbarch_convert_from_func_ptr_addr relies on target sections.  IOW,
on the exec_file being loaded already.  Thus if we use just
"symbol-file PROG", ppc64_convert_from_func_ptr_addr can't check of
ADDR points to a function descriptor, and
symfile.c:init_entry_point_info ends up caching the wrong entry point
address in the OBJFILE.  Even if the user uses "exec-file" afterwards,
GDB doesn't fix up the objfile's entry point address, as the address
had already been initialized:

 static void
 init_entry_point_info (struct objfile *objfile)
 {
   struct entry_info *ei = &objfile->per_bfd->ei;

   if (ei->initialized)
     return;

I think that it's expected that "symbol-file" alone doesn't work,
however, I think "symbol-file" followed by "exec-file" should behave
the same as "exec-file + symbol-file".

This patch fixes it by making GDB forget about the previously cached
entry point address when a new exec file is loaded.  I didn't make
this gdbarch-dependent in order to keep it simple.

New test that doesn't depend on --dbx included.  Fails without the GDB
fix.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* symfile.c (invalidate_symfile_entry_point_info): New function.
	(_initialize_symfile): Attach it as executable_changed observer.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.base/symbol-file-exec-file.c: New file.
	* gdb.base/symbol-file-exec-file.exp: New file.
---
 gdb/symfile.c                                    |  21 ++++
 gdb/testsuite/gdb.base/symbol-file-exec-file.c   |  30 ++++++
 gdb/testsuite/gdb.base/symbol-file-exec-file.exp | 126 +++++++++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/symbol-file-exec-file.c
 create mode 100644 gdb/testsuite/gdb.base/symbol-file-exec-file.exp

diff --git a/gdb/symfile.c b/gdb/symfile.c
index 0c35ffa..81244f7 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -900,6 +900,22 @@ read_symbols (struct objfile *objfile, int add_flags)
     require_partial_symbols (objfile, 0);
 }
 
+/* Forget about any previous computation of the main symfile's entry
+   point.  */
+
+static void
+invalidate_symfile_entry_point_info (void)
+{
+  struct entry_info *ei;
+
+  if (symfile_objfile == NULL)
+    return;
+
+  ei = &symfile_objfile->per_bfd->ei;
+  ei->initialized = 0;
+  ei->entry_point_p = 0;
+}
+
 /* Initialize entry point information for this objfile.  */
 
 static void
@@ -3957,6 +3973,11 @@ _initialize_symfile (void)
 
   observer_attach_free_objfile (symfile_free_objfile);
 
+  /* Some target's like PPC64 (see ppc64_convert_from_func_ptr_addr),
+     rely on the exec_file's target sections to compute the symfile's
+     entry point.  */
+  observer_attach_executable_changed (invalidate_symfile_entry_point_info);
+
   c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\
 Load symbol table from executable file FILE.\n\
 The `file' command can also load symbol tables, as well as setting the file\n\
diff --git a/gdb/testsuite/gdb.base/symbol-file-exec-file.c b/gdb/testsuite/gdb.base/symbol-file-exec-file.c
new file mode 100644
index 0000000..0b37f46
--- /dev/null
+++ b/gdb/testsuite/gdb.base/symbol-file-exec-file.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+void
+foo (int i)
+{
+}
+
+int
+main (void)
+{
+  foo (1);
+  foo (2);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/symbol-file-exec-file.exp b/gdb/testsuite/gdb.base/symbol-file-exec-file.exp
new file mode 100644
index 0000000..aebf794
--- /dev/null
+++ b/gdb/testsuite/gdb.base/symbol-file-exec-file.exp
@@ -0,0 +1,126 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that displaced stepping works if the program is loaded with
+# "symbol-file + exec-file", in that order.  GDB used to end up with a
+# broken entry point address on PPC64 in that case.  (The displaced
+# stepping scratch pad is put at the entry point.)
+
+standard_testfile
+
+if {[build_executable "failed to build" $testfile $srcfile debug] == -1} {
+    return -1
+}
+
+# Override gdb_file_cmd, allowing gdb_load to do its normal thing.
+# This way remotes and simulators work, too.
+
+set old_gdb_file_cmd_args [info args gdb_file_cmd]
+set old_gdb_file_cmd_body [info body gdb_file_cmd]
+
+set our_gdb_file_cmd_called 0
+
+set symbol_file_first 0
+
+proc gdb_file_cmd {arg} {
+    upvar timeout timeout
+    global last_loaded_file
+    global our_gdb_file_cmd_called
+    global symbol_file_first
+
+    set our_gdb_file_cmd_called 1
+
+    set last_loaded_file $arg
+
+    if [is_remote host] {
+        set arg [remote_download host $arg]
+        if { $arg == "" } {
+            error "download failed"
+            return -1
+        }
+    }
+
+    proc symbol_file {} {
+	upvar arg arg
+
+	if {[gdb_test "symbol-file $arg" \
+		 "Reading symbols from.*done\\." \
+		 "symbol-file \$arg"] != 0 } {
+	    return -code return -1
+	}
+    }
+
+    proc exec_file {} {
+	upvar arg arg
+
+	if {[gdb_test_no_output "exec-file $arg" \
+		 "exec-file \$arg"] != 0} {
+	    return -code return -1
+	}
+    }
+
+    if $symbol_file_first {
+	symbol_file
+	exec_file
+    } else {
+	exec_file
+	symbol_file
+    }
+
+    return 0
+}
+
+# The test proper.  DISPLACED indicates whether to use displaced
+# stepping to step over the breakpoint.
+proc do_test { displaced } {
+    global our_gdb_file_cmd_called
+    global binfile
+
+    set our_gdb_file_cmd_called 0
+
+    clean_restart $binfile
+
+    gdb_test "set displaced-stepping $displaced"
+
+    # Don't rely on runto_main leaving the breakpoint behind.
+    gdb_breakpoint "main"
+
+    gdb_run_cmd
+
+    gdb_test "" "Breakpoint 1, main .* foo \\(1\\);" "run to main"
+
+    gdb_assert $our_gdb_file_cmd_called "overridden gdb_file_cmd called"
+
+    gdb_test "next" "foo \\(2\\);" "step over breakpoint"
+}
+
+foreach displaced { "off" "on" } {
+    foreach symfile_first { 0 1 } {
+	set symbol_file_first $symfile_first
+
+	if { $symfile_first } {
+	    set prefix "symbol-file + exec-file"
+	} else {
+	    set prefix "exec-file + symbol-file"
+	}
+
+	with_test_prefix "displaced=$displaced: $prefix" {
+	    do_test $displaced
+	}
+    }
+}
+
+# Restore gdb_file_cmd.
+eval proc gdb_file_cmd {$old_gdb_file_cmd_args} {$old_gdb_file_cmd_body}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 17/23] Fix interrupt-noterm.exp on targets always in non-stop
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (15 preceding siblings ...)
  2015-04-07 12:50 ` [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols Pedro Alves
@ 2015-04-07 12:55 ` Pedro Alves
  2015-04-07 12:57 ` [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping Pedro Alves
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:55 UTC (permalink / raw)
  To: gdb-patches

With "maint set target-non-stop on" we get:

 @@ -66,13 +66,16 @@ Continuing.
  interrupt
  (gdb) PASS: gdb.base/interrupt-noterm.exp: interrupt

 -Program received signal SIGINT, Interrupt.
 -PASS: gdb.base/interrupt-noterm.exp: inferior received SIGINT
 -testcase src/gdb/testsuite/gdb.base/interrupt-noterm.exp completed in 0 seconds
 +[process 12119] #1 stopped.
 +0x0000003615ebc6d0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
 +81     T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
 +FAIL: gdb.base/interrupt-noterm.exp: inferior received SIGINT (timeout)
 +testcase src/gdb/testsuite/gdb.base/interrupt-noterm.exp completed in 10 seconds

That is, we get "[$thread] #1 stopped" instead of SIGINT.

The issue is that we don't currently distinguish send
"interrupt/ctrl-c" to target terminal vs "stop/pause" thread well;
both cases go through "target_stop".

And then, the native Linux backend (linux-nat.c) implements
target_stop with SIGSTOP in non-stop mode, and SIGINT in all-stop
mode.  Since "maint set target-non-stop on" forces the backend to be
always running in non-stop mode, even though the user-visible behavior
is "set non-stop" is "off", "interrupt" causes a SIGSTOP instead of
the SIGINT the test expects.

Fix this by introducing a target_interrupt method to use in the
"interrupt/ctrl-c" case, so "set non-stop off" can always work the
same irrespective of "maint set target-non-stop on/off".  I'm
explictly considering changing the "set non-stop on" behavior as out
of scope here.

Most of the patch is an across-the-board rename of to_stop hook
implementations to to_interrupt.  The only targets where something
more than a rename is being done are linux-nat.c and remote.c, which
are the only targets that support async, and thus are the only ones
the core side calls target_stop on.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* darwin-nat.c (darwin_stop): Rename to ...
	(darwin_interrupt): ... this.
	(_initialize_darwin_inferior): Adjust.
	* gnu-nat.c (gnu_stop): Delete.
	(gnu_thread_alive): Don't install gnu_stop.
	* inf-ptrace.c (inf_ptrace_stop): Rename to ...
	(inf_ptrace_interrupt): ... this.
	(inf_ptrace_target): Adjust.
	* infcmd.c (interrupt_target_1): Use target_interrupt instead of
	target_stop.
	* linux-nat (linux_nat_stop): Rename to ...
	(linux_nat_interrupt): ... this.
	(linux_nat_stop): Reimplement.
	(linux_nat_add_target): Install linux_nat_interrupt.
	* monitor.c (monitor_stop): Rename to ...
	(monitor_interrupt): ... this.
	(init_base_monitor_ops): Adjust.
	* nto-procfs.c (nto_interrupt_twice): Rename to ...
	(nto_handle_sigint_twice): ... this.
	(nto_interrupt): Rename to ...
	(nto_handle_sigint): ... this.  Call target_interrupt instead of
	target_stop.
	(procfs_wait, init_procfs_targets): Adjust.
	* procfs.c (procfs_target): Adjust.
	(procfs_stop): Rename to ...
	(procfs_interrupt): ... this.
	* remote-m32r-sdi.c (m32r_stop): Rename to ...
	(m32r_interrupt): ... this.
	(init_m32r_ops): Adjust.
	* remote-sim.c (gdbsim_stop_inferior): Rename to ...
	(gdbsim_interrupt_inferior): ... this.
	(gdbsim_stop): Rename to ...
	(gdbsim_interrupt): ... this.
	(gdbsim_cntrl_c): Adjust.
	(init_gdbsim_ops): Adjust.
	* remote.c (sync_remote_interrupt): Adjust comments.
	(remote_stop_as): Rename to ...
	(remote_interrupt_as): ... this.
	(remote_stop): Adjust comment.
	(remote_interrupt): New function.
	(init_remote_ops): Install remote_interrupt.
	* target.c (target_interrupt): New function.
	* target.h (struct target_ops) <to_interrupt>: New field.
	(target_interrupt): New declaration.
	* windows-nat.c (windows_stop): Rename to ...
	(windows_interrupt): ... this.
	* target-delegates.c: Regenerate.
---
 gdb/darwin-nat.c       |  6 +++---
 gdb/gnu-nat.c          |  7 -------
 gdb/inf-ptrace.c       |  6 +++---
 gdb/infcmd.c           |  2 +-
 gdb/linux-nat.c        | 12 +++++++++---
 gdb/monitor.c          |  4 ++--
 gdb/nto-procfs.c       | 14 +++++++-------
 gdb/procfs.c           |  4 ++--
 gdb/remote-m32r-sdi.c  |  6 +++---
 gdb/remote-sim.c       | 20 ++++++++++----------
 gdb/remote.c           | 44 +++++++++++++++++++++++++++++++++-----------
 gdb/target-delegates.c | 28 ++++++++++++++++++++++++++++
 gdb/target.c           | 12 ++++++++++++
 gdb/target.h           |  8 ++++++++
 gdb/windows-nat.c      |  6 +++---
 15 files changed, 124 insertions(+), 55 deletions(-)

diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index e1acc05..30e968f 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -83,7 +83,7 @@
 #define PTRACE(CMD, PID, ADDR, SIG) \
  darwin_ptrace(#CMD, CMD, (PID), (ADDR), (SIG))
 
-static void darwin_stop (struct target_ops *self, ptid_t);
+static void darwin_interrupt (struct target_ops *self, ptid_t);
 
 static void darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
                               enum gdb_signal signal);
@@ -1198,7 +1198,7 @@ darwin_wait_to (struct target_ops *ops,
 }
 
 static void
-darwin_stop (struct target_ops *self, ptid_t t)
+darwin_interrupt (struct target_ops *self, ptid_t t)
 {
   struct inferior *inf = current_inferior ();
 
@@ -2156,7 +2156,7 @@ _initialize_darwin_inferior (void)
   darwin_ops->to_wait = darwin_wait_to;
   darwin_ops->to_mourn_inferior = darwin_mourn_inferior;
   darwin_ops->to_kill = darwin_kill_inferior;
-  darwin_ops->to_stop = darwin_stop;
+  darwin_ops->to_interrupt = darwin_interrupt;
   darwin_ops->to_resume = darwin_resume_to;
   darwin_ops->to_thread_alive = darwin_thread_alive;
   darwin_ops->to_pid_to_str = darwin_pid_to_str;
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index d830773..4753634 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -2271,12 +2271,6 @@ gnu_terminal_init (struct target_ops *self)
   child_terminal_init_with_pgrp (gnu_current_inf->pid);
 }
 
-static void
-gnu_stop (struct target_ops *self, ptid_t ptid)
-{
-  error (_("to_stop target function not implemented"));
-}
-
 static int
 gnu_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
@@ -2686,7 +2680,6 @@ gnu_target (void)
   t->to_mourn_inferior = gnu_mourn_inferior;
   t->to_thread_alive = gnu_thread_alive;
   t->to_pid_to_str = gnu_pid_to_str;
-  t->to_stop = gnu_stop;
 
   return t;
 }
diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index cd58dfb..17ba903 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -288,10 +288,10 @@ inf_ptrace_kill (struct target_ops *ops)
   target_mourn_inferior ();
 }
 
-/* Stop the inferior.  */
+/* Interrupt the inferior.  */
 
 static void
-inf_ptrace_stop (struct target_ops *self, ptid_t ptid)
+inf_ptrace_interrupt (struct target_ops *self, ptid_t ptid)
 {
   /* Send a SIGINT to the process group.  This acts just like the user
      typed a ^C on the controlling terminal.  Note that using a
@@ -686,7 +686,7 @@ inf_ptrace_target (void)
   t->to_mourn_inferior = inf_ptrace_mourn_inferior;
   t->to_thread_alive = inf_ptrace_thread_alive;
   t->to_pid_to_str = inf_ptrace_pid_to_str;
-  t->to_stop = inf_ptrace_stop;
+  t->to_interrupt = inf_ptrace_interrupt;
   t->to_xfer_partial = inf_ptrace_xfer_partial;
 #if defined (PT_IO) && defined (PIOD_READ_AUXV)
   t->to_auxv_parse = inf_ptrace_auxv_parse;
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 94d87214..6ad8494 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2853,7 +2853,7 @@ interrupt_target_1 (int all_threads)
     ptid = minus_one_ptid;
   else
     ptid = inferior_ptid;
-  target_stop (ptid);
+  target_interrupt (ptid);
 
   /* Tag the thread as having been explicitly requested to stop, so
      other parts of gdb know not to resume this thread automatically,
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 9de291e..d8001f9 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4778,10 +4778,16 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 static void
 linux_nat_stop (struct target_ops *self, ptid_t ptid)
 {
-  if (target_is_non_stop_p ())
+  iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
+}
+
+static void
+linux_nat_interrupt (struct target_ops *self, ptid_t ptid)
+{
+  if (non_stop)
     iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
   else
-    linux_ops->to_stop (linux_ops, ptid);
+    linux_ops->to_interrupt (linux_ops, ptid);
 }
 
 static void
@@ -4884,8 +4890,8 @@ linux_nat_add_target (struct target_ops *t)
   super_close = t->to_close;
   t->to_close = linux_nat_close;
 
-  /* Methods for non-stop support.  */
   t->to_stop = linux_nat_stop;
+  t->to_interrupt = linux_nat_interrupt;
 
   t->to_supports_multi_process = linux_nat_supports_multi_process;
 
diff --git a/gdb/monitor.c b/gdb/monitor.c
index 548dae3..e47d479 100644
--- a/gdb/monitor.c
+++ b/gdb/monitor.c
@@ -2267,7 +2267,7 @@ monitor_load (struct target_ops *self, const char *args, int from_tty)
 }
 
 static void
-monitor_stop (struct target_ops *self, ptid_t ptid)
+monitor_interrupt (struct target_ops *self, ptid_t ptid)
 {
   monitor_debug ("MON stop\n");
   if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
@@ -2375,7 +2375,7 @@ init_base_monitor_ops (void)
   monitor_ops.to_load = monitor_load;
   monitor_ops.to_create_inferior = monitor_create_inferior;
   monitor_ops.to_mourn_inferior = monitor_mourn_inferior;
-  monitor_ops.to_stop = monitor_stop;
+  monitor_ops.to_interrupt = monitor_interrupt;
   monitor_ops.to_rcmd = monitor_rcmd;
   monitor_ops.to_log_command = serial_log_command;
   monitor_ops.to_thread_alive = monitor_thread_alive;
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
index 7312060..c318f19 100644
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -692,20 +692,20 @@ Give up (and stop debugging it)? ")))
 
 /* The user typed ^C twice.  */
 static void
-nto_interrupt_twice (int signo)
+nto_handle_sigint_twice (int signo)
 {
   signal (signo, ofunc);
   interrupt_query ();
-  signal (signo, nto_interrupt_twice);
+  signal (signo, nto_handle_sigint_twice);
 }
 
 static void
-nto_interrupt (int signo)
+nto_handle_sigint (int signo)
 {
   /* If this doesn't work, try more severe steps.  */
-  signal (signo, nto_interrupt_twice);
+  signal (signo, nto_handle_sigint_twice);
 
-  target_stop (inferior_ptid);
+  target_interrupt (inferior_ptid);
 }
 
 static ptid_t
@@ -733,7 +733,7 @@ procfs_wait (struct target_ops *ops,
   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
   while (!(status.flags & _DEBUG_FLAG_ISTOP))
     {
-      ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
+      ofunc = (void (*)()) signal (SIGINT, nto_handle_sigint);
       sigwaitinfo (&set, &info);
       signal (SIGINT, ofunc);
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
@@ -1444,7 +1444,7 @@ init_procfs_targets (void)
   t->to_thread_alive = procfs_thread_alive;
   t->to_update_thread_list = procfs_update_thread_list;
   t->to_pid_to_str = procfs_pid_to_str;
-  t->to_stop = procfs_stop;
+  t->to_interrupt = procfs_interrupt;
   t->to_have_continuable_watchpoint = 1;
   t->to_extra_thread_info = nto_extra_thread_info;
 
diff --git a/gdb/procfs.c b/gdb/procfs.c
index b62539f..e540e2a 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -194,7 +194,7 @@ procfs_target (void)
   t->to_xfer_partial = procfs_xfer_partial;
   t->to_pass_signals = procfs_pass_signals;
   t->to_files_info = procfs_files_info;
-  t->to_stop = procfs_stop;
+  t->to_interrupt = procfs_interrupt;
 
   t->to_update_thread_list = procfs_update_thread_list;
   t->to_thread_alive = procfs_thread_alive;
@@ -4204,7 +4204,7 @@ procfs_files_info (struct target_ops *ignore)
    kill(SIGINT) to the child's process group.  */
 
 static void
-procfs_stop (struct target_ops *self, ptid_t ptid)
+procfs_interrupt (struct target_ops *self, ptid_t ptid)
 {
   kill (-inferior_process_group (), SIGINT);
 }
diff --git a/gdb/remote-m32r-sdi.c b/gdb/remote-m32r-sdi.c
index 01cb5b6..b246cd9 100644
--- a/gdb/remote-m32r-sdi.c
+++ b/gdb/remote-m32r-sdi.c
@@ -1407,10 +1407,10 @@ m32r_load (struct target_ops *self, const char *args, int from_tty)
 }
 
 static void
-m32r_stop (struct target_ops *self, ptid_t ptid)
+m32r_interrupt (struct target_ops *self, ptid_t ptid)
 {
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "m32r_stop()\n");
+    fprintf_unfiltered (gdb_stdlog, "m32r_interrupt()\n");
 
   send_cmd (SDI_STOP_CPU);
 
@@ -1664,7 +1664,7 @@ init_m32r_ops (void)
   m32r_ops.to_load = m32r_load;
   m32r_ops.to_create_inferior = m32r_create_inferior;
   m32r_ops.to_mourn_inferior = m32r_mourn_inferior;
-  m32r_ops.to_stop = m32r_stop;
+  m32r_ops.to_interrupt = m32r_interrupt;
   m32r_ops.to_log_command = serial_log_command;
   m32r_ops.to_thread_alive = m32r_thread_alive;
   m32r_ops.to_pid_to_str = m32r_pid_to_str;
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index fd2fd58..766356a 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -87,7 +87,7 @@ static void gdbsim_files_info (struct target_ops *target);
 
 static void gdbsim_mourn_inferior (struct target_ops *target);
 
-static void gdbsim_stop (struct target_ops *self, ptid_t ptid);
+static void gdbsim_interrupt (struct target_ops *self, ptid_t ptid);
 
 void simulator_command (char *args, int from_tty);
 
@@ -888,17 +888,17 @@ gdbsim_resume (struct target_ops *ops,
     error (_("The program is not being run."));
 }
 
-/* Notify the simulator of an asynchronous request to stop.
+/* Notify the simulator of an asynchronous request to interrupt.
 
-   The simulator shall ensure that the stop request is eventually
+   The simulator shall ensure that the interrupt request is eventually
    delivered to the simulator.  If the call is made while the
-   simulator is not running then the stop request is processed when
+   simulator is not running then the interrupt request is processed when
    the simulator is next resumed.
 
    For simulators that do not support this operation, just abort.  */
 
 static int
-gdbsim_stop_inferior (struct inferior *inf, void *arg)
+gdbsim_interrupt_inferior (struct inferior *inf, void *arg)
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED);
@@ -918,13 +918,13 @@ gdbsim_stop_inferior (struct inferior *inf, void *arg)
 }
 
 static void
-gdbsim_stop (struct target_ops *self, ptid_t ptid)
+gdbsim_interrupt (struct target_ops *self, ptid_t ptid)
 {
   struct sim_inferior_data *sim_data;
 
   if (ptid_equal (ptid, minus_one_ptid))
     {
-      iterate_over_inferiors (gdbsim_stop_inferior, NULL);
+      iterate_over_inferiors (gdbsim_interrupt_inferior, NULL);
     }
   else
     {
@@ -934,7 +934,7 @@ gdbsim_stop (struct target_ops *self, ptid_t ptid)
 	error (_("Can't stop pid %d.  No inferior found."),
 	       ptid_get_pid (ptid));
 
-      gdbsim_stop_inferior (inf, NULL);
+      gdbsim_interrupt_inferior (inf, NULL);
     }
 }
 
@@ -962,7 +962,7 @@ gdb_os_poll_quit (host_callback *p)
 static void
 gdbsim_cntrl_c (int signo)
 {
-  gdbsim_stop (NULL, minus_one_ptid);
+  gdbsim_interrupt (NULL, minus_one_ptid);
 }
 
 static ptid_t
@@ -1320,7 +1320,7 @@ init_gdbsim_ops (void)
   gdbsim_ops.to_load = gdbsim_load;
   gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
   gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
-  gdbsim_ops.to_stop = gdbsim_stop;
+  gdbsim_ops.to_interrupt = gdbsim_interrupt;
   gdbsim_ops.to_thread_alive = gdbsim_thread_alive;
   gdbsim_ops.to_pid_to_str = gdbsim_pid_to_str;
   gdbsim_ops.to_stratum = process_stratum;
diff --git a/gdb/remote.c b/gdb/remote.c
index 0bf8b87..c1b7fd4 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4991,11 +4991,12 @@ async_cleanup_sigint_signal_handler (void *dummy)
    packet.  */
 static void (*ofunc) (int);
 
-/* The command line interface's stop routine.  This function is installed
-   as a signal handler for SIGINT.  The first time a user requests a
-   stop, we call remote_stop to send a break or ^C.  If there is no
+/* The command line interface's interrupt routine.  This function is installed
+   as a signal handler for SIGINT.  The first time a user requests an
+   interrupt, we call remote_interrupt to send a break or ^C.  If there is no
    response from the target (it didn't stop when the user requested it),
    we ask the user if he'd like to detach from the target.  */
+
 static void
 sync_remote_interrupt (int signo)
 {
@@ -5066,12 +5067,12 @@ remote_stop_ns (ptid_t ptid)
     error (_("Stopping %s failed: %s"), target_pid_to_str (ptid), rs->buf);
 }
 
-/* All-stop version of target_stop.  Sends a break or a ^C to stop the
-   remote target.  It is undefined which thread of which process
-   reports the stop.  */
+/* All-stop version of target_interrupt.  Sends a break or a ^C to
+   interrupt the remote target.  It is undefined which thread of which
+   process reports the interrupt.  */
 
 static void
-remote_stop_as (ptid_t ptid)
+remote_interrupt_as (ptid_t ptid)
 {
   struct remote_state *rs = get_remote_state ();
 
@@ -5087,9 +5088,7 @@ remote_stop_as (ptid_t ptid)
   send_interrupt_sequence ();
 }
 
-/* This is the generic stop called via the target vector.  When a target
-   interrupt is requested, either by the command line or the GUI, we
-   will eventually end up here.  */
+/* Implement the to_stop function for the remote targets.  */
 
 static void
 remote_stop (struct target_ops *self, ptid_t ptid)
@@ -5100,7 +5099,29 @@ remote_stop (struct target_ops *self, ptid_t ptid)
   if (non_stop)
     remote_stop_ns (ptid);
   else
-    remote_stop_as (ptid);
+    {
+      /* We don't currently have a way to transparently pause the
+	 remote target in all-stop mode.  Interrupt it instead.  */
+      remote_interrupt_as (ptid);
+    }
+}
+
+/* Implement the to_interrupt function for the remote targets.  */
+
+static void
+remote_interrupt (struct target_ops *self, ptid_t ptid)
+{
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n");
+
+  if (non_stop)
+    {
+      /* We don't currently have a way to ^C the remote target in
+	 non-stop mode.  Stop it (with no signal) instead.  */
+      remote_stop_ns (ptid);
+    }
+  else
+    remote_interrupt_as (ptid);
 }
 
 /* Ask the user what to do when an interrupt is received.  */
@@ -11700,6 +11721,7 @@ Specify the serial device it is connected to\n\
   remote_ops.to_extra_thread_info = remote_threads_extra_info;
   remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;
   remote_ops.to_stop = remote_stop;
+  remote_ops.to_interrupt = remote_interrupt;
   remote_ops.to_xfer_partial = remote_xfer_partial;
   remote_ops.to_rcmd = remote_rcmd;
   remote_ops.to_log_command = serial_log_command;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 8a92acf..054ad32 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -1537,6 +1537,30 @@ debug_stop (struct target_ops *self, ptid_t arg1)
 }
 
 static void
+delegate_interrupt (struct target_ops *self, ptid_t arg1)
+{
+  self = self->beneath;
+  self->to_interrupt (self, arg1);
+}
+
+static void
+tdefault_interrupt (struct target_ops *self, ptid_t arg1)
+{
+}
+
+static void
+debug_interrupt (struct target_ops *self, ptid_t arg1)
+{
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_interrupt (...)\n", debug_target.to_shortname);
+  debug_target.to_interrupt (&debug_target, arg1);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_interrupt (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_ptid_t (arg1);
+  fputs_unfiltered (")\n", gdb_stdlog);
+}
+
+static void
 delegate_rcmd (struct target_ops *self, const char *arg1, struct ui_file *arg2)
 {
   self = self->beneath;
@@ -4016,6 +4040,8 @@ install_delegators (struct target_ops *ops)
     ops->to_thread_name = delegate_thread_name;
   if (ops->to_stop == NULL)
     ops->to_stop = delegate_stop;
+  if (ops->to_interrupt == NULL)
+    ops->to_interrupt = delegate_interrupt;
   if (ops->to_rcmd == NULL)
     ops->to_rcmd = delegate_rcmd;
   if (ops->to_pid_to_exec_file == NULL)
@@ -4253,6 +4279,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_extra_thread_info = tdefault_extra_thread_info;
   ops->to_thread_name = tdefault_thread_name;
   ops->to_stop = tdefault_stop;
+  ops->to_interrupt = tdefault_interrupt;
   ops->to_rcmd = default_rcmd;
   ops->to_pid_to_exec_file = tdefault_pid_to_exec_file;
   ops->to_log_command = tdefault_log_command;
@@ -4402,6 +4429,7 @@ init_debug_target (struct target_ops *ops)
   ops->to_extra_thread_info = debug_extra_thread_info;
   ops->to_thread_name = debug_thread_name;
   ops->to_stop = debug_stop;
+  ops->to_interrupt = debug_interrupt;
   ops->to_rcmd = debug_rcmd;
   ops->to_pid_to_exec_file = debug_pid_to_exec_file;
   ops->to_log_command = debug_log_command;
diff --git a/gdb/target.c b/gdb/target.c
index ab6c977..2262131 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3244,6 +3244,18 @@ target_stop (ptid_t ptid)
   (*current_target.to_stop) (&current_target, ptid);
 }
 
+void
+target_interrupt (ptid_t ptid)
+{
+  if (!may_stop)
+    {
+      warning (_("May not interrupt or stop the target, ignoring attempt"));
+      return;
+    }
+
+  (*current_target.to_interrupt) (&current_target, ptid);
+}
+
 /* See target/target.h.  */
 
 void
diff --git a/gdb/target.h b/gdb/target.h
index 2663db5..6c57a69 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -606,6 +606,8 @@ struct target_ops
       TARGET_DEFAULT_RETURN (NULL);
     void (*to_stop) (struct target_ops *, ptid_t)
       TARGET_DEFAULT_IGNORE ();
+    void (*to_interrupt) (struct target_ops *, ptid_t)
+      TARGET_DEFAULT_IGNORE ();
     void (*to_rcmd) (struct target_ops *,
 		     const char *command, struct ui_file *output)
       TARGET_DEFAULT_FUNC (default_rcmd);
@@ -1630,6 +1632,12 @@ extern void target_update_thread_list (void);
 
 extern void target_stop (ptid_t ptid);
 
+/* Interrupt the target just like the user typed a ^C on the
+   inferior's controlling terminal.  (For instance, under Unix, this
+   should act like SIGINT).  This function is asynchronous.  */
+
+extern void target_interrupt (ptid_t ptid);
+
 /* Send the specified COMMAND to the target's monitor
    (shell,interpreter) for execution.  The result of the query is
    placed in OUTBUF.  */
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index fd31083..46a378c 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -162,7 +162,7 @@ static int windows_initialization_done;
 #define DEBUG_MEM(x)	if (debug_memory)	printf_unfiltered x
 #define DEBUG_EXCEPT(x)	if (debug_exceptions)	printf_unfiltered x
 
-static void windows_stop (struct target_ops *self, ptid_t);
+static void windows_interrupt (struct target_ops *self, ptid_t);
 static int windows_thread_alive (struct target_ops *, ptid_t);
 static void windows_kill_inferior (struct target_ops *);
 
@@ -2294,7 +2294,7 @@ windows_mourn_inferior (struct target_ops *ops)
    ^C on the controlling terminal.  */
 
 static void
-windows_stop (struct target_ops *self, ptid_t ptid)
+windows_interrupt (struct target_ops *self, ptid_t ptid)
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
@@ -2488,7 +2488,7 @@ windows_target (void)
   t->to_mourn_inferior = windows_mourn_inferior;
   t->to_thread_alive = windows_thread_alive;
   t->to_pid_to_str = windows_pid_to_str;
-  t->to_stop = windows_stop;
+  t->to_interrupt = windows_interrupt;
   t->to_pid_to_exec_file = windows_pid_to_exec_file;
   t->to_get_ada_task_ptid = windows_get_ada_task_ptid;
   t->to_get_tib_address = windows_get_tib_address;
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (16 preceding siblings ...)
  2015-04-07 12:55 ` [PATCH v2 17/23] Fix interrupt-noterm.exp on targets always in non-stop Pedro Alves
@ 2015-04-07 12:57 ` Pedro Alves
  2015-04-10 14:54   ` Pedro Alves
  2015-04-07 12:59 ` [PATCH v2 07/23] Embed the pending step-over chain in thread_info objects Pedro Alves
                   ` (6 subsequent siblings)
  24 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:57 UTC (permalink / raw)
  To: gdb-patches

These tests exercise the infrun.c:proceed code that needs to know to
start new step overs (along with switch_back_to_stepped_thread, etc.).
That code is tricky to get right in the multitude of possible
combinations (at least):

 (native | remote)
  X (all-stop | all-stop-but-target-always-in-non-stop)
  X (displaced-stepping | in-line step-over).

The first two above are properties of the target, but the different
step-over-breakpoint methods should work with any target that supports
them.  This patch makes sure we always test both methods on all
targets.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): New
	procedure, factored out from ...
	(top level): ... here.  Add "set displaced-stepping" testing axis.
	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): New
	parameter "displaced".  Use it.
	(top level): Use foreach and add "set displaced-stepping" testing
	axis.
---
 .../gdb.threads/step-over-lands-on-breakpoint.exp    | 18 +++++++++++++++---
 .../gdb.threads/step-over-trips-on-watchpoint.exp    | 20 +++++++++++++-------
 2 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
index 1e12314..4d27059 100644
--- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
@@ -24,15 +24,20 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
     return -1
 }
 
-# Cover both stepping and non-stepping execution commands.
-foreach command {"step" "next" "continue" } {
-    with_test_prefix $command {
+# The test proper.  DISPLACED is true if we should try with displaced
+# stepping.  COMMAND is the execution command to test.
+proc do_test {displaced command} {
+    global executable
+
+    with_test_prefix "displaced=$displaced: $command" {
 	clean_restart $executable
 
 	if ![runto_main] {
 	    continue
 	}
 
+	gdb_test_no_output "set displaced-stepping $displaced"
+
 	gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"]
 	gdb_continue_to_breakpoint "run to wait-thread breakpoint"
 	gdb_test "info threads" "2 .*\\\* 1.*" "info threads shows all threads"
@@ -60,3 +65,10 @@ foreach command {"step" "next" "continue" } {
 	gdb_test "$command" "step-over here.*"
     }
 }
+
+foreach displaced { "off" "on" } {
+    # Cover both stepping and non-stepping execution commands.
+    foreach command { "step" "next" "continue" } {
+	do_test $displaced $command
+    }
+}
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
index b8fc6a8..7a0fb79 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
@@ -31,7 +31,11 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
     return -1
 }
 
-proc do_test { with_bp } {
+# The test proper.  DISPLACED is true if we should try with displaced
+# stepping.  WITH_BP is true if we should try with a thread-specific
+# breakpoint (for the wrong thread) right after the instruction that
+# triggers the watchpoint.
+proc do_test { displaced with_bp } {
     global executable
 
     if ${with_bp} {
@@ -39,7 +43,7 @@ proc do_test { with_bp } {
     } else {
 	set prefix "no thread-specific bp"
     }
-    with_test_prefix $prefix {
+    with_test_prefix "displaced=$displaced: $prefix" {
 	# Cover both stepping and non-stepping execution commands.
 	foreach command {"step" "next" "continue" } {
 	    with_test_prefix $command {
@@ -49,6 +53,8 @@ proc do_test { with_bp } {
 		    continue
 		}
 
+		gdb_test_no_output "set displaced-stepping $displaced"
+
 		gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"]
 		gdb_continue_to_breakpoint "run to wait-thread breakpoint"
 		gdb_test "info threads" "2 .*\\\* 1.*" "info threads shows all threads"
@@ -65,9 +71,6 @@ proc do_test { with_bp } {
 		gdb_test "watch watch_me" "Hardware watchpoint .*"
 
 		if ${with_bp} {
-		    # Set a thread-specific breakpoint (for the wrong
-		    # thread) right after instruction that triggers
-		    # the watchpoint.
 		    set linenum [gdb_get_line_number "set thread-specific breakpoint here"]
 		    gdb_test "b $linenum thread 1"
 		}
@@ -86,5 +89,8 @@ proc do_test { with_bp } {
     }
 }
 
-do_test 0
-do_test 1
+foreach displaced { "off" "on" } {
+    foreach with_bp { 0 1 } {
+	do_test $displaced $with_bp
+    }
+}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 13/23] Factor out code to re-resume stepped thread
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (18 preceding siblings ...)
  2015-04-07 12:59 ` [PATCH v2 07/23] Embed the pending step-over chain in thread_info objects Pedro Alves
@ 2015-04-07 12:59 ` Pedro Alves
  2015-04-07 12:59 ` [PATCH v2 14/23] Teach non-stop to do in-line step-overs (stop all, step, restart) Pedro Alves
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:59 UTC (permalink / raw)
  To: gdb-patches

Just a code refactor, no funcionality change intended.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (keep_going_stepped_thread): New function, factored out
	from ...
	(switch_back_to_stepped_thread): ... here.
---
 gdb/infrun.c | 198 ++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 106 insertions(+), 92 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 87bbe03..f24e8d7 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1879,6 +1879,7 @@ reset_ecs (struct execution_control_state *ecs, struct thread_info *tp)
 
 static void keep_going_pass (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
+static int keep_going_stepped_thread (struct thread_info *tp);
 static int thread_still_needs_step_over (struct thread_info *tp);
 
 /* Are there any pending step-over requests for INF?  If so, run one
@@ -5753,110 +5754,123 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
       if (stepping_thread != NULL)
 	{
-	  struct frame_info *frame;
-	  struct gdbarch *gdbarch;
-
-	  tp = stepping_thread;
-
-	  /* If the stepping thread exited, then don't try to switch
-	     back and resume it, which could fail in several different
-	     ways depending on the target.  Instead, just keep going.
-
-	     We can find a stepping dead thread in the thread list in
-	     two cases:
-
-	     - The target supports thread exit events, and when the
-	     target tries to delete the thread from the thread list,
-	     inferior_ptid pointed at the exiting thread.  In such
-	     case, calling delete_thread does not really remove the
-	     thread from the list; instead, the thread is left listed,
-	     with 'exited' state.
-
-	     - The target's debug interface does not support thread
-	     exit events, and so we have no idea whatsoever if the
-	     previously stepping thread is still alive.  For that
-	     reason, we need to synchronously query the target
-	     now.  */
-	  if (is_exited (tp->ptid)
-	      || !target_thread_alive (tp->ptid))
-	    {
-	      if (debug_infrun)
-		fprintf_unfiltered (gdb_stdlog,
-				    "infrun: not switching back to "
-				    "stepped thread, it has vanished\n");
-
-	      delete_thread (tp->ptid);
-	      return 0;
-	    }
-
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog,
 				"infrun: switching back to stepped thread\n");
 
-	  reset_ecs (ecs, tp);
-	  switch_to_thread (tp->ptid);
+	  if (keep_going_stepped_thread (stepping_thread))
+	    {
+	      prepare_to_wait (ecs);
+	      return 1;
+	    }
+	}
+    }
 
-	  stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
-	  frame = get_current_frame ();
-	  gdbarch = get_frame_arch (frame);
+  return 0;
+}
 
-	  /* If the PC of the thread we were trying to single-step has
-	     changed, then that thread has trapped or been signaled,
-	     but the event has not been reported to GDB yet.  Re-poll
-	     the target looking for this particular thread's event
-	     (i.e. temporarily enable schedlock) by:
+/* Set a previously stepped thread back to stepping.  Returns true on
+   success, false if the resume is not possible (e.g., the thread
+   vanished).  */
+
+static int
+keep_going_stepped_thread (struct thread_info *tp)
+{
+  struct frame_info *frame;
+  struct gdbarch *gdbarch;
+  struct execution_control_state ecss;
+  struct execution_control_state *ecs = &ecss;
 
-	       - setting a break at the current PC
-	       - resuming that particular thread, only (by setting
-		 trap expected)
+  /* If the stepping thread exited, then don't try to switch back and
+     resume it, which could fail in several different ways depending
+     on the target.  Instead, just keep going.
 
-	     This prevents us continuously moving the single-step
-	     breakpoint forward, one instruction at a time,
-	     overstepping.  */
+     We can find a stepping dead thread in the thread list in two
+     cases:
 
-	  if (stop_pc != tp->prev_pc)
-	    {
-	      ptid_t resume_ptid;
+     - The target supports thread exit events, and when the target
+       tries to delete the thread from the thread list, inferior_ptid
+       pointed at the exiting thread.  In such case, calling
+       delete_thread does not really remove the thread from the list;
+       instead, the thread is left listed, with 'exited' state.
 
-	      if (debug_infrun)
-		fprintf_unfiltered (gdb_stdlog,
-				    "infrun: expected thread advanced also "
-				    "(%s -> %s)\n",
-				    paddress (target_gdbarch (), tp->prev_pc),
-				    paddress (target_gdbarch (), stop_pc));
-
-	      /* Clear the info of the previous step-over, as it's no
-		 longer valid (if the thread was trying to step over a
-		 breakpoint, it has already succeeded).  It's what
-		 keep_going would do too, if we called it.  Do this
-		 before trying to insert the sss breakpoint, otherwise
-		 if we were previously trying to step over this exact
-		 address in another thread, the breakpoint is
-		 skipped.  */
-	      clear_step_over_info ();
-	      tp->control.trap_expected = 0;
-
-	      insert_single_step_breakpoint (get_frame_arch (frame),
-					     get_frame_address_space (frame),
-					     stop_pc);
-
-	      resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
-	      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
-	      prepare_to_wait (ecs);
-	    }
-	  else
-	    {
-	      if (debug_infrun)
-		fprintf_unfiltered (gdb_stdlog,
-				    "infrun: expected thread still "
-				    "hasn't advanced\n");
-	      keep_going_pass (ecs);
-	    }
+       - The target's debug interface does not support thread exit
+         events, and so we have no idea whatsoever if the previously
+         stepping thread is still alive.  For that reason, we need to
+         synchronously query the target now.  */
 
-	  return 1;
-	}
+  if (is_exited (tp->ptid)
+      || !target_thread_alive (tp->ptid))
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: not resuming previously  "
+			    "stepped thread, it has vanished\n");
+
+      delete_thread (tp->ptid);
+      return 0;
     }
-  return 0;
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+			"infrun: resuming previously stepped thread\n");
+
+  reset_ecs (ecs, tp);
+  switch_to_thread (tp->ptid);
+
+  stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
+  frame = get_current_frame ();
+  gdbarch = get_frame_arch (frame);
+
+  /* If the PC of the thread we were trying to single-step has
+     changed, then that thread has trapped or been signaled, but the
+     event has not been reported to GDB yet.  Re-poll the target
+     looking for this particular thread's event (i.e. temporarily
+     enable schedlock) by:
+
+     - setting a break at the current PC
+     - resuming that particular thread, only (by setting trap
+     expected)
+
+     This prevents us continuously moving the single-step breakpoint
+     forward, one instruction at a time, overstepping.  */
+
+  if (stop_pc != tp->prev_pc)
+    {
+      ptid_t resume_ptid;
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: expected thread advanced also (%s -> %s)\n",
+			    paddress (target_gdbarch (), tp->prev_pc),
+			    paddress (target_gdbarch (), stop_pc));
+
+      /* Clear the info of the previous step-over, as it's no longer
+	 valid (if the thread was trying to step over a breakpoint, it
+	 has already succeeded).  It's what keep_going would do too,
+	 if we called it.  Do this before trying to insert the sss
+	 breakpoint, otherwise if we were previously trying to step
+	 over this exact address in another thread, the breakpoint is
+	 skipped.  */
+      clear_step_over_info ();
+      tp->control.trap_expected = 0;
+
+      insert_single_step_breakpoint (get_frame_arch (frame),
+				     get_frame_address_space (frame),
+				     stop_pc);
+
+      resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+    }
+  else
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: expected thread still hasn't advanced\n");
+
+      keep_going_pass (ecs);
+    }
+  return 1;
 }
 
 /* Is thread TP in the middle of single-stepping?  */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 07/23] Embed the pending step-over chain in thread_info objects
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (17 preceding siblings ...)
  2015-04-07 12:57 ` [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping Pedro Alves
@ 2015-04-07 12:59 ` Pedro Alves
  2015-04-07 12:59 ` [PATCH v2 13/23] Factor out code to re-resume stepped thread Pedro Alves
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:59 UTC (permalink / raw)
  To: gdb-patches

In order to teach non-stop mode to do in-line step-overs (pause all
threads, remove breakpoint, single-step, reinsert breakpoint, restart
threads), we'll need to be able to queue in-line step over requests,
much like we queue displaced stepping (out-of-line) requests.
Actually, the queue should be the same -- threads wait for their turn
to step past something (breakpoint, watchpoint), doesn't matter what
technique we end up using when the step over actually starts.

I found that the queue management ends up simpler and more efficient
if embedded in the thread objects themselves.  This commit converts
the existing displaced stepping queue to that.  Later patches will
make the in-line step-overs code paths use it too.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdbthread.h (struct thread_info) <step_over_prev,
	step_over_next>: New fields.
	(thread_step_over_chain_enqueue, thread_step_over_chain_remove)
	(inferior_step_over_chain_remove_all, step_over_chain_dequeue):
	New declarations.
	* inferior.h (struct inferior) <step_over_queue_head>: New field.
	* infrun.c (struct displaced_step_request): Delete.
	(struct displaced_step_inferior_state) <step_request_queue>:
	Delete field.
	(displaced_step_in_progress): New function.
	(displaced_step_prepare): Assert that trap_expected is set.  Use
	thread_step_over_chain_enqueue.  Split starting a new displaced
	stepping to ...
	(start_step_over_inferior): ... this new function.
	(start_step_over): New function.
	(infrun_thread_ptid_changed): Delete references to the old
	displaced step request queue.
	(proceed): Assert the thread isn't waiting for a step over
	already.
	(infrun_thread_stop_requested): Adjust to remove threads from the
	embedded step-over chain.
	(handle_inferior_event) <fork/vfork>: Call start_step_over after
	displaced_step_fixup.
	(handle_signal_stop): Call start_step_over after
	displaced_step_fixup.
	* thread.c (step_over_chain_enqueue, step_over_chain_remove)
	(step_over_chain_dequeue, thread_step_over_chain_enqueue)
	(thread_step_over_chain_remove)
	(inferior_step_over_chain_remove_all): New function.
	(delete_thread_1): Remove thread from the step-over chain.
---
 gdb/gdbthread.h |  20 +++++++++
 gdb/inferior.h  |   4 ++
 gdb/infrun.c    | 128 +++++++++++++++++++++++++++++---------------------------
 gdb/thread.c    |  93 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 184 insertions(+), 61 deletions(-)

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index bb15717..e654432 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -285,6 +285,10 @@ struct thread_info
   /* Values that are stored as temporaries on stack while evaluating
      expressions.  */
   value_vec *stack_temporaries;
+
+  /* Step-over chain.  */
+  struct thread_info *step_over_prev;
+  struct thread_info *step_over_next;
 };
 
 /* Create an empty thread list, or empty the existing one.  */
@@ -498,6 +502,22 @@ extern struct value *get_last_thread_stack_temporary (ptid_t);
 
 extern int value_in_thread_stack_temporaries (struct value *, ptid_t);
 
+/* Add TP to the end of its inferior's pending step-over chain.  */
+
+extern void thread_step_over_chain_enqueue (struct thread_info *tp);
+
+/* Remove TP from its inferior's pending step-over chain.  */
+
+extern void thread_step_over_chain_remove (struct thread_info *tp);
+
+/* Remove all threads from inferior INF's pending step-over chain.  */
+
+extern void inferior_step_over_chain_remove_all (struct inferior *inf);
+
+/* Remove the head of LIST_P, a pending step-over chain.  */
+
+extern void step_over_chain_dequeue (struct thread_info **list_p);
+
 extern struct thread_info *thread_list;
 
 #endif /* GDBTHREAD_H */
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 2530777..3cec101 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -410,6 +410,10 @@ struct inferior
      this gdbarch.  */
   struct gdbarch *gdbarch;
 
+  /* The queue of this inferior's threads that need to do a step-over
+     operation to get past e.g., a breakpoint.  */
+  struct thread_info *step_over_queue_head;
+
   /* Per inferior data-pointers required by other GDB modules.  */
   REGISTRY_FIELDS;
 };
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c544362..937a29d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1406,12 +1406,6 @@ step_over_info_valid_p (void)
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_fixup for details.  */
 
-struct displaced_step_request
-{
-  ptid_t ptid;
-  struct displaced_step_request *next;
-};
-
 /* Per-inferior displaced stepping state.  */
 struct displaced_step_inferior_state
 {
@@ -1421,10 +1415,6 @@ struct displaced_step_inferior_state
   /* The process this displaced step state refers to.  */
   int pid;
 
-  /* A queue of pending displaced stepping requests.  One entry per
-     thread that needs to do a displaced step.  */
-  struct displaced_step_request *step_request_queue;
-
   /* If this is not null_ptid, this is the thread carrying out a
      displaced single-step in process PID.  This thread's state will
      require fixing up once it has completed its step.  */
@@ -1674,6 +1664,9 @@ displaced_step_prepare (ptid_t ptid)
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
+  /* Nor if the thread isn't meant to step over a breakpoint.  */
+  gdb_assert (tp->control.trap_expected);
+
   /* Disable range stepping while executing in the scratch pad.  We
      want a single-step even if executing the displaced instruction in
      the scratch buffer lands within the stepping range (e.g., a
@@ -1689,28 +1682,13 @@ displaced_step_prepare (ptid_t ptid)
     {
       /* Already waiting for a displaced step to finish.  Defer this
 	 request and place in queue.  */
-      struct displaced_step_request *req, *new_req;
 
       if (debug_displaced)
 	fprintf_unfiltered (gdb_stdlog,
-			    "displaced: defering step of %s\n",
+			    "displaced: deferring step of %s\n",
 			    target_pid_to_str (ptid));
 
-      new_req = xmalloc (sizeof (*new_req));
-      new_req->ptid = ptid;
-      new_req->next = NULL;
-
-      if (displaced->step_request_queue)
-	{
-	  for (req = displaced->step_request_queue;
-	       req && req->next;
-	       req = req->next)
-	    ;
-	  req->next = new_req;
-	}
-      else
-	displaced->step_request_queue = new_req;
-
+      thread_step_over_chain_enqueue (tp);
       return 0;
     }
   else
@@ -1856,24 +1834,34 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
   do_cleanups (old_cleanups);
 
   displaced->step_ptid = null_ptid;
+}
+
+/* Are there any pending step-over requests for INF?  */
 
-  /* Are there any pending displaced stepping requests?  If so, run
-     one now.  Leave the state object around, since we're likely to
-     need it again soon.  */
-  while (displaced->step_request_queue)
+static void
+start_step_over_inferior (struct inferior *inf)
+{
+  /* Don't start a new step-over if we already have a displaced step
+     operation ongoing.  */
+  if (displaced_step_in_progress (inf->pid))
+    return;
+
+  while (inf->step_over_queue_head != NULL)
     {
-      struct displaced_step_request *head;
       ptid_t ptid;
+      struct displaced_step_inferior_state *displaced;
       struct regcache *regcache;
       struct gdbarch *gdbarch;
       CORE_ADDR actual_pc;
       struct address_space *aspace;
+      struct thread_info *tp;
+
+      tp = inf->step_over_queue_head;
+      displaced = get_displaced_stepping_state (inf->pid);
 
-      head = displaced->step_request_queue;
-      ptid = head->ptid;
-      displaced->step_request_queue = head->next;
-      xfree (head);
+      step_over_chain_dequeue (&inf->step_over_queue_head);
 
+      ptid = tp->ptid;
       context_switch (ptid);
 
       regcache = get_thread_regcache (ptid);
@@ -1935,6 +1923,25 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 	     thread waiting for its turn.  */
 	}
     }
+
+  if (inf->step_over_queue_head == NULL)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: step-over queue of process %d now empty\n",
+			    inf->pid);
+    }
+}
+
+/* Are there any pending step-over requests for the inferior of
+   EVENT_PTID?  */
+
+static void
+start_step_over (ptid_t event_ptid)
+{
+  struct inferior *inf = find_inferior_ptid (event_ptid);
+
+  start_step_over_inferior (inf);
 }
 
 /* Update global variables holding ptids to hold NEW_PTID if they were
@@ -1954,10 +1961,6 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
     {
       if (ptid_equal (displaced->step_ptid, old_ptid))
 	displaced->step_ptid = new_ptid;
-
-      for (it = displaced->step_request_queue; it; it = it->next)
-	if (ptid_equal (it->ptid, old_ptid))
-	  it->ptid = new_ptid;
     }
 }
 
@@ -2664,6 +2667,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   /* Fill in with reasonable starting values.  */
   init_thread_stepping_state (tp);
 
+  gdb_assert (tp->step_over_next == NULL);
+  gdb_assert (tp->step_over_prev == NULL);
+
   if (addr == (CORE_ADDR) -1)
     {
       if (pc == stop_pc
@@ -2971,35 +2977,31 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
 static void
 infrun_thread_stop_requested (ptid_t ptid)
 {
-  struct displaced_step_inferior_state *displaced;
-
   /* PTID was requested to stop.  Remove it from the displaced
      stepping queue, so we don't try to resume it automatically.  */
 
-  for (displaced = displaced_step_inferior_states;
-       displaced;
-       displaced = displaced->next)
+  if (ptid_equal (minus_one_ptid, ptid))
     {
-      struct displaced_step_request *it, **prev_next_p;
+      struct inferior *inf;
 
-      it = displaced->step_request_queue;
-      prev_next_p = &displaced->step_request_queue;
-      while (it)
+      ALL_INFERIORS (inf)
 	{
-	  if (ptid_match (it->ptid, ptid))
-	    {
-	      *prev_next_p = it->next;
-	      it->next = NULL;
-	      xfree (it);
-	    }
-	  else
-	    {
-	      prev_next_p = &it->next;
-	    }
-
-	  it = *prev_next_p;
+	  inferior_step_over_chain_remove_all (inf);
 	}
     }
+  else if (ptid_is_pid (ptid))
+    {
+      struct inferior *inf = find_inferior_ptid (ptid);
+
+      inferior_step_over_chain_remove_all (inf);
+    }
+  else
+    {
+      struct thread_info *tp = find_thread_ptid (ptid);
+
+      if (tp->step_over_next != NULL)
+	thread_step_over_chain_remove (tp);
+    }
 
   iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
 }
@@ -4050,6 +4052,9 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 	       that this operation also cleans up the child process for vfork,
 	       because their pages are shared.  */
 	    displaced_step_fixup (ecs->ptid, GDB_SIGNAL_TRAP);
+	    /* Start a new step-over in another thread if there's one
+	       that needs it.  */
+	    start_step_over (ecs->ptid);
 
 	    if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
 	      {
@@ -4282,6 +4287,7 @@ handle_signal_stop (struct execution_control_state *ecs)
      the PC, so do it here, before we set stop_pc.)  */
   displaced_step_fixup (ecs->ptid,
 			ecs->event_thread->suspend.stop_signal);
+  start_step_over (ecs->ptid);
 
   /* If we either finished a single-step or hit a breakpoint, but
      the user wanted this thread to be stopped, pretend we got a
diff --git a/gdb/thread.c b/gdb/thread.c
index db631c9..d5c9896 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -307,6 +307,95 @@ add_thread (ptid_t ptid)
   return add_thread_with_info (ptid, NULL);
 }
 
+/* Add TP to the end of the step-over chain LIST_P.  */
+
+static void
+step_over_chain_enqueue (struct thread_info **list_p, struct thread_info *tp)
+{
+  gdb_assert (tp->step_over_next == NULL);
+  gdb_assert (tp->step_over_prev == NULL);
+
+  if (*list_p == NULL)
+    {
+      *list_p = tp;
+      tp->step_over_prev = tp->step_over_next = tp;
+    }
+  else
+    {
+      struct thread_info *head = *list_p;
+      struct thread_info *tail = head->step_over_prev;
+
+      tp->step_over_prev = tail;
+      tp->step_over_next = head;
+      head->step_over_prev = tp;
+      tail->step_over_next = tp;
+    }
+}
+
+/* Remove TP from step-over chain LIST_P.  */
+
+static void
+step_over_chain_remove (struct thread_info **list_p, struct thread_info *tp)
+{
+  gdb_assert (tp->step_over_next != NULL);
+  gdb_assert (tp->step_over_prev != NULL);
+
+  if (*list_p == tp)
+    {
+      if (tp == tp->step_over_next)
+	*list_p = NULL;
+      else
+	*list_p = tp->step_over_next;
+    }
+
+  tp->step_over_prev->step_over_next = tp->step_over_next;
+  tp->step_over_next->step_over_prev = tp->step_over_prev;
+  tp->step_over_prev = tp->step_over_next = NULL;
+}
+
+/* See gdbthread.h.  */
+
+void
+step_over_chain_dequeue (struct thread_info **list_p)
+{
+  step_over_chain_remove (list_p, *list_p);
+}
+
+/* See gdbthread.h.  */
+
+void
+thread_step_over_chain_enqueue (struct thread_info *tp)
+{
+  struct inferior *inf;
+
+  inf = find_inferior_ptid (tp->ptid);
+  gdb_assert (inf != NULL);
+
+  step_over_chain_enqueue (&inf->step_over_queue_head, tp);
+}
+
+/* See gdbthread.h.  */
+
+void
+thread_step_over_chain_remove (struct thread_info *tp)
+{
+  struct inferior *inf;
+
+  inf = find_inferior_ptid (tp->ptid);
+  gdb_assert (inf != NULL);
+
+  step_over_chain_remove (&inf->step_over_queue_head, tp);
+}
+
+/* See gdbthread.h.  */
+
+void
+inferior_step_over_chain_remove_all (struct inferior *inf)
+{
+  while (inf->step_over_queue_head != NULL)
+    step_over_chain_dequeue (&inf->step_over_queue_head);
+}
+
 /* Delete thread PTID.  If SILENT, don't notify the observer of this
    exit.  */
 static void
@@ -323,6 +412,10 @@ delete_thread_1 (ptid_t ptid, int silent)
   if (!tp)
     return;
 
+  /* Dead threads don't need to step-over.  Remove from queue.  */
+  if (tp->step_over_next != NULL)
+    thread_step_over_chain_remove (tp);
+
   /* If this is the current thread, or there's code out there that
      relies on it existing (refcount > 0) we can't delete yet.  Mark
      it as exited, and notify it.  */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 14/23] Teach non-stop to do in-line step-overs (stop all, step, restart)
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (19 preceding siblings ...)
  2015-04-07 12:59 ` [PATCH v2 13/23] Factor out code to re-resume stepped thread Pedro Alves
@ 2015-04-07 12:59 ` Pedro Alves
  2015-04-07 13:30 ` [PATCH v2 18/23] Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race Pedro Alves
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 12:59 UTC (permalink / raw)
  To: gdb-patches

That is, step past breakpoints by:

 - pausing all threads
 - removing breakpoint at PC
 - single-step
 - reinsert breakpoint
 - restart threads

similarly to all-stop (with displaced stepping disabled).  This allows
non-stop to work on targets/architectures without displaced stepping
support.  That is, it makes displaced stepping an optimization instead
of a requirement.  For example, in principle, all GNU/Linux ports
support non-stop mode at the target_ops level, but not all
corresponding gdbarch's implement displaced stepping.  This should
make non-stop work for all (albeit, not as efficiently).  And then
there are scenarios where even if the architecture supports displaced
stepping, we can't use it, because we e.g., don't find a usable
address to use as displaced step scratch pad.  It should also fix
stepping past watchpoints on targets that have non-continuable
watchpoints in non-stop mode (e.g., PPC, untested).  Running the
instruction out of line in the displaced stepping scratch pad doesn't
help that case, as the copied instruction reads/writes the same
watched memory...  We can fix that too by teaching GDB to only remove
the watchpoint from the thread that we want to move past the
watchpoint (currently, removing a watchpoint always removes it from
all threads), but again, that can be considered an optimization; not
all targets would support it.

For those familiar with the gdb and gdbserver Linux target_ops
backends, the implementation should look similar, except it is done on
the core side.  When we pause threads, we may find they stop with an
interesting event that should be handled later when the thread is
re-resumed, thus we store such events in the thread object, and mark
the event as pending.  We should only consume pending events if the
thread is indeed resumed, thus we add a new "resumed" flag to the
thread object. At a later stage, we might add new target methods to
accelerate some of this, like "pause all threads", with corresponding
RSP packets, but we'd still need a fallback method for remote targets
that don't support such packets, so, again, that can be deferred as
optimization.

My _real_ motivation here is making it possible to reimplement
all-stop mode on top of the target always working on non-stop mode, so
that e.g., we can send RSP packets to a remote target even while the
target is running -- can't do that in the all-stop RSP variant, by
design).

Tested on x86_64 Fedora 20, with and without "set displaced off"
forced.  The latter forces the new code paths whenever GDB needs to
step past a breakpoint.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <pedro@codesourcery.com>

	* breakpoint.c (breakpoints_should_be_inserted_now): If any thread
	has a pending status, return true.
	* gdbthread.h: Include target/waitstatus.h.
	(struct thread_suspend_state) <stop_reason, waitstatus_pending_p,
	stop_pc>: New fields.
	(struct thread_info) <resumed>: New field.
	(set_resumed): Delare.
	* infrun.c: Include "event-loop.h".
	(infrun_async_inferior_event_token, infrun_is_async): New globals.
	(infrun_async): New function.
	(clear_step_over_info): Add debug output.
	(displaced_step_fixup): New returns int.
	(start_step_over_inferior): Also check step_over_info_valid_p.
	Also make sure the thread isn't resumed.
	(resume_cleanups): Clear the thread's resumed flag.
	(resume): Set the thread's resumed flag.  Return early if the
	thread has a pending status.  Allow stepping a breakpoint with no
	signal.
	(clear_proceed_status_thread): If the thread has a pending status,
	and that status is a finished step, discard the pending status.
	(clear_proceed_status): Don't clear step_over_info here.
	(random_pending_event_thread, do_target_wait): New functions.
	(prepare_for_detach, wait_for_inferior, fetch_inferior_event): Use
	do_target_wait.
	(wait_one): New function.
	(THREAD_STOPPED_BY): New macro.
	(thread_stopped_by_watchpoint, thread_stopped_by_sw_breakpoint)
	(thread_stopped_by_hw_breakpoint): New functions.
	(switch_to_thread_cleanup, stop_all_threads): New functions.
	(handle_inferior_event): Also call set_resumed(false) on all
	threads implicitly stopped by the event.
	(restart_threads): New function.
	(finish_step_over): If we were doing an in-line step-over before,
	and no longer are after trying to start a new step-over, restart
	all threads.
	(handle_signal_stop) <random signal>: Clear step_over_info before
	delivering the signal.
	(keep_going_stepped_thread): Return early if the thread has a
	pending status.  Mark the thread as resumed.
	(keep_going_pass): Assert the thread isn't resumed.  If some other
	thread is doing an in-line step-over, defer the resume.  If we
	just started a new in-line step-over, stop all threads.
	(infrun_async_inferior_event_handler): New function.
	(_initialize_infrun): Create async event handler with
	infrun_async_inferior_event_handler as callback.
	(infrun_async): New declaration.
	* target.c (target_async): New function.
	* target.h (target_async): Declare macro and readd as function
	declaration.
	* target/waitstatus.h (enum target_stop_reason)
	<TARGET_STOPPED_BY_SINGLE_STEP>: New value.
	* thread.c (new_thread): Clear the new waitstatus field.
	(set_resumed): New function.

-v2

  - `proceed' changes dropped.  no longer needed after fix to previous patch.
  - "infrun.c" -> "infrun" in debug output.
  - clear trap_expected when displaced_step_fixup returns -1, when
    stopping threads (as the step-over was cancelled).  Testing on
    PPC64 caught this was missing ("inconsistent state" internal error
    in start_step_over_inferior).
---
 gdb/breakpoint.c        |   9 +
 gdb/gdbthread.h         |  31 ++
 gdb/infrun.c            | 878 +++++++++++++++++++++++++++++++++++++++++++++---
 gdb/infrun.h            |   3 +
 gdb/target.c            |   9 +
 gdb/target.h            |   3 +-
 gdb/target/waitstatus.h |   5 +-
 gdb/thread.c            |  23 ++
 8 files changed, 912 insertions(+), 49 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 12955cb..76c86f8 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -468,6 +468,8 @@ breakpoints_should_be_inserted_now (void)
     }
   else if (target_has_execution)
     {
+      struct thread_info *tp;
+
       if (always_inserted_mode)
 	{
 	  /* The user wants breakpoints inserted even if all threads
@@ -477,6 +479,13 @@ breakpoints_should_be_inserted_now (void)
 
       if (threads_are_executing ())
 	return 1;
+
+      /* Don't remove breakpoints yet if, even though all threads are
+	 stopped, we still have events to process.  */
+      ALL_NON_EXITED_THREADS (tp)
+	if (tp->resumed
+	    && tp->suspend.waitstatus_pending_p)
+	  return 1;
     }
   return 0;
 }
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index f15cbc4..780d288 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -29,6 +29,7 @@ struct symtab;
 #include "inferior.h"
 #include "btrace.h"
 #include "common/vec.h"
+#include "target/waitstatus.h"
 
 /* Frontend view of the thread state.  Possible extensions: stepping,
    finishing, until(ling),...  */
@@ -159,6 +160,23 @@ struct thread_suspend_state
      should be suppressed, the core will take care of clearing this
      before the target is resumed.  */
   enum gdb_signal stop_signal;
+
+  /* The reason the thread last stopped, if we need to track it
+     (breakpoint, watchpoint, etc.)  */
+  enum target_stop_reason stop_reason;
+
+  /* The waitstatus for this thread's last event.  */
+  struct target_waitstatus waitstatus;
+  /* If true WAITSTATUS hasn't been handled yet.  */
+  int waitstatus_pending_p;
+
+  /* Record the pc of the thread the last time it stopped.  (This is
+     not the current thread's PC as that may have changed since the
+     last stop, e.g., "return" command, or "p $pc = 0xf000").  This
+     used in coordination with stop_reason and waitstatus_pending_p:
+     if the thread's PC is changed since it last stopped, a pending
+     breakpoint waitstatus is discarded.  */
+  CORE_ADDR stop_pc;
 };
 
 typedef struct value *value_ptr;
@@ -183,6 +201,14 @@ struct thread_info
      thread is off and running.  */
   int executing;
 
+  /* Non-zero if this thread will be/has been resumed.  Note that a
+     thread can be marked both as not-executing and resumed at the
+     same time.  This happens if we try to resume a thread that has a
+     wait status pending.  We shouldn't let the thread run until that
+     wait status has been processed, but we should not process that
+     wait status if we didn't try to let the thread run.  */
+  int resumed;
+
   /* Frontend view of the thread state.  Note that the THREAD_RUNNING/
      THREAD_STOPPED states are different from EXECUTING.  When the
      thread is stopped internally while handling an internal event,
@@ -399,6 +425,11 @@ extern int thread_count (void);
 /* Switch from one thread to another.  */
 extern void switch_to_thread (ptid_t ptid);
 
+/* Marks or clears thread(s) PTID as resumed.  If PTID is
+   MINUS_ONE_PTID, applies to all threads.  If ptid_is_pid(PTID) is
+   true, applies to all threads of the process pointed at by PTID.  */
+extern void set_resumed (ptid_t ptid, int resumed);
+
 /* Marks thread PTID is running, or stopped. 
    If PTID is minus_one_ptid, marks all threads.  */
 extern void set_running (ptid_t ptid, int running);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index f24e8d7..8e49fa2 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -60,6 +60,36 @@
 #include "target-descriptions.h"
 #include "target-dcache.h"
 #include "terminal.h"
+#include "event-loop.h"
+
+/* Asynchronous signal handler registered as event loop source for
+   when we have pending events ready to be passed to the core.  */
+static struct async_event_handler *infrun_async_inferior_event_token;
+
+/* Stores whether infrun_async was previously enabled or disabled.
+   Starts off as -1, indicating "never enabled/disabled".  */
+static int infrun_is_async = -1;
+
+/* See infrun.h.  */
+
+void
+infrun_async (int enable)
+{
+  if (infrun_is_async != enable)
+    {
+      infrun_is_async = enable;
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: infrun_async(%d)\n",
+			    enable);
+
+      if (enable)
+	mark_async_event_handler (infrun_async_inferior_event_token);
+      else
+	clear_async_event_handler (infrun_async_inferior_event_token);
+    }
+}
 
 /* Prototypes for local functions */
 
@@ -1283,6 +1313,9 @@ set_step_over_info (struct address_space *aspace, CORE_ADDR address,
 static void
 clear_step_over_info (void)
 {
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+			"infrun: clear_step_over_info\n");
   step_over_info.aspace = NULL;
   step_over_info.address = 0;
   step_over_info.nonsteppable_watchpoint_p = 0;
@@ -1786,7 +1819,13 @@ displaced_step_restore (struct displaced_step_inferior_state *displaced,
 				  displaced->step_copy));
 }
 
-static void
+/* If we displaced stepped an instruction successfully, adjust
+   registers and memory to yield the same effect the instruction would
+   have had if we had executed it at its original address, and return
+   1.  If the instruction didn't complete, relocate the PC and return
+   -1.  If the thread wasn't displaced stepping, return 0.  */
+
+static int
 displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 {
   struct cleanup *old_cleanups;
@@ -1794,15 +1833,16 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
     = get_displaced_stepping_state (ptid_get_pid (event_ptid));
   struct regcache *regcache;
   struct gdbarch *gdbarch;
+  int ret;
 
   /* Was any thread of this process doing a displaced step?  */
   if (displaced == NULL)
-    return;
+    return 0;
 
   /* Was this event for the pid we displaced?  */
   if (ptid_equal (displaced->step_ptid, null_ptid)
       || ! ptid_equal (displaced->step_ptid, event_ptid))
-    return;
+    return 0;
 
   old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
 
@@ -1828,6 +1868,7 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
                                     displaced->step_original,
                                     displaced->step_copy,
                                     get_thread_regcache (displaced->step_ptid));
+      ret = 1;
     }
   else
     {
@@ -1837,11 +1878,14 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
       pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
+      ret = -1;
     }
 
   do_cleanups (old_cleanups);
 
   displaced->step_ptid = null_ptid;
+
+  return ret;
 }
 
 /* Data to be passed around while handling an event.  This data is
@@ -1888,9 +1932,10 @@ static int thread_still_needs_step_over (struct thread_info *tp);
 static int
 start_step_over_inferior (struct inferior *inf)
 {
-  /* Don't start a new step-over if we already have a displaced step
+  /* Don't start a new step-over if we already have a step-over
      operation ongoing.  */
-  if (displaced_step_in_progress (inf->pid))
+  if (step_over_info_valid_p ()
+      || displaced_step_in_progress (inf->pid))
     return 0;
 
   while (inf->step_over_queue_head != NULL)
@@ -1903,13 +1948,16 @@ start_step_over_inferior (struct inferior *inf)
 
       step_over_chain_dequeue (&inf->step_over_queue_head);
 
-      if (tp->control.trap_expected || tp->executing)
+      if (tp->control.trap_expected
+	  || tp->resumed
+	  || tp->executing)
 	{
 	  internal_error (__FILE__, __LINE__,
 			  "[%s] has inconsistent state: "
-			  "trap_expected=%d, executing=%d\n",
+			  "trap_expected=%d, resumed=%d, executing=%d\n",
 			  target_pid_to_str (tp->ptid),
 			  tp->control.trap_expected,
+			  tp->resumed,
 			  tp->executing);
 	}
 
@@ -1996,7 +2044,12 @@ static void
 resume_cleanups (void *ignore)
 {
   if (!ptid_equal (inferior_ptid, null_ptid))
-    delete_single_step_breakpoints (inferior_thread ());
+    {
+      struct thread_info *tp = inferior_thread ();
+
+      tp->resumed = 0;
+      delete_single_step_breakpoints (tp);
+    }
 
   normal_stop ();
 }
@@ -2161,12 +2214,39 @@ resume (enum gdb_signal sig)
      single-step).  */
   int step;
 
-  tp->stepped_breakpoint = 0;
+  tp->resumed = 1;
 
   gdb_assert (tp->step_over_next == NULL);
 
   QUIT;
 
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      if (debug_infrun)
+	{
+	  char *statstr;
+
+	  statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: resume: thread %s has pending wait status %s "
+			      "(currently_stepping=%d).\n",
+			      target_pid_to_str (tp->ptid),  statstr,
+			      currently_stepping (tp));
+	  xfree (statstr);
+	}
+
+      /* Avoid confusing the next resume, if the next stop/resume
+	 happens to apply to another thread.  */
+      tp->suspend.stop_signal = GDB_SIGNAL_0;
+      discard_cleanups (old_cleanups);
+
+      if (target_can_async_p ())
+	target_async (1);
+      return;
+    }
+
+  tp->stepped_breakpoint = 0;
+
   /* Depends on stepped_breakpoint.  */
   step = currently_stepping (tp);
 
@@ -2300,6 +2380,7 @@ resume (enum gdb_signal sig)
 				"Got placed in displaced stepping queue\n");
 
 	  tp->control.trap_expected = 0;
+	  tp->resumed = 0;
 	  discard_cleanups (old_cleanups);
 	  return;
 	}
@@ -2389,11 +2470,12 @@ resume (enum gdb_signal sig)
   if (execution_direction != EXEC_REVERSE
       && step && breakpoint_inserted_here_p (aspace, pc))
     {
-      /* The only case we currently need to step a breakpoint
-	 instruction is when we have a signal to deliver.  See
-	 handle_signal_stop where we handle random signals that could
-	 take out us out of the stepping range.  Normally, in that
-	 case we end up continuing (instead of stepping) over the
+      /* There are two cases where we currently need to step a
+	 breakpoint instruction when we have a signal to deliver:
+
+	 - See handle_signal_stop where we handle random signals that
+	 could take out us out of the stepping range.  Normally, in
+	 that case we end up continuing (instead of stepping) over the
 	 signal handler with a breakpoint at PC, but there are cases
 	 where we should _always_ single-step, even if we have a
 	 step-resume breakpoint, like when a software watchpoint is
@@ -2406,8 +2488,20 @@ resume (enum gdb_signal sig)
 	 recurses and executes PC again, it'll miss the breakpoint.
 	 So we leave the breakpoint inserted anyway, but we need to
 	 record that we tried to step a breakpoint instruction, so
-	 that adjust_pc_after_break doesn't end up confused.  */
-      gdb_assert (sig != GDB_SIGNAL_0);
+	 that adjust_pc_after_break doesn't end up confused.
+
+         - In non-stop if we insert a breakpoint (e.g., a step-resume)
+	 in one thread after another thread that was stepping had been
+	 momentarily paused for a step-over.  When we re-resume the
+	 stepping thread, it may be resumed from that address with a
+	 breakpoint that hasn't trapped yet.  Seen with
+	 gdb.threads/non-stop-fair-events.exp, on targets that don't
+	 do displaced stepping.  */
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: resume: [%s] stepped breakpoint\n",
+			    target_pid_to_str (tp->ptid));
 
       tp->stepped_breakpoint = 1;
 
@@ -2461,6 +2555,37 @@ clear_proceed_status_thread (struct thread_info *tp)
 			"infrun: clear_proceed_status_thread (%s)\n",
 			target_pid_to_str (tp->ptid));
 
+  /* If we're starting a new sequence, then the previous finished
+     single-step is no longer relevant.  */
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SINGLE_STEP)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: clear_proceed_status: pending "
+				"event of %s was a finished step. "
+				"Discarding.\n",
+				target_pid_to_str (tp->ptid));
+
+	  tp->suspend.waitstatus_pending_p = 0;
+	  tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+	}
+      else if (debug_infrun)
+	{
+	  char *statstr;
+
+	  statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: clear_proceed_status_thread: thread %s "
+			      "has pending wait status %s "
+			      "(currently_stepping=%d).\n",
+			      target_pid_to_str (tp->ptid), statstr,
+			      currently_stepping (tp));
+	  xfree (statstr);
+	}
+    }
+
   /* If this signal should not be seen by program, give it zero.
      Used for debugging signals.  */
   if (!signal_pass_state (tp->suspend.stop_signal))
@@ -2524,8 +2649,6 @@ clear_proceed_status (int step)
 
   stop_after_trap = 0;
 
-  clear_step_over_info ();
-
   observer_notify_about_to_proceed ();
 
   if (stop_registers)
@@ -3097,6 +3220,174 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
   ui_file_delete (tmp_stream);
 }
 
+/* Select a thread at random, out of those which are resumed and have
+   had events.  */
+
+static struct thread_info *
+random_pending_event_thread (ptid_t waiton_ptid)
+{
+  struct thread_info *event_tp;
+  int num_events = 0;
+  int random_selector;
+
+  /* First see how many events we have.  Count only resumed threads
+     that have an event pending.  */
+  ALL_NON_EXITED_THREADS (event_tp)
+    if (ptid_match (event_tp->ptid, waiton_ptid)
+	&& event_tp->resumed
+	&& event_tp->suspend.waitstatus_pending_p)
+      num_events++;
+
+  if (num_events == 0)
+    return NULL;
+
+  /* Now randomly pick a thread out of those that have had events.  */
+  random_selector = (int)
+    ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
+
+  if (debug_infrun && num_events > 1)
+    fprintf_unfiltered (gdb_stdlog,
+			"infrun: Found %d events, selecting #%d\n",
+			num_events, random_selector);
+
+  /* Select the Nth thread that has had an event.  */
+  ALL_NON_EXITED_THREADS (event_tp)
+    if (ptid_match (event_tp->ptid, waiton_ptid)
+	&& event_tp->resumed
+	&& event_tp->suspend.waitstatus_pending_p)
+      if (random_selector-- == 0)
+	break;
+
+  return event_tp;
+}
+
+/* Wrapper for target_wait that first checks whether threads have
+   pending status to report before actually asking the target for more
+   events.  */
+
+static ptid_t
+do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
+{
+  ptid_t event_ptid;
+  struct thread_info *tp;
+
+  /* First check if there is a resumed thread with a wait status
+     pending.  */
+  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+    {
+      tp = random_pending_event_thread (ptid);
+    }
+  else
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: Waiting for specific thread %s.\n",
+			    target_pid_to_str (ptid));
+
+      /* We have a specific thread to check.  */
+      tp = find_thread_ptid (ptid);
+      gdb_assert (tp != NULL);
+      if (!tp->suspend.waitstatus_pending_p)
+	tp = NULL;
+    }
+
+  if (tp != NULL
+      && (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+	  || tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
+    {
+      struct regcache *regcache = get_thread_regcache (tp->ptid);
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      CORE_ADDR pc;
+      int discard = 0;
+
+      pc = regcache_read_pc (regcache);
+
+      if (pc != tp->suspend.stop_pc)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: PC of %s changed.  was=%s, now=%s\n",
+				target_pid_to_str (tp->ptid),
+				paddress (target_gdbarch (), tp->prev_pc),
+				paddress (target_gdbarch (), pc));
+	  discard = 1;
+	}
+      else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: previous breakpoint of %s, at %s gone\n",
+				target_pid_to_str (tp->ptid),
+				paddress (target_gdbarch (), pc));
+
+	  discard = 1;
+	}
+
+      if (discard)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: pending event of %s cancelled.\n",
+				target_pid_to_str (tp->ptid));
+
+	  tp->suspend.waitstatus.kind = TARGET_WAITKIND_SPURIOUS;
+	  tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+	}
+    }
+
+  if (tp != NULL)
+    {
+      if (debug_infrun)
+	{
+	  char *statstr;
+
+	  statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: Using pending wait status %s for %s.\n",
+			      statstr,
+			      target_pid_to_str (tp->ptid));
+	  xfree (statstr);
+	}
+
+      /* Now that we've selected our final event LWP, un-adjust its PC
+	 if it was a software breakpoint (and the target doesn't
+	 always adjust the PC itself).  */
+      if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+	  && !target_supports_stopped_by_sw_breakpoint ())
+	{
+	  struct regcache *regcache;
+	  struct gdbarch *gdbarch;
+	  int decr_pc;
+
+	  regcache = get_thread_regcache (tp->ptid);
+	  gdbarch = get_regcache_arch (regcache);
+
+	  decr_pc = gdbarch_decr_pc_after_break (gdbarch);
+	  if (decr_pc != 0)
+	    {
+	      CORE_ADDR pc;
+
+	      pc = regcache_read_pc (regcache);
+	      regcache_write_pc (regcache, pc + decr_pc);
+	    }
+	}
+
+      tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+      *status = tp->suspend.waitstatus;
+      tp->suspend.waitstatus_pending_p = 0;
+      return tp->ptid;
+    }
+
+  /* But if we don't find one, we'll have to wait.  */
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (ptid, status, options);
+  else
+    event_ptid = target_wait (ptid, status, options);
+
+  return event_ptid;
+}
+
 /* Prepare and stabilize the inferior for detaching it.  E.g.,
    detaching while a thread is displaced stepping is a recipe for
    crashing it, as nothing would readjust the PC out of the scratch
@@ -3140,10 +3431,7 @@ prepare_for_detach (void)
 	 don't get any event.  */
       target_dcache_invalidate ();
 
-      if (deprecated_target_wait_hook)
-	ecs->ptid = deprecated_target_wait_hook (pid_ptid, &ecs->ws, 0);
-      else
-	ecs->ptid = target_wait (pid_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (pid_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
 	print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
@@ -3215,10 +3503,7 @@ wait_for_inferior (void)
 	 don't get any event.  */
       target_dcache_invalidate ();
 
-      if (deprecated_target_wait_hook)
-	ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws, 0);
-      else
-	ecs->ptid = target_wait (waiton_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
 	print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
@@ -3315,11 +3600,7 @@ fetch_inferior_event (void *client_data)
   make_cleanup_restore_integer (&execution_direction);
   execution_direction = target_execution_direction ();
 
-  if (deprecated_target_wait_hook)
-    ecs->ptid =
-      deprecated_target_wait_hook (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
-  else
-    ecs->ptid = target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
+  ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
 
   if (debug_infrun)
     print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
@@ -3692,6 +3973,321 @@ get_inferior_stop_soon (ptid_t ptid)
   return inf->control.stop_soon;
 }
 
+/* Wait for one event.  Store the resulting waitstatus in WS, and
+   return the event ptid.  */
+
+static ptid_t
+wait_one (struct target_waitstatus *ws)
+{
+  ptid_t event_ptid;
+  ptid_t wait_ptid = minus_one_ptid;
+
+  overlay_cache_invalid = 1;
+
+  /* Flush target cache before starting to handle each event.
+     Target was running and cache could be stale.  This is just a
+     heuristic.  Running threads may modify target memory, but we
+     don't get any event.  */
+  target_dcache_invalidate ();
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (wait_ptid, ws, 0);
+  else
+    event_ptid = target_wait (wait_ptid, ws, 0);
+
+  if (debug_infrun)
+    print_target_wait_results (wait_ptid, event_ptid, ws);
+
+  if (ws->kind == TARGET_WAITKIND_SYSCALL_ENTRY
+      || ws->kind == TARGET_WAITKIND_SYSCALL_RETURN)
+    ws->value.syscall_number = UNKNOWN_SYSCALL;
+
+  return event_ptid;
+}
+
+/* Generate a wrapper for target_stopped_by_REASON that works on PTID
+   instead of the current thread.  */
+#define THREAD_STOPPED_BY(REASON)		\
+static int					\
+thread_stopped_by_ ## REASON (ptid_t ptid)	\
+{						\
+  struct cleanup *old_chain;			\
+  int res;					\
+						\
+  old_chain = save_inferior_ptid ();		\
+  inferior_ptid = ptid;				\
+						\
+  res = target_stopped_by_ ## REASON ();	\
+						\
+  do_cleanups (old_chain);			\
+						\
+  return res;					\
+}
+
+/* Generate thread_stopped_by_watchpoint.  */
+THREAD_STOPPED_BY (watchpoint)
+/* Generate thread_stopped_by_sw_breakpoint.  */
+THREAD_STOPPED_BY (sw_breakpoint)
+/* Generate thread_stopped_by_hw_breakpoint.  */
+THREAD_STOPPED_BY (hw_breakpoint)
+
+/* Cleanups that switches to the PTID pointed at by PTID_P.  */
+
+static void
+switch_to_thread_cleanup (void *ptid_p)
+{
+  ptid_t ptid = *(ptid_t *) ptid_p;
+
+  switch_to_thread (ptid);
+}
+
+/* Stop all threads.  */
+
+static void
+stop_all_threads (void)
+{
+  /* We may need multiple passes to discover all threads.  */
+  int pass;
+  int iterations = 0;
+  ptid_t entry_ptid;
+  struct cleanup *old_chain;
+
+  gdb_assert (non_stop);
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
+
+  entry_ptid = inferior_ptid;
+  old_chain = make_cleanup (switch_to_thread_cleanup, &entry_ptid);
+
+  /* Stop threads in two passes since threads could be spawning as we
+     go through the first pass.  In the second pass, we will stop such
+     spawned threads.  */
+  for (pass = 0; pass < 2; pass++, iterations++)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: stop_all_threads, pass=%d, "
+			    "iterations=%d\n", pass, iterations);
+      while (1)
+	{
+	  ptid_t event_ptid;
+	  struct target_waitstatus ws;
+	  int need_wait = 0;
+	  struct thread_info *t;
+
+	  update_thread_list ();
+
+	  /* Go through all threads looking for threads that we need
+	     to tell the target to stop.  */
+	  ALL_NON_EXITED_THREADS (t)
+	    {
+	      if (t->executing)
+		{
+		  /* If already stopping, don't request a stop again.
+		     We just haven't seen the notification yet.  */
+		  if (!t->stop_requested)
+		    {
+		      if (debug_infrun)
+			fprintf_unfiltered (gdb_stdlog,
+					    "infrun:   %s executing, "
+					    "need stop\n",
+					    target_pid_to_str (t->ptid));
+		      target_stop (t->ptid);
+		      t->stop_requested = 1;
+		    }
+		  else
+		    {
+		      if (debug_infrun)
+			fprintf_unfiltered (gdb_stdlog,
+					    "infrun:   %s executing, "
+					    "already stopping\n",
+					    target_pid_to_str (t->ptid));
+		    }
+
+		  if (t->stop_requested)
+		    need_wait = 1;
+		}
+	      else
+		{
+		  if (debug_infrun)
+		    fprintf_unfiltered (gdb_stdlog,
+					"infrun:   %s not executing\n",
+					target_pid_to_str (t->ptid));
+
+		  /* The thread may be not executing, but still be
+		     resumed with a pending status to process.  */
+		  t->resumed = 0;
+		}
+	    }
+
+	  if (!need_wait)
+	    break;
+
+	  /* If we find new threads on the second iteration, restart
+	     over.  We want to see two iterations in a row with all
+	     threads stopped.  */
+	  if (pass > 0)
+	    pass = -1;
+
+	  event_ptid = wait_one (&ws);
+	  if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
+	    /* All resumed threads exited.  */
+	    ;
+	  else if (ws.kind == TARGET_WAITKIND_EXITED
+		   || ws.kind == TARGET_WAITKIND_SIGNALLED)
+	    {
+	      if (debug_infrun)
+		{
+		  ptid_t ptid = pid_to_ptid (ws.value.integer);
+
+		  fprintf_unfiltered (gdb_stdlog,
+				      "infrun: %s exited while "
+				      "stopping threads\n",
+				      target_pid_to_str (ptid));
+		}
+	    }
+	  else
+	    {
+	      if (!in_thread_list (event_ptid))
+		t = add_thread (event_ptid);
+	      else
+		t = find_thread_ptid (event_ptid);
+
+	      t->stop_requested = 0;
+	      t->executing = 0;
+	      t->resumed = 0;
+	      t->control.may_range_step = 0;
+
+	      if (ws.kind == TARGET_WAITKIND_STOPPED
+		  && ws.value.sig == GDB_SIGNAL_0)
+		{
+		  /* We caught the event that we intended to catch, so
+		     there's no event pending.  */
+		  t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+		  t->suspend.waitstatus_pending_p = 0;
+
+		  if (displaced_step_fixup (t->ptid, GDB_SIGNAL_0) < 0)
+		    {
+		      /* Add it back to the step-over queue.  */
+		      if (debug_infrun)
+			{
+			  fprintf_unfiltered (gdb_stdlog,
+					      "infrun: displaced-step of %s "
+					      "canceled: adding back to the "
+					      "step-over queue\n",
+					      target_pid_to_str (t->ptid));
+			}
+		      t->control.trap_expected = 0;
+		      thread_step_over_chain_enqueue (t);
+		    }
+		}
+	      else
+		{
+		  enum gdb_signal sig;
+		  struct regcache *regcache;
+		  struct address_space *aspace;
+
+		  if (debug_infrun)
+		    {
+		      char *statstr;
+
+		      statstr = target_waitstatus_to_string (&ws);
+		      fprintf_unfiltered (gdb_stdlog,
+					  "infrun: target_wait %s, saving "
+					  "status for %d.%ld.%ld\n",
+					  statstr,
+					  ptid_get_pid (t->ptid),
+					  ptid_get_lwp (t->ptid),
+					  ptid_get_tid (t->ptid));
+		      xfree (statstr);
+		    }
+
+		  /* Record for later.  */
+		  t->suspend.waitstatus = ws;
+		  t->suspend.waitstatus_pending_p = 1;
+
+		  sig = (ws.kind == TARGET_WAITKIND_STOPPED
+			 ? ws.value.sig : GDB_SIGNAL_0);
+
+		  regcache = get_thread_regcache (t->ptid);
+		  aspace = get_regcache_aspace (regcache);
+
+		  if (ws.kind == TARGET_WAITKIND_STOPPED
+		      && ws.value.sig == GDB_SIGNAL_TRAP)
+		    {
+		      CORE_ADDR pc = regcache_read_pc (regcache);
+
+		      adjust_pc_after_break (t, &t->suspend.waitstatus);
+
+		      if (thread_stopped_by_watchpoint (t->ptid))
+			{
+			  t->suspend.stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
+			}
+		      else if (target_supports_stopped_by_sw_breakpoint ()
+			       && thread_stopped_by_sw_breakpoint (t->ptid))
+			{
+			  t->suspend.stop_reason
+			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+			}
+		      else if (target_supports_stopped_by_hw_breakpoint ()
+			       && thread_stopped_by_hw_breakpoint (t->ptid))
+			{
+			  t->suspend.stop_reason
+			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+			}
+		      else if (!target_supports_stopped_by_hw_breakpoint ()
+			       && hardware_breakpoint_inserted_here_p (aspace,
+								       pc))
+			{
+			  t->suspend.stop_reason
+			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+			}
+		      else if (!target_supports_stopped_by_sw_breakpoint ()
+			       && software_breakpoint_inserted_here_p (aspace,
+								       pc))
+			{
+			  t->suspend.stop_reason
+			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+			}
+		      else if (!thread_has_single_step_breakpoints_set (t)
+			       && currently_stepping (t))
+			{
+			  t->suspend.stop_reason
+			    = TARGET_STOPPED_BY_SINGLE_STEP;
+			}
+		    }
+
+		  if (displaced_step_fixup (t->ptid, sig) < 0)
+		    {
+		      /* Add it back to the step-over queue.  */
+		      t->control.trap_expected = 0;
+		      thread_step_over_chain_enqueue (t);
+		    }
+
+		  t->suspend.stop_pc = regcache_read_pc (regcache);
+
+		  if (debug_infrun)
+		    {
+		      fprintf_unfiltered (gdb_stdlog,
+					  "infrun: saved stop_pc=%s for %s "
+					  "(currently_stepping=%d)\n",
+					  paddress (target_gdbarch (),
+						    t->suspend.stop_pc),
+					  target_pid_to_str (t->ptid),
+					  currently_stepping (t));
+		    }
+		}
+	    }
+	}
+    }
+
+  do_cleanups (old_chain);
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads done\n");
+}
+
 /* Given an execution control state that has been freshly filled in by
    an event from the inferior, figure out what it means and take
    appropriate action.
@@ -3814,21 +4410,28 @@ handle_inferior_event (struct execution_control_state *ecs)
      we're handling a process exit in non-stop mode, there's nothing
      to do, as threads of the dead process are gone, and threads of
      any other process were left running.  */
-  if (!non_stop)
-    set_executing (minus_one_ptid, 0);
-  else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
-	   && ecs->ws.kind == TARGET_WAITKIND_EXITED)
-    {
-      ptid_t pid_ptid;
 
-      /* Some targets still have execution when a process exits.
-	 E.g., for "checkpoint", when when a fork exits and is
-	 mourned, linux-fork.c switches to another fork.  */
-      pid_ptid = pid_to_ptid (ptid_get_pid (ecs->ptid));
-      set_executing (pid_ptid, 0);
-    }
-  else
-    set_executing (ecs->ptid, 0);
+  {
+    ptid_t mark_ptid;
+
+    if (!non_stop)
+      mark_ptid = minus_one_ptid;
+    else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
+	     && ecs->ws.kind == TARGET_WAITKIND_EXITED)
+      {
+	/* Some targets still have execution when a process exits.
+	   E.g., for "checkpoint", when when a fork exits and is
+	   mourned, linux-fork.c switches to another fork.  */
+	mark_ptid = pid_to_ptid (ptid_get_pid (ecs->ptid));
+      }
+    else
+      mark_ptid = ecs->ptid;
+
+    set_executing (mark_ptid, 0);
+
+    /* Likewise the resumed flag.  */
+    set_resumed (mark_ptid, 0);
+  }
 
   switch (ecs->ws.kind)
     {
@@ -4241,16 +4844,105 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
     }
 }
 
+/* Restart threads back to what they were trying to do back when we
+   paused them for an in-line step-over.  The EVENT_THREAD thread is
+   ignored.  */
+
+static void
+restart_threads (struct thread_info *event_thread)
+{
+  struct thread_info *tp;
+  struct thread_info *step_over = NULL;
+
+  /* In case the instruction just stepped spawned a new thread.  */
+  update_thread_list ();
+
+  ALL_NON_EXITED_THREADS (tp)
+    {
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs = &ecss;
+
+      if (tp == event_thread)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: "
+				"[%s] is event thread\n",
+				target_pid_to_str (tp->ptid));
+	  continue;
+	}
+
+      if (!(tp->state == THREAD_RUNNING || tp->control.in_infcall))
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: "
+				"[%s] not meant to be running\n",
+				target_pid_to_str (tp->ptid));
+	  continue;
+	}
+
+      if (tp->executing)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: [%s] executing\n",
+				target_pid_to_str (tp->ptid));
+	  gdb_assert (tp->resumed);
+	  continue;
+	}
+
+      if (tp->step_over_next != NULL)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: "
+				"[%s] needs step-over\n",
+				target_pid_to_str (tp->ptid));
+	  gdb_assert (!tp->resumed);
+	  continue;
+	}
+
+      /* If some thread needs to start a step-over at this point, it
+	 should still be in the step-over queue, and thus skipped
+	 above.  */
+      gdb_assert (!thread_still_needs_step_over (tp));
+
+      if (currently_stepping (tp))
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: [%s] was stepping\n",
+				target_pid_to_str (tp->ptid));
+	  keep_going_stepped_thread (tp);
+	}
+      else
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: [%s] continuing\n",
+				target_pid_to_str (tp->ptid));
+	  reset_ecs (ecs, tp);
+	  switch_to_thread (tp->ptid);
+	  keep_going_pass (ecs);
+	}
+    }
+}
+
 /* Called when we get an event that may finish an in-line or
    out-of-line (displaced stepping) step-over started previously.  */
 
 static void
 finish_step_over (struct execution_control_state *ecs)
 {
+  int had_step_over_info;
+
   displaced_step_fixup (ecs->ptid,
 			ecs->event_thread->suspend.stop_signal);
 
-  if (step_over_info_valid_p ())
+  had_step_over_info = step_over_info_valid_p ();
+
+  if (had_step_over_info)
     {
       /* If we're stepping over a breakpoint with all threads locked,
 	 then only the thread that was stepped should be reporting
@@ -4267,6 +4959,18 @@ finish_step_over (struct execution_control_state *ecs)
   /* Start a new step-over in another thread if there's one that
      needs it.  */
   start_step_over (ecs->ptid);
+
+  /* If we were stepping over a breakpoint before, and haven't started
+     a new in-line step-over sequence, then restart all other threads
+     (except the event thread).  We can't do this in all-stop, as then
+     e.g., we wouldn't be able to issue any other remote packet until
+     these other threads stop.  */
+  if (had_step_over_info && !step_over_info_valid_p ())
+    {
+      restart_threads (ecs->event_thread);
+
+      gdb_assert (!ecs->event_thread->resumed);
+    }
 }
 
 /* Come here when the program has stopped with a signal.  */
@@ -4743,6 +5447,7 @@ handle_signal_stop (struct execution_control_state *ecs)
                                 "infrun: signal arrived while stepping over "
                                 "breakpoint\n");
 
+	  clear_step_over_info ();
 	  insert_hp_step_resume_breakpoint_at_frame (frame);
 	  ecs->event_thread->step_after_step_resume_breakpoint = 1;
 	  /* Reset trap_expected to ensure breakpoints are re-inserted.  */
@@ -4776,6 +5481,7 @@ handle_signal_stop (struct execution_control_state *ecs)
                                 "infrun: signal may take us out of "
                                 "single-step range\n");
 
+	  clear_step_over_info ();
 	  insert_hp_step_resume_breakpoint_at_frame (frame);
 	  ecs->event_thread->step_after_step_resume_breakpoint = 1;
 	  /* Reset trap_expected to ensure breakpoints are re-inserted.  */
@@ -5781,6 +6487,27 @@ keep_going_stepped_thread (struct thread_info *tp)
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
 
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      if (debug_infrun)
+	{
+	  char *statstr;
+
+	  statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: previously stepped thread %s "
+			      "has pending wait status %s.\n",
+			      target_pid_to_str (tp->ptid),  statstr);
+	  xfree (statstr);
+	}
+
+      tp->resumed = 1;
+
+      if (target_can_async_p ())
+	target_async (1);
+      return 1;
+    }
+
   /* If the stepping thread exited, then don't try to switch back and
      resume it, which could fail in several different ways depending
      on the target.  Instead, just keep going.
@@ -5859,6 +6586,7 @@ keep_going_stepped_thread (struct thread_info *tp)
 				     get_frame_address_space (frame),
 				     stop_pc);
 
+      tp->resumed = 1;
       resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
       do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
     }
@@ -6290,6 +7018,7 @@ keep_going_pass (struct execution_control_state *ecs)
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
 
   gdb_assert (ptid_equal (ecs->event_thread->ptid, inferior_ptid));
+  gdb_assert (!ecs->event_thread->resumed);
 
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
@@ -6312,6 +7041,34 @@ keep_going_pass (struct execution_control_state *ecs)
       discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
+  else if (step_over_info_valid_p ())
+    {
+      /* Another thread is stepping over a breakpoint in-line.  If
+	 this thread needs a step-over too, queue the request.  In
+	 either case, this resume must be deferred for later.  */
+      struct thread_info *tp = ecs->event_thread;
+
+      if (ecs->hit_singlestep_breakpoint
+	  || thread_still_needs_step_over (tp))
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: step-over already in progress: "
+				"step-over for %s deferred\n",
+				target_pid_to_str (tp->ptid));
+	  thread_step_over_chain_enqueue (tp);
+	}
+      else
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: step-over in progress: "
+				"resume of %s deferred\n",
+				target_pid_to_str (tp->ptid));
+	}
+
+      discard_cleanups (old_cleanups);
+    }
   else
     {
       struct regcache *regcache = get_current_regcache ();
@@ -6362,6 +7119,14 @@ keep_going_pass (struct execution_control_state *ecs)
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
+      /* If we're now doing an in-line step-over, we need to stop all
+	 other threads.  Note this must be done before
+	 insert_breakpoints below, because that removes the breakpoint
+	 we're about to step over, otherwise other threads could miss
+	 it.  */
+      if (step_over_info_valid_p () && non_stop)
+	stop_all_threads ();
+
       /* Stop stepping if inserting breakpoints fails.  */
       TRY
 	{
@@ -7792,6 +8557,23 @@ static const struct internalvar_funcs siginfo_funcs =
   NULL
 };
 
+/* Callback for infrun's target events source.  This is marked when a
+   thread has a pending status to process.  */
+
+static void
+infrun_async_inferior_event_handler (gdb_client_data data)
+{
+  /* If the target is closed while this event source is marked, we
+     will reach here without execution, or a target to call
+     target_wait on, which is an error.  Instead of tracking whether
+     the target has been popped already, or whether we do have threads
+     with pending statutes, simply ignore the event.  */
+  if (!target_is_async_p ())
+    return;
+
+  inferior_event_handler (INF_REG_EVENT, NULL);
+}
+
 void
 _initialize_infrun (void)
 {
@@ -7799,6 +8581,10 @@ _initialize_infrun (void)
   int numsigs;
   struct cmd_list_element *c;
 
+  /* Register extra event sources in the event loop.  */
+  infrun_async_inferior_event_token
+    = create_async_event_handler (infrun_async_inferior_event_handler, NULL);
+
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 1f09e41..0a5d20d 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -196,4 +196,7 @@ extern void signal_catch_update (const unsigned int *);
    systems.  Use of symbolic signal names is strongly encouraged.  */
 enum gdb_signal gdb_signal_from_command (int num);
 
+/* Enables/disables infrun's async event source in the event loop.  */
+extern void infrun_async (int enable);
+
 #endif /* INFRUN_H */
diff --git a/gdb/target.c b/gdb/target.c
index 306c21d..e992a35 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3712,6 +3712,15 @@ maintenance_print_target_stack (char *cmd, int from_tty)
     }
 }
 
+/* See target.h.  */
+
+void
+target_async (int enable)
+{
+  infrun_async (enable);
+  current_target.to_async (&current_target, enable);
+}
+
 /* Controls if targets can report that they can/are async.  This is
    just for maintainers to use when debugging gdb.  */
 int target_async_permitted = 1;
diff --git a/gdb/target.h b/gdb/target.h
index f57e431..1f6dd98 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1699,8 +1699,7 @@ extern int target_async_permitted;
 #define target_is_async_p() (current_target.to_is_async_p (&current_target))
 
 /* Enables/disabled async target events.  */
-#define target_async(ENABLE) \
-     (current_target.to_async (&current_target, (ENABLE)))
+extern void target_async (int enable);
 
 #define target_execution_direction() \
   (current_target.to_execution_direction (&current_target))
diff --git a/gdb/target/waitstatus.h b/gdb/target/waitstatus.h
index d4ef3b8..ffaddc1 100644
--- a/gdb/target/waitstatus.h
+++ b/gdb/target/waitstatus.h
@@ -131,7 +131,10 @@ enum target_stop_reason
   TARGET_STOPPED_BY_HW_BREAKPOINT,
 
   /* Stopped by a watchpoint.  */
-  TARGET_STOPPED_BY_WATCHPOINT
+  TARGET_STOPPED_BY_WATCHPOINT,
+
+  /* Stopped by a single step finishing.  */
+  TARGET_STOPPED_BY_SINGLE_STEP
 };
 
 /* Prototypes */
diff --git a/gdb/thread.c b/gdb/thread.c
index a01f5d8..bb942c2 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -232,6 +232,7 @@ new_thread (ptid_t ptid)
   /* Nothing to follow yet.  */
   tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
   tp->state = THREAD_STOPPED;
+  tp->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
 
   return tp;
 }
@@ -848,6 +849,28 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
   observer_notify_thread_ptid_changed (old_ptid, new_ptid);
 }
 
+/* See gdbthread.h.  */
+
+void
+set_resumed (ptid_t ptid, int resumed)
+{
+  struct thread_info *tp;
+  int all = ptid_equal (ptid, minus_one_ptid);
+
+  if (all || ptid_is_pid (ptid))
+    {
+      for (tp = thread_list; tp; tp = tp->next)
+	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
+	  tp->resumed = resumed;
+    }
+  else
+    {
+      tp = find_thread_ptid (ptid);
+      gdb_assert (tp != NULL);
+      tp->resumed = resumed;
+    }
+}
+
 /* Helper for set_running, that marks one thread either running or
    stopped.  */
 
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 18/23] Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (20 preceding siblings ...)
  2015-04-07 12:59 ` [PATCH v2 14/23] Teach non-stop to do in-line step-overs (stop all, step, restart) Pedro Alves
@ 2015-04-07 13:30 ` Pedro Alves
  2015-04-07 13:30 ` [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too Pedro Alves
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 13:30 UTC (permalink / raw)
  To: gdb-patches

On a target that is both always in non-stop mode and can do displaced
stepping (such as native x86_64 GNU/Linux, with "maint set
target-non-stop on"), the step-over-trips-on-watchpoint.exp test
sometimes fails like this:

   (gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: thread 1
   set scheduler-locking off
   (gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: set scheduler-locking off
   step
  -[Switching to Thread 0x7ffff7fc0700 (LWP 11782)]
  -Hardware watchpoint 4: watch_me
  -
  -Old value = 0
  -New value = 1
  -child_function (arg=0x0) at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c:39
  -39           other = 1; /* set thread-specific breakpoint here */
  -(gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: step
  +wait_threads () at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c:49
  +49       return 1; /* in wait_threads */
  +(gdb) FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: step

Note "scheduler-locking" was set off.  The problem is that on such
targets, the step-over of thread 2 and the "step" of thread 1 can be
set to run simultaneously (since with displaced stepping the
breakpoint isn't ever removed from the target), and sometimes, the
"step" of thread 1 finishes first, so it'd take another resume to see
the watchpoint trigger.  Fix this by replacing the wait_threads
function with a one-line infinite loop that doesn't call any function,
so that the "step" of thread 1 never finishes.

gdb/testsuite/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* gdb.threads/step-over-lands-on-breakpoint.c (wait_threads):
	Delete function.
	(main): Add alarm.  Run an infinite loop instead of calling
	wait_threads.
	* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): Change
	comment.
	* gdb.threads/step-over-trips-on-watchpoint.c (wait_threads):
	Delete function.
	(main): Add alarm.  Run an infinite loop instead of calling
	wait_threads.
	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): Change
	comment.
---
 .../gdb.threads/step-over-lands-on-breakpoint.c         | 17 ++++++++++-------
 .../gdb.threads/step-over-lands-on-breakpoint.exp       |  6 +++---
 .../gdb.threads/step-over-trips-on-watchpoint.c         | 17 ++++++++++-------
 .../gdb.threads/step-over-trips-on-watchpoint.exp       |  9 ++++-----
 4 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
index 0a6ed8f..2480164 100644
--- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
+++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
@@ -41,23 +41,26 @@ child_function (void *arg)
   pthread_exit (NULL);
 }
 
-static int
-wait_threads (void)
-{
-  return 1; /* in wait_threads */
-}
-
 int
 main ()
 {
   int res;
   long i;
 
+  alarm (300);
+
   pthread_barrier_init (&barrier, NULL, 2);
 
   res = pthread_create (&child_thread, NULL, child_function, NULL);
   pthread_barrier_wait (&barrier);
-  wait_threads (); /* set wait-thread breakpoint here */
+
+  /* Use an infinite loop with no function calls so that "step" over
+     this line never finishes before the breakpoint in the other
+     thread triggers.  That can happen if the step-over of thread 2 is
+     done with displaced stepping on a target that is always in
+     non-stop mode, as in that case GDB runs both threads
+     simultaneously.  */
+  while (1); /* set wait-thread breakpoint here */
 
   pthread_join (child_thread, NULL);
 
diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
index 4d27059..239aa96 100644
--- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
@@ -59,9 +59,9 @@ proc do_test {displaced command} {
 	gdb_test_no_output "set scheduler-locking off"
 
 	# Thread 2 is still stopped at a breakpoint that needs to be
-	# stepped over before proceeding thread 1.  However, right
-	# where the step-over lands there's another breakpoint
-	# installed, which should trap and be reported to the user.
+	# stepped over.  However, right where the step-over lands
+	# there's another breakpoint installed, which should trap and
+	# be reported to the user.
 	gdb_test "$command" "step-over here.*"
     }
 }
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
index 6cf97fb..34ba079 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
@@ -43,23 +43,26 @@ child_function (void *arg)
   pthread_exit (NULL);
 }
 
-static int
-wait_threads (void)
-{
-  return 1; /* in wait_threads */
-}
-
 int
 main ()
 {
   int res;
   long i;
 
+  alarm (300);
+
   pthread_barrier_init (&barrier, NULL, 2);
 
   res = pthread_create (&child_thread, NULL, child_function, NULL);
   pthread_barrier_wait (&barrier);
-  wait_threads (); /* set wait-thread breakpoint here */
+
+  /* Use an infinite loop with no function calls so that "step" over
+     this line never finishes before the watchpoint in the other
+     thread triggers.  That can happen if the step-over of thread 2 is
+     done with displaced stepping on a target that is always in
+     non-stop mode, as in that case GDB runs both threads
+     simultaneously.  */
+  while (1); /* set wait-thread breakpoint here */
 
   pthread_join (child_thread, NULL);
 
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
index 3ccceae..a2dc1b9 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
@@ -112,11 +112,10 @@ proc do_test { displaced with_bp } {
 		gdb_test "thread 1" "Switching to .*"
 		gdb_test_no_output "set scheduler-locking off"
 
-		# Thread 2 is still stopped at a breakpoint that needs to be
-		# stepped over before proceeding thread 1.  However, the
-		# instruction that is under the breakpoint triggers a
-		# watchpoint, which should trap and be reported to the
-		# user.
+		# Thread 2 is still stopped at a breakpoint that needs
+		# to be stepped over.  However, the instruction that
+		# is under the breakpoint triggers a watchpoint, which
+		# should trap and be reported to the user.
 		gdb_test "$command" "Hardware watchpoint.*: watch_me.*New value = 1.*"
 	    }
 	}
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (21 preceding siblings ...)
  2015-04-07 13:30 ` [PATCH v2 18/23] Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race Pedro Alves
@ 2015-04-07 13:30 ` Pedro Alves
  2015-04-08  9:28   ` Yao Qi
  2015-04-08  9:45 ` [PATCH v2 00/23] All-stop on top of non-stop Yao Qi
  2015-04-10  8:22 ` Yao Qi
  24 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-07 13:30 UTC (permalink / raw)
  To: gdb-patches

I noticed that even though keep_going knows to start a step over for a
watchpoint, thread_still_needs_step_over doesn't.

gdb/ChangeLog:
2015-04-07  Pedro Alves  <palves@redhat.com>

	* infrun.c (thread_still_needs_step_over): Rename to ...
	(thread_still_needs_step_over_bp): ... this.
	(enum step_over_what): New.
	(thread_still_needs_step_over): Reimplement.
---
 gdb/infrun.c | 46 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 1e8ee4f..c544362 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2521,7 +2521,7 @@ clear_proceed_status (int step)
    meanwhile, we can skip the whole step-over dance.  */
 
 static int
-thread_still_needs_step_over (struct thread_info *tp)
+thread_still_needs_step_over_bp (struct thread_info *tp)
 {
   if (tp->stepping_over_breakpoint)
     {
@@ -2538,6 +2538,34 @@ thread_still_needs_step_over (struct thread_info *tp)
   return 0;
 }
 
+/* Bit flags indicating what the thread needs to step over.  */
+
+enum step_over_what
+  {
+    STEP_OVER_BREAKPOINT = 1,
+    STEP_OVER_WATCHPOINT = 2
+  };
+
+/* Check whether thread TP still needs to start a step-over in order
+   to make progress when resumed.  Returns a union of enum
+   step_over_what bits, indicating what needs to be stepped over.  */
+
+static int
+thread_still_needs_step_over (struct thread_info *tp)
+{
+  struct inferior *inf = find_inferior_ptid (tp->ptid);
+  int what = 0;
+
+  if (thread_still_needs_step_over_bp (tp))
+    what |= STEP_OVER_BREAKPOINT;
+
+  if (tp->stepping_over_watchpoint
+      && !target_have_steppable_watchpoint)
+    what |= STEP_OVER_WATCHPOINT;
+
+  return what;
+}
+
 /* Returns true if scheduler locking applies.  STEP indicates whether
    we're about to do a step/next-like command to a thread.  */
 
@@ -6274,6 +6302,7 @@ keep_going (struct execution_control_state *ecs)
       int remove_bp;
       int remove_wps;
       enum gdb_signal signo;
+      enum step_over_what step_what;
 
       /* Either the trap was not expected, but we are continuing
 	 anyway (if we got a signal, the user asked it be passed to
@@ -6294,11 +6323,6 @@ keep_going (struct execution_control_state *ecs)
 	 instruction, and then re-insert the breakpoint when that step
 	 is finished.  */
 
-      remove_bp = (ecs->hit_singlestep_breakpoint
-		   || thread_still_needs_step_over (ecs->event_thread));
-      remove_wps = (ecs->event_thread->stepping_over_watchpoint
-		    && !target_have_steppable_watchpoint);
-
       /* Do not deliver GDB_SIGNAL_TRAP (except when the user
 	 explicitly specifies that such a signal should be delivered
 	 to the target program).  Typically, that would occur when a
@@ -6315,6 +6339,12 @@ keep_going (struct execution_control_state *ecs)
 
       signo = ecs->event_thread->suspend.stop_signal;
 
+      step_what = thread_still_needs_step_over (ecs->event_thread);
+
+      remove_bp = (ecs->hit_singlestep_breakpoint
+		   || (step_what & STEP_OVER_BREAKPOINT));
+      remove_wps = (step_what & STEP_OVER_WATCHPOINT);
+
       if (remove_bp
 	  && !use_displaced_stepping_now_p (get_regcache_arch (regcache),
 					    signo))
@@ -6327,6 +6357,8 @@ keep_going (struct execution_control_state *ecs)
       else
 	clear_step_over_info ();
 
+      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
+
       /* Stop stepping if inserting breakpoints fails.  */
       TRY
 	{
@@ -6341,8 +6373,6 @@ keep_going (struct execution_control_state *ecs)
 	}
       END_CATCH
 
-      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
-
       discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
@ 2015-04-07 13:36   ` Eli Zaretskii
  2015-04-08  9:34   ` Yao Qi
  1 sibling, 0 replies; 47+ messages in thread
From: Eli Zaretskii @ 2015-04-07 13:36 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <palves@redhat.com>
> Date: Tue,  7 Apr 2015 13:49:42 +0100
> 
> gdb/ChangeLog:
> 2015-04-07  Pedro Alves  <palves@redhat.com>
> 
> 	* NEWS: Mention "maint set/show target-non-stop".
> 	* breakpoint.c (update_global_location_list): Check
> 	target_is_non_stop_p instead of non_stop.
> 	* infcmd.c (attach_command_post_wait, attach_command): Likewise.
> 	* infrun.c (show_can_use_displaced_stepping)
> 	(can_use_displaced_stepping_p, start_step_over_inferior):
> 	Likewise.
> 	(resume): Always resume a single thread if the target is in
> 	non-stop mode.
> 	(proceed): Check target_is_non_stop_p instead of non_stop.  If in
> 	all-mode but the target is always in non-stop mode, start all the
> 	other threads that are implicitly resumed too.
> 	(for_each_just_stopped_thread, fetch_inferior_event)
> 	(adjust_pc_after_break, stop_all_threads): Check
> 	target_is_non_stop_p instead of non_stop.
> 	(handle_inferior_event): Likewise.  Handle detach-fork in all-stop
> 	with the target always in non-stop mode.
> 	(handle_signal_stop) <random signal>: If we get a signal while
> 	stepping over a breakpoint, and the target is always in non-stop
> 	mode, restart all threads.
> 	(switch_back_to_stepped_thread): Check target_is_non_stop_p
> 	instead of non_stop.
> 	(keep_going_stepped_thread): Always resume a single thread if the
> 	target is in non-stop mode.
> 	(stop_waiting): If in all-stop mode, and the target is in non-stop
> 	mode, stop all threads.
> 	(keep_going_pass): Likewise, when starting a new in-line step-over
> 	sequence.
> 	* linux-nat.c (get_pending_status, select_event_lwp)
> 	(linux_nat_filter_event, linux_nat_wait_1, linux_nat_wait): Check
> 	target_is_non_stop_p instead of non_stop.
> 	(linux_nat_always_non_stop_p): New function.
> 	(linux_nat_stop): Check target_is_non_stop_p instead of non_stop.
> 	(linux_nat_add_target): Install linux_nat_always_non_stop_p.
> 	* target-delegates.c: Regenerate.
> 	* target.c (target_is_non_stop_p): New function.
> 	(target_non_stop_enabled, target_non_stop_enabled_1): New globals.
> 	(maint_set_target_non_stop_command)
> 	(maint_show_target_non_stop_command): New functions.
> 	(_initilize_target): Install "maint set/show target-non-stop"
> 	commands.
> 	* target.h (struct target_ops) <to_always_non_stop_p>: New field.
> 	(target_non_stop_enabled): New declaration.
> 	(target_is_non_stop_p): New declaration.
> 
> gdb/doc/ChangeLog:
> 2015-04-07  Pedro Alves  <palves@redhat.com>
> 
> 	* gdb.texinfo (Maintenance Commands): Document "maint set/show
> 	target-non-stop".
> 
> v2:
> 
>  - Documentation adjusted per Eli's review.  NEWS entry added.
>  - `proceed' change simplified, thanks to fixes in v2 of previous
>    patches in the series.

OK for the documentation parts.

Thanks.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too
  2015-04-07 13:30 ` [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too Pedro Alves
@ 2015-04-08  9:28   ` Yao Qi
  2015-04-13 10:47     ` Pedro Alves
  0 siblings, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-08  9:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> +static int
> +thread_still_needs_step_over (struct thread_info *tp)
> +{
> +  struct inferior *inf = find_inferior_ptid (tp->ptid);

'inf' isn't used.

> @@ -6327,6 +6357,8 @@ keep_going (struct execution_control_state *ecs)
>        else
>  	clear_step_over_info ();
>  
> +      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
> +
>        /* Stop stepping if inserting breakpoints fails.  */
>        TRY
>  	{
> @@ -6341,8 +6373,6 @@ keep_going (struct execution_control_state *ecs)
>  	}
>        END_CATCH
>  
> -      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
> -

Why do we hoist this line in front of the TRY/CATCH block? because we
want to set control.trap_expected before insert_breakpoints which may
throw exception?  We need a ChangeLog entry for it.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
  2015-04-07 13:36   ` Eli Zaretskii
@ 2015-04-08  9:34   ` Yao Qi
  2015-04-08  9:53     ` Pedro Alves
  1 sibling, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-08  9:34 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> @@ -1997,7 +1998,7 @@ start_step_over_inferior (struct inferior *inf)
>  	{
>  	  /* In all-stop, we shouldn't have resumed unless we needed a
>  	     step over.  */
> -	  gdb_assert (non_stop);
> +	  gdb_assert (target_is_non_stop_p ());
>  	}
>      }

Hi Pedro,
I tested the whole series on arm-linux and there is an assert triggered
with gdbserver,

signal SIGTRAP^M
Continuing with signal SIGTRAP.^M
../../../binutils-gdb/gdb/infrun.c:2008: internal-error: start_step_over_inferior: Assertion `target_is_non_stop_p ()' failed.^M
A problem internal to GDB has been detected,^M
further debugging may prove unreliable.^M
Quit this debugging session? (y or n) FAIL: gdb.threads/signal-sigtrap.exp: sigtrap thread 2: signal SIGTRAP reaches handler (GDB internal error)

there is no such internal error in native testing.  I haven't analyse it
carefully yet.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (22 preceding siblings ...)
  2015-04-07 13:30 ` [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too Pedro Alves
@ 2015-04-08  9:45 ` Yao Qi
  2015-04-08 10:17   ` Pedro Alves
  2015-04-10  8:22 ` Yao Qi
  24 siblings, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-08  9:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> While v1 had only been tested on x86-64 GNU/Linux, v2 was tested on:
>
>      x86-64 GNU/Linux
>      x86-64 GNU/Linux on top of software single-step branch
>      PPC64 GNU/Linux
>      S/390 GNU/Linux

Hi Pedro,
I tested this patch series on arm GNU/Linux, both native and gdbserver.
Overall, the results look pretty good, here are some fails
exposed/caused by this series.  I'd like to post them first today and
take a look at this series then.

1, on gdbserver,
-UNSUPPORTED: gdb.mi/mi-dprintf.exp: send dprintf to target
+FAIL: gdb.mi/mi-dprintf.exp: mi expect stop (unknown output after running)
+FAIL: gdb.mi/mi-dprintf.exp: mi 1st dprintf, agent (unknown output after running)
+FAIL: gdb.mi/mi-dprintf.exp: mi info dprintf second time
+FAIL: gdb.mi/mi-dprintf.exp: mi 2nd dprintf, agent (timeout)

BEFORE:
220-exec-continue^M
220^error,msg="Warning:\nCannot insert breakpoint 3: Target doesn't support breakpoints that have target side commands.\nCannot insert breakpoint 4: Target doesn't support breakpoints that have target side commands.\n"^M
(gdb) ^M
UNSUPPORTED: gdb.mi/mi-dprintf.exp: send dprintf to target

AFTER:
220-exec-continue^M
220^running^M
*running,thread-id="all"^M
(gdb) ^M

I think that is the mi-dprintf.exp issue, which doesn't detect target
dprintf support correctly.

2, on gdbserver,
+FAIL: gdb.threads/thread-find.exp: find lwp id 6
+FAIL: gdb.threads/thread-find.exp: find lwp id 5
+FAIL: gdb.threads/thread-find.exp: find lwp id 4
+FAIL: gdb.threads/thread-find.exp: find lwp id 3
+FAIL: gdb.threads/thread-find.exp: find lwp id 2
+FAIL: gdb.threads/thread-find.exp: find lwp id 1
thread find 18340^M
No threads match '18340'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 6
thread find 18339^M
No threads match '18339'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 5
thread find 18338^M
No threads match '18338'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 4
thread find 18337^M
No threads match '18337'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 3
thread find 18336^M
No threads match '18336'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 2
thread find 18333^M
No threads match '18333'^M
(gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 1

Maybe, thread list in GDB side is out of date?

3, on native,
-PASS: gdb.base/info-shared.exp: continue to breakpoint: library function #4
+FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4

continue^M
Continuing.^M
^M
Program received signal SIGSEGV, Segmentation fault.^M
0x40021564 in ?? () gdb/testsuite/gdb.base/info-shared-solib1.so^M
(gdb) FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-08  9:34   ` Yao Qi
@ 2015-04-08  9:53     ` Pedro Alves
  2015-04-08 11:08       ` Pedro Alves
  0 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-08  9:53 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 10:34 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> @@ -1997,7 +1998,7 @@ start_step_over_inferior (struct inferior *inf)
>>  	{
>>  	  /* In all-stop, we shouldn't have resumed unless we needed a
>>  	     step over.  */
>> -	  gdb_assert (non_stop);
>> +	  gdb_assert (target_is_non_stop_p ());
>>  	}
>>      }
> 
> Hi Pedro,
> I tested the whole series on arm-linux and there is an assert triggered
> with gdbserver,
> 
> signal SIGTRAP^M
> Continuing with signal SIGTRAP.^M
> ../../../binutils-gdb/gdb/infrun.c:2008: internal-error: start_step_over_inferior: Assertion `target_is_non_stop_p ()' failed.^M
> A problem internal to GDB has been detected,^M
> further debugging may prove unreliable.^M
> Quit this debugging session? (y or n) FAIL: gdb.threads/signal-sigtrap.exp: sigtrap thread 2: signal SIGTRAP reaches handler (GDB internal error)
> 
> there is no such internal error in native testing.  I haven't analyse it
> carefully yet.

Interesting.  I hadn't tested gdbserver with the series applied on
top of my x86-64 software single-step branch.  But running signal-sigtrap.exp
against that trips on that assert too.  The test does passes cleanly against
gdbserver with hardware single-step (x86-64).  I'll take a look.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-08  9:45 ` [PATCH v2 00/23] All-stop on top of non-stop Yao Qi
@ 2015-04-08 10:17   ` Pedro Alves
  2015-04-08 10:30     ` Pedro Alves
  2015-04-10  8:41     ` Yao Qi
  0 siblings, 2 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-08 10:17 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 10:45 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> While v1 had only been tested on x86-64 GNU/Linux, v2 was tested on:
>>
>>      x86-64 GNU/Linux
>>      x86-64 GNU/Linux on top of software single-step branch
>>      PPC64 GNU/Linux
>>      S/390 GNU/Linux
> 
> Hi Pedro,
> I tested this patch series on arm GNU/Linux, both native and gdbserver.
> Overall, the results look pretty good, here are some fails
> exposed/caused by this series.  I'd like to post them first today and
> take a look at this series then.
> 
> 1, on gdbserver,
> -UNSUPPORTED: gdb.mi/mi-dprintf.exp: send dprintf to target
> +FAIL: gdb.mi/mi-dprintf.exp: mi expect stop (unknown output after running)
> +FAIL: gdb.mi/mi-dprintf.exp: mi 1st dprintf, agent (unknown output after running)
> +FAIL: gdb.mi/mi-dprintf.exp: mi info dprintf second time
> +FAIL: gdb.mi/mi-dprintf.exp: mi 2nd dprintf, agent (timeout)
> 
> BEFORE:
> 220-exec-continue^M
> 220^error,msg="Warning:\nCannot insert breakpoint 3: Target doesn't support breakpoints that have target side commands.\nCannot insert breakpoint 4: Target doesn't support breakpoints that have target side commands.\n"^M
> (gdb) ^M
> UNSUPPORTED: gdb.mi/mi-dprintf.exp: send dprintf to target
> 
> AFTER:
> 220-exec-continue^M
> 220^running^M
> *running,thread-id="all"^M
> (gdb) ^M
> 
> I think that is the mi-dprintf.exp issue, which doesn't detect target
> dprintf support correctly.

Sounds like it.  Though I can't see how the series could have
changed the result.  Maybe it's racy.  Passes for me with
x86_64 gdbserver with and without software single-step.

> 
> 2, on gdbserver,
> +FAIL: gdb.threads/thread-find.exp: find lwp id 6
> +FAIL: gdb.threads/thread-find.exp: find lwp id 5
> +FAIL: gdb.threads/thread-find.exp: find lwp id 4
> +FAIL: gdb.threads/thread-find.exp: find lwp id 3
> +FAIL: gdb.threads/thread-find.exp: find lwp id 2
> +FAIL: gdb.threads/thread-find.exp: find lwp id 1
> thread find 18340^M
> No threads match '18340'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 6
> thread find 18339^M
> No threads match '18339'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 5
> thread find 18338^M
> No threads match '18338'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 4
> thread find 18337^M
> No threads match '18337'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 3
> thread find 18336^M
> No threads match '18336'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 2
> thread find 18333^M
> No threads match '18333'^M
> (gdb) FAIL: gdb.threads/thread-find.exp: find lwp id 1
> 

How odd.  Passes for me with x86_64 gdbserver+sss.

The "find lwp id" messages indicate that this:

if { [info exists lwp6] } then {
    gdb_test "echo $lwp6\\n" "$lwp6" "got lwp ids"
}

... was reached.  Are you running the testsuite with two boards
at the same time?  In that case, I'd guess that the test first
ran against the native target, which left $lwp6 set, and then
it run against gdbserver, with $lwp6 stale.

> Maybe, thread list in GDB side is out of date?

Don't think so, there are a bunch of "info threads" calls.

> 
> 3, on native,
> -PASS: gdb.base/info-shared.exp: continue to breakpoint: library function #4
> +FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4
> 
> continue^M
> Continuing.^M
> ^M
> Program received signal SIGSEGV, Segmentation fault.^M
> 0x40021564 in ?? () gdb/testsuite/gdb.base/info-shared-solib1.so^M
> (gdb) FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4

Most of the SIGSEGV/SIGILL/SIGBUS inferior crashes I saw were
due to a displaced stepping bug.  Force disabling displaced
stepping with "set displaced off" usually "fixes" it.  The next
step I would usually take would be to run the test manually, with
"set debug infrun 1" + "set debug displaced 1" + "set debug lin-lwp 1".

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-08 10:17   ` Pedro Alves
@ 2015-04-08 10:30     ` Pedro Alves
  2015-04-10  8:41     ` Yao Qi
  1 sibling, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-08 10:30 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 11:17 AM, Pedro Alves wrote:
> How odd.  Passes for me with x86_64 gdbserver+sss.
> 
> The "find lwp id" messages indicate that this:
> 
> if { [info exists lwp6] } then {
>     gdb_test "echo $lwp6\\n" "$lwp6" "got lwp ids"
> }
> 
> ... was reached.  Are you running the testsuite with two boards
> at the same time?  In that case, I'd guess that the test first
> ran against the native target, which left $lwp6 set, and then
> it run against gdbserver, with $lwp6 stale.
> 
>> > Maybe, thread list in GDB side is out of date?
> Don't think so, there are a bunch of "info threads" calls.
> 

Confirmed, if I do that, I get the same fails:

$ make check RUNTESTFLAGS="--target_board='unix native-gdbserver' thread-find.exp"
...
Native configuration is x86_64-unknown-linux-gnu

                === gdb tests ===

Schedule of variations:
    unix
    native-gdbserver

...
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/thread-find.exp ...

                === gdb Summary for unix ===

# of expected passes            40
Running target native-gdbserver
...
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/thread-find.exp ...
FAIL: gdb.threads/thread-find.exp: find lwp id 6
FAIL: gdb.threads/thread-find.exp: find lwp id 5
FAIL: gdb.threads/thread-find.exp: find lwp id 4
FAIL: gdb.threads/thread-find.exp: find lwp id 3
FAIL: gdb.threads/thread-find.exp: find lwp id 2
FAIL: gdb.threads/thread-find.exp: find lwp id 1

                === gdb Summary for native-gdbserver ===

# of expected passes            34
# of unexpected failures        6

                === gdb Summary ===

# of expected passes            74
# of unexpected failures        6


This trivial patch fixes it:

From 8f31ed0db2fb3d34942c72c859e52857468d46e8 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 8 Apr 2015 11:25:09 +0100
Subject: [PATCH] thread-find.exp: fix stale variables

---
 gdb/testsuite/gdb.threads/thread-find.exp | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/thread-find.exp b/gdb/testsuite/gdb.threads/thread-find.exp
index 1cd39de..1508ca3 100644
--- a/gdb/testsuite/gdb.threads/thread-find.exp
+++ b/gdb/testsuite/gdb.threads/thread-find.exp
@@ -55,6 +55,9 @@ gdb_test "thread apply 6 thread name threadname_6" \
     "name thread 6"
 
 # Collect thread ids, if any.
+
+set thread6 ""
+
 gdb_test_multiple "info threads" "collect thread id" {
     -re ". 6 .*\[Tt\]hread (\[0-9a-fA-Fx\]+).* \"threadname_6\" \[^\r\n\]*" {
 	set thread6 $expect_out(1,string)
@@ -85,11 +88,14 @@ gdb_test_multiple "info threads" "collect thread id" {
     }
 }
 
-if { [info exists thread6] } then {
+if { $thread6 != "" } then {
     gdb_test "echo $thread6\\n" "$thread6" "got thread ids"
 }
 
 # Collect process ids, if any.
+
+set process6 ""
+
 gdb_test_multiple "info threads" "collect thread id" {
     -re ". 6 .*\[Pp\]rocess (\[0-9a-fA-Fx\]+).* \"threadname_6\" \[^\r\n\]*" {
 	set process6 $expect_out(1,string)
@@ -125,6 +131,9 @@ if { [info exists process6] } then {
 }
 
 # Collect lwp ids, if any.
+
+set lwp6 ""
+
 gdb_test_multiple "info threads" "collect thread id" {
     -re ". 6 .*LWP (\[0-9a-fA-Fx\]+).* \"threadname_6\" \[^\r\n\]*" {
 	set lwp6 $expect_out(1,string)
@@ -155,7 +164,7 @@ gdb_test_multiple "info threads" "collect thread id" {
     }
 }
 
-if { [info exists lwp6] } then {
+if { $lwp6 != "" } then {
     gdb_test "echo $lwp6\\n" "$lwp6" "got lwp ids"
 }
 
@@ -180,7 +189,7 @@ gdb_test "thread find threadname_1" \
 # Test 'thread find' with thread ids, if any.
 #
 
-if { [info exists thread6] } then {
+if { $thread6 != "" } then {
     gdb_test "thread find $thread6" \
 	"Thread 6 has .*$thread6.*" "find thread id 6"
     gdb_test "thread find $thread5" \
@@ -199,7 +208,7 @@ if { [info exists thread6] } then {
 # Test 'thread find' with process ids, if any.
 #
 
-if { [info exists process6] } then {
+if { $process6 != "" } then {
     gdb_test "thread find $process6" \
 	"Thread 6 has .*$process6.*" "find process id 6"
     gdb_test "thread find $process5" \
@@ -218,7 +227,7 @@ if { [info exists process6] } then {
 # Test 'thread find' with lwp ids, if any.
 #
 
-if { [info exists lwp6] } then {
+if { $lwp6 != "" } then {
     gdb_test "thread find $lwp6" \
 	"Thread 6 has .*$lwp6.*" "find lwp id 6"
     gdb_test "thread find $lwp5" \
-- 
1.9.3


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-08  9:53     ` Pedro Alves
@ 2015-04-08 11:08       ` Pedro Alves
  2015-04-08 19:35         ` Pedro Alves
  0 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-08 11:08 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 10:52 AM, Pedro Alves wrote:
> On 04/08/2015 10:34 AM, Yao Qi wrote:
>> Pedro Alves <palves@redhat.com> writes:
>>
>>> @@ -1997,7 +1998,7 @@ start_step_over_inferior (struct inferior *inf)
>>>  	{
>>>  	  /* In all-stop, we shouldn't have resumed unless we needed a
>>>  	     step over.  */
>>> -	  gdb_assert (non_stop);
>>> +	  gdb_assert (target_is_non_stop_p ());
>>>  	}
>>>      }
>>
>> Hi Pedro,
>> I tested the whole series on arm-linux and there is an assert triggered
>> with gdbserver,
>>
>> signal SIGTRAP^M
>> Continuing with signal SIGTRAP.^M
>> ../../../binutils-gdb/gdb/infrun.c:2008: internal-error: start_step_over_inferior: Assertion `target_is_non_stop_p ()' failed.^M
>> A problem internal to GDB has been detected,^M
>> further debugging may prove unreliable.^M
>> Quit this debugging session? (y or n) FAIL: gdb.threads/signal-sigtrap.exp: sigtrap thread 2: signal SIGTRAP reaches handler (GDB internal error)
>>
>> there is no such internal error in native testing.  I haven't analyse it
>> carefully yet.
> 
> Interesting.  I hadn't tested gdbserver with the series applied on
> top of my x86-64 software single-step branch.  But running signal-sigtrap.exp
> against that trips on that assert too.  The test does passes cleanly against
> gdbserver with hardware single-step (x86-64).  I'll take a look.


The issue is that the thread that we're starting a new step-over on
has a signal to deliver as well.  So 'resume' reaches the:

  /* Currently, our software single-step implementation leads to different
     results than hardware single-stepping in one situation: when stepping
     into delivering a signal which has an associated signal handler,
     hardware single-step will stop at the first instruction of the handler,
     while software single-step will simply skip execution of the handler.

... part.  This clears trap_expected, which results in that assertion.

Hmm.  Looks like the assertion caught a pre-existing problem.
This sets up the thread to re-hit the breakpoint at PC once the
signal handler returns, and lets _all_ threads run.  But, what if had
_other_ threads that needed a step-over too?  Those will run too,
and immediately re-trap the same breakpoint, but GDB will re-report them.
Maybe we should set a step-resume breakpoint on _all_ threads that need
a step-over, not just the current.  I'll need to think a bit about this.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-08 11:08       ` Pedro Alves
@ 2015-04-08 19:35         ` Pedro Alves
  2015-04-08 19:41           ` Pedro Alves
  0 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-08 19:35 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 12:08 PM, Pedro Alves wrote:
> 
> Hmm.  Looks like the assertion caught a pre-existing problem.
> This sets up the thread to re-hit the breakpoint at PC once the
> signal handler returns, and lets _all_ threads run.  But, what if had
> _other_ threads that needed a step-over too?  Those will run too,
> and immediately re-trap the same breakpoint, but GDB will re-report them.

I thought it'd be easy to test that with multiple-step-overs.exp test, and
indeed, bad things happened.  I filed bugs and pushed the test in upfront,
as managing all these patch dependencies is getting complicated... 

 [pushed] Add test for PR18214 and PR18216 - multiple step-overs with queued signals
 https://sourceware.org/ml/gdb-patches/2015-04/msg00293.html

> Maybe we should set a step-resume breakpoint on _all_ threads that need
> a step-over, not just the current.  I'll need to think a bit about this.

That works.  I tested it with native | remote, all-stop | non-stop,
software | hardware single-step, and all pass now.

Both PR18214 and PR18216 end up fixed with this series (and this
patch).  I don't exactly (yet) which patch fixed PR18216.

I'll try moving the start_step_over_inferior hunk to the proper patch.
That bit alone should fix the signal-sigtrap.exp assertion you tripped
on.  The rest I'm planning on leaving as a separate patch.

From b0a3b75b242714cbdad0c93ddcabf00af0663d12 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 8 Apr 2015 16:59:56 +0100
Subject: [PATCH] PR18214 - multiple step overs + deliver signal, on sss
 targets

The 'resume' code that detects that we're stepping over a breakpoint
and delivering a signal at the same time:

  /* Currently, our software single-step implementation leads to different
     results than hardware single-stepping in one situation: when stepping
     into delivering a signal which has an associated signal handler,
     hardware single-step will stop at the first instruction of the handler,
     while software single-step will simply skip execution of the handler.
...
     Fortunately, we can at least fix this particular issue.  We detect
     here the case where we are about to deliver a signal while software
     single-stepping with breakpoints removed.  In this situation, we
     revert the decisions to remove all breakpoints and insert single-
     step breakpoints, and instead we install a step-resume breakpoint
     at the current address, deliver the signal without stepping, and
     once we arrive back at the step-resume breakpoint, actually step
     over the breakpoint we originally wanted to step over.  */

doesn't handle the case of another thread also needing to step over a
breakpoint.  It just resumes all threads.  And then that other thread
immediately re-traps the same breakpoint it had stopped for.

Fix it by setting a step-resume breakpoint on _all_ threads that need
a step-over, not just the current.

gdb/ChangeLog:
2015-04-08  Pedro Alves  <palves@redhat.com>

	* infrun.c (start_step_over_inferior): Assert the thread is
	executing.  If in all-stop, also return early if the thread now
	has a step resume set (to skip past a signal handler).
	(setup_step_after_step_resume_breakpoint): New function.
	(resume): When delivering a signal with software single-step, set
	a step-resume breakpoint in all threads that need a step-over, not
	just the current thread.
---
 gdb/infrun.c | 69 ++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 51 insertions(+), 18 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6511c8b..9c85628 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2001,7 +2001,11 @@ start_step_over_inferior (struct inferior *inf)
       if (!ecs->wait_some_more)
 	error (_("Command aborted."));
 
-      if (tp->control.trap_expected)
+      gdb_assert (tp->executing);
+
+      if (tp->control.trap_expected
+	  || (tp->step_after_step_resume_breakpoint
+	      && !target_is_non_stop_p ()))
 	{
 	  if (inf->step_over_queue_head == NULL)
 	    {
@@ -2206,6 +2210,26 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
   target_resume (resume_ptid, step, sig);
 }
 
+/* In order to skip a signal handler, set a high-priority step-resume
+   breakpoint the TP's current frame, and setup to step over it once
+   it is reached.  */
+
+static void
+setup_step_after_step_resume_breakpoint (struct thread_info *tp)
+{
+  /* If we have nested signals or a pending signal is delivered
+     immediately after a handler returns, we might already have a
+     step-resume breakpoint set on the earlier handler.  We cannot set
+     another step-resume breakpoint; just continue on until the
+     original breakpoint is hit.  */
+  if (tp->control.step_resume_breakpoint == NULL)
+    {
+      switch_to_thread (tp->ptid);
+      insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
+      tp->step_after_step_resume_breakpoint = 1;
+    }
+}
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
@@ -2470,6 +2494,11 @@ resume (enum gdb_signal sig)
   if (use_software_single_step && execution_direction == EXEC_FORWARD)
     gdb_assert (!step);
 
+  /* Decide the set of threads to ask the target to resume.  Start
+     by assuming everything will be resumed, than narrow the set
+     by applying increasingly restricting conditions.  */
+  resume_ptid = user_visible_resume_ptid (user_step);
+
   /* Currently, our software single-step implementation leads to different
      results than hardware single-stepping in one situation: when stepping
      into delivering a signal which has an associated signal handler,
@@ -2498,21 +2527,30 @@ resume (enum gdb_signal sig)
       && sig != GDB_SIGNAL_0
       && step_over_info_valid_p ())
     {
-      /* If we have nested signals or a pending signal is delivered
-	 immediately after a handler returns, might might already have
-	 a step-resume breakpoint set on the earlier handler.  We cannot
-	 set another step-resume breakpoint; just continue on until the
-	 original breakpoint is hit.  */
-      if (tp->control.step_resume_breakpoint == NULL)
-	{
-	  insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
-	  tp->step_after_step_resume_breakpoint = 1;
-	}
+      clear_step_over_info ();
+      tp->control.trap_expected = 0;
 
       delete_single_step_breakpoints (tp);
 
-      clear_step_over_info ();
-      tp->control.trap_expected = 0;
+      setup_step_after_step_resume_breakpoint (tp);
+
+      if (!target_is_non_stop_p ())
+	{
+	  struct thread_info *current = tp;
+
+	  ALL_NON_EXITED_THREADS (tp)
+	    if (ptid_match (tp->ptid, resume_ptid))
+	      {
+		if (tp->step_over_next != NULL)
+		  {
+		    thread_step_over_chain_remove (tp);
+		    setup_step_after_step_resume_breakpoint (tp);
+		  }
+	      }
+
+	  tp = current;
+	  switch_to_thread (tp->ptid);
+	}
 
       insert_breakpoints ();
     }
@@ -2523,11 +2561,6 @@ resume (enum gdb_signal sig)
   if (use_software_single_step)
     gdb_assert (!(thread_has_single_step_breakpoints_set (tp) && step));
 
-  /* Decide the set of threads to ask the target to resume.  Start
-     by assuming everything will be resumed, than narrow the set
-     by applying increasingly restricting conditions.  */
-  resume_ptid = user_visible_resume_ptid (user_step);
-
   /* Maybe resume a single thread after all.  */
   if (target_is_non_stop_p ())
     {
-- 
1.9.3


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode
  2015-04-08 19:35         ` Pedro Alves
@ 2015-04-08 19:41           ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-08 19:41 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 08:35 PM, Pedro Alves wrote:
> On 04/08/2015 12:08 PM, Pedro Alves wrote:
>>
>> Hmm.  Looks like the assertion caught a pre-existing problem.
>> This sets up the thread to re-hit the breakpoint at PC once the
>> signal handler returns, and lets _all_ threads run.  But, what if had
>> _other_ threads that needed a step-over too?  Those will run too,
>> and immediately re-trap the same breakpoint, but GDB will re-report them.
> 
> I thought it'd be easy to test that with multiple-step-overs.exp test, and
> indeed, bad things happened.  I filed bugs and pushed the test in upfront,
> as managing all these patch dependencies is getting complicated... 
> 
>  [pushed] Add test for PR18214 and PR18216 - multiple step-overs with queued signals
>  https://sourceware.org/ml/gdb-patches/2015-04/msg00293.html
> 
>> Maybe we should set a step-resume breakpoint on _all_ threads that need
>> a step-over, not just the current.  I'll need to think a bit about this.
> 
> That works.  I tested it with native | remote, all-stop | non-stop,
> software | hardware single-step, and all pass now.

Oh, I almost forgot, I also needed to move the pending waitstatus handling
to restart_threads.  The "If some thread needs to start a step-over
at this point" assertion just below triggers otherwise.  I'll fold this
into the "Teach non-stop to do in-line step-overs" patch.

diff --git a/gdb/infrun.c b/gdb/infrun.c
index cce29fe..3a12c2b 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4918,6 +4918,18 @@ restart_threads (struct thread_info *event_thread)
 	  continue;
 	}
 
+
+      if (tp->suspend.waitstatus_pending_p)
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: restart threads: "
+				"[%s] has pending status\n",
+				target_pid_to_str (tp->ptid));
+	  tp->resumed = 1;
+	  continue;
+	}
+
       /* If some thread needs to start a step-over at this point, it
 	 should still be in the step-over queue, and thus skipped
 	 above.  */
@@ -6504,6 +6516,8 @@ keep_going_stepped_thread (struct thread_info *tp)
 
   if (tp->suspend.waitstatus_pending_p)
     {
+      abort ();
+
       if (debug_infrun)
 	{
 	  char *statstr;

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols
  2015-04-07 12:50 ` [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols Pedro Alves
@ 2015-04-09 12:46   ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-09 12:46 UTC (permalink / raw)
  To: gdb-patches

On 04/07/2015 01:49 PM, Pedro Alves wrote:
> Running break-interp.exp with the target always in non-stop mode trips
> on PR13858, as enabling non-stop also enables displaced stepping.
> 
> The problem is that when GDB doesn't know where the entry point is, it
> doesn't know where to put the displaced stepping scratch pad.  The
> test added by this commit exercises this.  Without the fix, we get:
> 
>  (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: break *$pc
>  set displaced-stepping on
>  (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: set displaced-stepping on
>  stepi
>  0x00000000004005be in ?? ()
>  Entry point address is not known.
>  (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: stepi
>  p /x $pc
>  $2 = 0x4005be
>  (gdb) PASS: gdb.base/step-over-no-symbols.exp: displaced=on: get after PC
>  FAIL: gdb.base/step-over-no-symbols.exp: displaced=on: advanced
> 
> The fix is to fall back to stepping over the breakpoint in-line if we
> don't know where the entry point address is.
> 
> This is enough to fix all-stop + "set displaced on".  For non-stop,
> we'll need to teach core gdb to pause all threads to be able to start
> the in-line step-over (because then we need to remove the breakpoint
> from the target temporarily).

Hmm, actually not all targets get the entry point from symbols -- when
Cell debugging is enabled, PPC gets the entry point from AT_ENTRY from
the auxv...  We should probably make that the default on GNU/Linux.
I just tried that now on x86-64 and it worked fine.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
                   ` (23 preceding siblings ...)
  2015-04-08  9:45 ` [PATCH v2 00/23] All-stop on top of non-stop Yao Qi
@ 2015-04-10  8:22 ` Yao Qi
  2015-04-10  8:34   ` Pedro Alves
  24 siblings, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-10  8:22 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> While v1 had only been tested on x86-64 GNU/Linux, v2 was tested on:
>
>      x86-64 GNU/Linux
>      x86-64 GNU/Linux on top of software single-step branch
>      PPC64 GNU/Linux
>      S/390 GNU/Linux

I also tested this series on aarch64 GNU/Linux (hardware single step, no
displaced stepping) with GDBserver.  Some regressions in
gdb.threads/non-stop-fair-events.exp.

(gdb) PASS: gdb.threads/non-stop-fair-events.exp: signal_thread=2: continue &
^M
Program received signal SIGUSR1, User defined signal 1.^M
FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 1 broke out of loop (timeout)
FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 2 broke out of loop (timeout)
FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 3 broke out of loop (timeout)

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-10  8:22 ` Yao Qi
@ 2015-04-10  8:34   ` Pedro Alves
  2015-04-10  9:26     ` Yao Qi
  0 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-10  8:34 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/10/2015 09:21 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> While v1 had only been tested on x86-64 GNU/Linux, v2 was tested on:
>>
>>      x86-64 GNU/Linux
>>      x86-64 GNU/Linux on top of software single-step branch
>>      PPC64 GNU/Linux
>>      S/390 GNU/Linux
> 
> I also tested this series on aarch64 GNU/Linux (hardware single step, no

Thanks!

> displaced stepping) with GDBserver.  Some regressions in
> gdb.threads/non-stop-fair-events.exp.
> 
> (gdb) PASS: gdb.threads/non-stop-fair-events.exp: signal_thread=2: continue &
> ^M
> Program received signal SIGUSR1, User defined signal 1.^M
> FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 1 broke out of loop (timeout)
> FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 2 broke out of loop (timeout)
> FAIL: gdb.threads/non-stop-fair-events.exp: signal_thread=2: thread 3 broke out of loop (timeout)

Fun.   TBC, that was only with gdbserver, right?

I suspect the test was only passing by change before though.
AFAICS, aarch64 doesn't have a displaced stepping implementation.
I'd suspect current master fails other non-stop tests? (and hopefully
this series fixes them).

So GDB should now be falling back to stopping all threads to
step past the breakpoint on aarch64, while before threads were
just missing breakpoints.   Likely something wrong with that
with remote targets still.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-08 10:17   ` Pedro Alves
  2015-04-08 10:30     ` Pedro Alves
@ 2015-04-10  8:41     ` Yao Qi
  2015-04-10  8:50       ` Pedro Alves
  1 sibling, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-10  8:41 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Yao Qi, gdb-patches

Pedro Alves <palves@redhat.com> writes:

>> 3, on native,
>> -PASS: gdb.base/info-shared.exp: continue to breakpoint: library function #4
>> +FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4
>> 
>> continue^M
>> Continuing.^M
>> ^M
>> Program received signal SIGSEGV, Segmentation fault.^M
>> 0x40021564 in ?? () gdb/testsuite/gdb.base/info-shared-solib1.so^M
>> (gdb) FAIL: gdb.base/info-shared.exp: continue to breakpoint:
>> library function #4
>
> Most of the SIGSEGV/SIGILL/SIGBUS inferior crashes I saw were
> due to a displaced stepping bug.  Force disabling displaced
> stepping with "set displaced off" usually "fixes" it.  The next
> step I would usually take would be to run the test manually, with
> "set debug infrun 1" + "set debug displaced 1" + "set debug lin-lwp 1".

Yeah, it is a bug in displaced stepping... Here is the patch to fix it.

-- 
Yao (齐尧)

From: Yao Qi <yao.qi@linaro.org>
Subject: [PATCH] [arm] Fix displaced stepping for thumb alu reg instruction

Recent patch series "V2 All-stop on top of non-stop" causes a SIGSEGV
in the test case,

> -PASS: gdb.base/info-shared.exp: continue to breakpoint: library function #4
> +FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4
>
> continue^M
> Continuing.^M
> ^M
> Program received signal SIGSEGV, Segmentation fault.^M
> 0x40021564 in ?? () gdb/testsuite/gdb.base/info-shared-solib1.so^M
> (gdb) FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4

and an ARM displaced stepping bug is exposed.  It can be reproduced by
the modified gdb.arch/arm-disp-step.exp as below,

continue^M
Continuing.^M
^M
Program received signal SIGSEGV, Segmentation fault.^M
0xa713cfcc in ?? ()^M
(gdb) FAIL: gdb.arch/arm-disp-step.exp: continue to breakpoint: continue to test_add_rn_pc_end

This patch is to fix it.

gdb:

2015-04-09  Yao Qi  <yao.qi@linaro.org>

	* arm-tdep.c (install_alu_reg): Update comment.
	(thumb_copy_alu_reg): Remove local variable rn.  Update
	debugging message.  Use r2 instead of r1 in the modified
	instruction.

gdb/testsuite:

2015-04-09  Yao Qi  <yao.qi@linaro.org>

	* gdb.arch/arm-disp-step.S (main): Call test_add_rn_pc.
	(test_add_rn_pc): New function.
	* gdb.arch/arm-disp-step.exp (test_add_rn_pc): New proc.
	(top level): Invoke test_add_rn_pc.

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 630a207..8181f25 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -6407,7 +6407,7 @@ install_alu_reg (struct gdbarch *gdbarch, struct regcache *regs,
 
      Preparation: tmp1, tmp2, tmp3 <- r0, r1, r2;
 		  r0, r1, r2 <- rd, rn, rm
-     Insn: <op><cond> r0, r1, r2 [, <shift>]
+     Insn: <op><cond> r0, [r1,] r2 [, <shift>]
      Cleanup: rd <- r0; r0, r1, r2 <- tmp1, tmp2, tmp3
   */
 
@@ -6454,22 +6454,21 @@ thumb_copy_alu_reg (struct gdbarch *gdbarch, uint16_t insn,
 		    struct regcache *regs,
 		    struct displaced_step_closure *dsc)
 {
-  unsigned rn, rm, rd;
+  unsigned rm, rd;
 
-  rd = bits (insn, 3, 6);
-  rn = (bit (insn, 7) << 3) | bits (insn, 0, 2);
-  rm = 2;
+  rm = bits (insn, 3, 6);
+  rd = (bit (insn, 7) << 3) | bits (insn, 0, 2);
 
-  if (rd != ARM_PC_REGNUM && rn != ARM_PC_REGNUM)
+  if (rd != ARM_PC_REGNUM && rm != ARM_PC_REGNUM)
     return thumb_copy_unmodified_16bit (gdbarch, insn, "ALU reg", dsc);
 
   if (debug_displaced)
-    fprintf_unfiltered (gdb_stdlog, "displaced: copying reg %s insn %.4x\n",
-			"ALU", (unsigned short) insn);
+    fprintf_unfiltered (gdb_stdlog, "displaced: copying ALU reg insn %.4x\n",
+			(unsigned short) insn);
 
-  dsc->modinsn[0] = ((insn & 0xff00) | 0x08);
+  dsc->modinsn[0] = ((insn & 0xff00) | 0x10);
 
-  install_alu_reg (gdbarch, regs, dsc, rd, rn, rm);
+  install_alu_reg (gdbarch, regs, dsc, rd, rd, rm);
 
   return 0;
 }
diff --git a/gdb/testsuite/gdb.arch/arm-disp-step.S b/gdb/testsuite/gdb.arch/arm-disp-step.S
index c9c9447..c3b1088 100644
--- a/gdb/testsuite/gdb.arch/arm-disp-step.S
+++ b/gdb/testsuite/gdb.arch/arm-disp-step.S
@@ -78,6 +78,11 @@ test_ret_end:
 #if !defined(__thumb__)
 	bl test_str_pc
 #endif
+
+	/* Test add with pc in Thumb and Thumb-2 */
+#if defined(__thumb__)
+	bl test_add_rn_pc
+#endif
 	/* Return */
 	mov     sp, r7
 	sub     sp, sp, #4
@@ -372,3 +377,17 @@ pc_offset_wrong:
 test_str_pc_end:
 	bx lr
 #endif
+
+#if defined(__thumb__)
+	.global test_add_rn_pc
+	.code   16
+	.thumb_func
+test_add_rn_pc:
+	mov	r3, 4
+test_add_rn_pc_start:
+	add	r3, pc
+	.global test_add_rn_pc_end
+test_add_rn_pc_end:
+	bx lr
+	.size test_add_rn_pc, .-test_add_rn_pc
+#endif
diff --git a/gdb/testsuite/gdb.arch/arm-disp-step.exp b/gdb/testsuite/gdb.arch/arm-disp-step.exp
index 7eac4d1..e191f73 100644
--- a/gdb/testsuite/gdb.arch/arm-disp-step.exp
+++ b/gdb/testsuite/gdb.arch/arm-disp-step.exp
@@ -371,6 +371,45 @@ proc test_str_pc {} {
 	".*bx lr.*"
 }
 
+# Test 16 bit thumb instruction 'add rd, pc'.
+
+proc test_add_rn_pc {} {
+    global srcfile gdb_prompt
+
+    set test "break test_add_rn_pc"
+    gdb_test_multiple "break *test_add_rn_pc" $test {
+	-re "Breakpoint.*at.* file .*$srcfile, line.*\r\n$gdb_prompt $" {
+	    pass $test
+	}
+	-re "No symbol.*\r\n$gdb_prompt $" {
+	    return
+	}
+    }
+
+    gdb_continue_to_breakpoint "continue to test_add_rn_pc" \
+	".*mov.*r3, 4.*"
+
+    gdb_test "break *test_add_rn_pc_start" \
+	"Breakpoint.*at.* file .*$srcfile, line.*" \
+	"break test_add_rn_pc_start"
+
+    gdb_continue_to_breakpoint "continue to test_add_rn_pc_start" \
+	".*add.*r3,.*pc.*"
+
+    set pc_val [get_integer_valueof "\$pc" 0]
+
+    gdb_test "break *test_add_rn_pc_end" \
+	"Breakpoint.*at.* file .*$srcfile, line.*" \
+	"break test_add_rn_pc_end"
+
+    gdb_continue_to_breakpoint "continue to test_add_rn_pc_end" \
+	".*bx lr.*"
+
+    set r3_val [get_integer_valueof "\$r3" 0]
+    # Test the value in r3 is correct.
+    gdb_assert { [expr {$pc_val + 4 + 4} == $r3_val] }
+}
+
 # Get things started.
 
 clean_restart ${testfile}
@@ -410,6 +449,8 @@ test_pop_pc
 
 test_str_pc
 
+test_add_rn_pc
+
 ##########################################
 
 # Done, run program to exit.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-10  8:41     ` Yao Qi
@ 2015-04-10  8:50       ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-10  8:50 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/10/2015 09:40 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>>> 3, on native,
>>> -PASS: gdb.base/info-shared.exp: continue to breakpoint: library function #4
>>> +FAIL: gdb.base/info-shared.exp: continue to breakpoint: library function #4
>>>
>>> continue^M
>>> Continuing.^M
>>> ^M
>>> Program received signal SIGSEGV, Segmentation fault.^M
>>> 0x40021564 in ?? () gdb/testsuite/gdb.base/info-shared-solib1.so^M
>>> (gdb) FAIL: gdb.base/info-shared.exp: continue to breakpoint:
>>> library function #4
>>
>> Most of the SIGSEGV/SIGILL/SIGBUS inferior crashes I saw were
>> due to a displaced stepping bug.  Force disabling displaced
>> stepping with "set displaced off" usually "fixes" it.  The next
>> step I would usually take would be to run the test manually, with
>> "set debug infrun 1" + "set debug displaced 1" + "set debug lin-lwp 1".
> 
> Yeah, it is a bug in displaced stepping... Here is the patch to fix it.

Looks great to me.  Thanks!

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-10  8:34   ` Pedro Alves
@ 2015-04-10  9:26     ` Yao Qi
  2015-04-13 15:28       ` Pedro Alves
  0 siblings, 1 reply; 47+ messages in thread
From: Yao Qi @ 2015-04-10  9:26 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Yao Qi, gdb-patches

Pedro Alves <palves@redhat.com> writes:

> Fun.   TBC, that was only with gdbserver, right?
>

Right, I just run non-stop-fair-events.exp on native aarch64-linux gdb,
they all pass.

> I suspect the test was only passing by change before though.

They pass before this change.

> AFAICS, aarch64 doesn't have a displaced stepping implementation.

No, aarch64 doesn't have.

> I'd suspect current master fails other non-stop tests? (and hopefully
> this series fixes them).

Current master doesn't fail other non-stop tests on aarch64-linux.  This
series doesn't change the test result except non-stop-fair-events.exp.

>
> So GDB should now be falling back to stopping all threads to
> step past the breakpoint on aarch64, while before threads were
> just missing breakpoints.   Likely something wrong with that
> with remote targets still.

I'll take a look, and see if I can find anything wrong.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets
  2015-04-07 12:50 ` [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets Pedro Alves
@ 2015-04-10  9:56   ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-10  9:56 UTC (permalink / raw)
  To: gdb-patches

On 04/07/2015 01:49 PM, Pedro Alves wrote:
> TL;DR:
> 
> When stepping over a breakpoint with displaced stepping, the core must
> be notified of all signals, otherwise the displaced step fixup code
> confuses a breakpoint trap in the signal handler for the expected trap
> indicating the displaced instruction was single-stepped
> normally/successfully.

I'm fairly sure this is correct.  With Yao's extra testing, I'm
even more confident.  I pushed this one in now.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping
  2015-04-07 12:57 ` [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping Pedro Alves
@ 2015-04-10 14:54   ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-10 14:54 UTC (permalink / raw)
  To: gdb-patches

On 04/07/2015 01:49 PM, Pedro Alves wrote:
> These tests exercise the infrun.c:proceed code that needs to know to
> start new step overs (along with switch_back_to_stepped_thread, etc.).
> That code is tricky to get right in the multitude of possible
> combinations (at least):
> 
>  (native | remote)
>   X (all-stop | all-stop-but-target-always-in-non-stop)
>   X (displaced-stepping | in-line step-over).
> 
> The first two above are properties of the target, but the different
> step-over-breakpoint methods should work with any target that supports
> them.  This patch makes sure we always test both methods on all
> targets.
> 
> gdb/testsuite/ChangeLog:
> 2015-04-07  Pedro Alves  <palves@redhat.com>
> 
> 	* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): New
> 	procedure, factored out from ...
> 	(top level): ... here.  Add "set displaced-stepping" testing axis.
> 	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): New
> 	parameter "displaced".  Use it.
> 	(top level): Use foreach and add "set displaced-stepping" testing
> 	axis.

I went ahead and pushed this one in too.  If this exposes problems on
other ports, the sooner we know them the better...

---
From c79d856c88fbc58584d811c04b4812618aa6ac7b Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Fri, 10 Apr 2015 15:22:38 +0100
Subject: [PATCH] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp
 with displaced stepping

These tests exercise the infrun.c:proceed code that needs to know to
start new step overs (along with switch_back_to_stepped_thread, etc.).
That code is tricky to get right in the multitude of possible
combinations (at least):

 (native | remote)
  X (all-stop | all-stop-but-target-always-in-non-stop)
  X (displaced-stepping | in-line step-over).

The first two above are properties of the target, but the different
step-over-breakpoint methods should work with any target that supports
them.  This patch makes sure we always test both methods on all
targets.

Tested on x86-64 Fedora 20.

gdb/testsuite/ChangeLog:
2015-04-10  Pedro Alves  <palves@redhat.com>

	* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): New
	procedure, factored out from ...
	(top level): ... here.  Add "set displaced-stepping" testing axis.
	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): New
	parameter "displaced".  Use it.
	(top level): Use foreach and add "set displaced-stepping" testing
	axis.
---
 gdb/testsuite/ChangeLog                            | 10 +++++++++
 .../gdb.threads/step-over-lands-on-breakpoint.exp  | 22 +++++++++++++++++---
 .../gdb.threads/step-over-trips-on-watchpoint.exp  | 24 +++++++++++++++-------
 3 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ec319ab..0d5d07f 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,15 @@
 2015-04-10  Pedro Alves  <palves@redhat.com>
 
+	* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): New
+	procedure, factored out from ...
+	(top level): ... here.  Add "set displaced-stepping" testing axis.
+	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): New
+	parameter "displaced".  Use it.
+	(top level): Use foreach and add "set displaced-stepping" testing
+	axis.
+
+2015-04-10  Pedro Alves  <palves@redhat.com>
+
 	* gdb.threads/step-over-trips-on-watchpoint.c (child_function):
 	Remove comment.
 	* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): Find
diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
index 1e12314..52b59ec 100644
--- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp
@@ -24,15 +24,20 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
     return -1
 }
 
-# Cover both stepping and non-stepping execution commands.
-foreach command {"step" "next" "continue" } {
-    with_test_prefix $command {
+# The test proper.  DISPLACED is true if we should try with displaced
+# stepping.  COMMAND is the execution command to test.
+proc do_test {displaced command} {
+    global executable
+
+    with_test_prefix "displaced=$displaced: $command" {
 	clean_restart $executable
 
 	if ![runto_main] {
 	    continue
 	}
 
+	gdb_test_no_output "set displaced-stepping $displaced"
+
 	gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"]
 	gdb_continue_to_breakpoint "run to wait-thread breakpoint"
 	gdb_test "info threads" "2 .*\\\* 1.*" "info threads shows all threads"
@@ -60,3 +65,14 @@ foreach command {"step" "next" "continue" } {
 	gdb_test "$command" "step-over here.*"
     }
 }
+
+foreach displaced { "off" "on" } {
+    if { $displaced != "off" && ![support_displaced_stepping] } {
+	continue
+    }
+
+    # Cover both stepping and non-stepping execution commands.
+    foreach command { "step" "next" "continue" } {
+	do_test $displaced $command
+    }
+}
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
index 17cd758..aa983f7 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
@@ -31,7 +31,11 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
     return -1
 }
 
-proc do_test { with_bp } {
+# The test proper.  DISPLACED is true if we should try with displaced
+# stepping.  WITH_BP is true if we should try with a thread-specific
+# breakpoint (for the wrong thread) right after the instruction that
+# triggers the watchpoint.
+proc do_test { displaced with_bp } {
     global executable
     global gdb_prompt
     global hex
@@ -41,7 +45,7 @@ proc do_test { with_bp } {
     } else {
 	set prefix "no thread-specific bp"
     }
-    with_test_prefix $prefix {
+    with_test_prefix "displaced=$displaced: $prefix" {
 	# Cover both stepping and non-stepping execution commands.
 	foreach command {"step" "next" "continue" } {
 	    with_test_prefix $command {
@@ -51,6 +55,8 @@ proc do_test { with_bp } {
 		    continue
 		}
 
+		gdb_test_no_output "set displaced-stepping $displaced"
+
 		gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"]
 		gdb_continue_to_breakpoint "run to wait-thread breakpoint"
 		gdb_test "info threads" "2 .*\\\* 1.*" "info threads shows all threads"
@@ -99,9 +105,6 @@ proc do_test { with_bp } {
 		gdb_test "watch watch_me" "Hardware watchpoint .*"
 
 		if ${with_bp} {
-		    # Set a thread-specific breakpoint (for the wrong
-		    # thread) right after instruction that triggers
-		    # the watchpoint.
 		    gdb_test "b *$after_address_triggers_watch thread 1"
 		}
 
@@ -120,5 +123,12 @@ proc do_test { with_bp } {
     }
 }
 
-do_test 0
-do_test 1
+foreach displaced { "off" "on" } {
+    if { $displaced != "off" && ![support_displaced_stepping] } {
+	continue
+    }
+
+    foreach with_bp { 0 1 } {
+	do_test $displaced $with_bp
+    }
+}
-- 
1.9.3


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too
  2015-04-08  9:28   ` Yao Qi
@ 2015-04-13 10:47     ` Pedro Alves
  0 siblings, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-13 10:47 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/08/2015 10:28 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> +static int
>> +thread_still_needs_step_over (struct thread_info *tp)
>> +{
>> +  struct inferior *inf = find_inferior_ptid (tp->ptid);
> 
> 'inf' isn't used.
> 

Whoops.  It used to in an older version.  Dropped.

>> @@ -6327,6 +6357,8 @@ keep_going (struct execution_control_state *ecs)
>>        else
>>  	clear_step_over_info ();
>>  
>> +      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
>> +
>>        /* Stop stepping if inserting breakpoints fails.  */
>>        TRY
>>  	{
>> @@ -6341,8 +6373,6 @@ keep_going (struct execution_control_state *ecs)
>>  	}
>>        END_CATCH
>>  
>> -      ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
>> -
> 
> Why do we hoist this line in front of the TRY/CATCH block? because we
> want to set control.trap_expected before insert_breakpoints which may
> throw exception?  We need a ChangeLog entry for it.

Short version: there's really no reason for that. I've undone that last
week, and all the testing I've been doing so far never tripped on
any problem.

The longer version is that in a earlier version of this series (never posted
anywhere), I had a version of keep_going and resume that only prepared the
resume, but did not insert breakpoints or call 'target_resume', so that we could
aggregate all the target_resume calls into a single call.  That
trap_expected set back then was still done by keep_going.  That caused a lot of
pain and so in the end, I undid all that.  When I put back the insert_breakpoints
etc code I probably put it after the trap_expected line instead
of before, probably just because it's easier to read that way, as there's a
connection between that trap_expected set and the code that comes before the
breakpoints insertion.  And then after staring at these patches for
so long, my brain just learned to ignore this diff's hunk as
not important.  :-)

Thanks!

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-10  9:26     ` Yao Qi
@ 2015-04-13 15:28       ` Pedro Alves
  2015-04-13 16:16         ` Yao Qi
  0 siblings, 1 reply; 47+ messages in thread
From: Pedro Alves @ 2015-04-13 15:28 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/10/2015 10:26 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> Fun.   TBC, that was only with gdbserver, right?
>>
> 
> Right, I just run non-stop-fair-events.exp on native aarch64-linux gdb,
> they all pass.
> 
>> I suspect the test was only passing by change before though.
> 
> They pass before this change.
> 
>> AFAICS, aarch64 doesn't have a displaced stepping implementation.
> 
> No, aarch64 doesn't have.
> 
>> I'd suspect current master fails other non-stop tests? (and hopefully
>> this series fixes them).
> 
> Current master doesn't fail other non-stop tests on aarch64-linux.  This
> series doesn't change the test result except non-stop-fair-events.exp.
> 
>>
>> So GDB should now be falling back to stopping all threads to
>> step past the breakpoint on aarch64, while before threads were
>> just missing breakpoints.   Likely something wrong with that
>> with remote targets still.
> 
> I'll take a look, and see if I can find anything wrong.

With displaced stepping disabled on x86, I can reproduce it
sometimes here too.  The issue seems to be that we're constantly
bouncing between the events of the same two threads over and over,
and thus the signal event is never processed.  Exactly the sort
of issue the test is meant to catch.   Hurray, I guess?  :-)
I've been testing with the patch below, and it seems to fix it.
Testing against gdbserver + software single-step + displaced
stepping disabled caught a couple other issues too.  I'm testing
this further and cleaning it all up now.

Thanks,
Pedro Alves

commit 9112338313db3a23b9abb4d2176ce6f62498dc08
Author:     Pedro Alves <palves@redhat.com>
AuthorDate: Mon Apr 13 14:16:27 2015 +0100

    better randomization

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 4dd25d6..334d153 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4154,6 +4154,82 @@ switch_to_thread_cleanup (void *ptid_p)
   switch_to_thread (ptid);
 }
 
+/* Save the thread's event and stop reason to process it later.  */
+
+static void
+save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
+{
+  struct regcache *regcache;
+  struct address_space *aspace;
+
+  if (debug_infrun)
+    {
+      char *statstr;
+
+      statstr = target_waitstatus_to_string (ws);
+      fprintf_unfiltered (gdb_stdlog,
+			  "infrun: saving status %s for %d.%ld.%ld\n",
+			  statstr,
+			  ptid_get_pid (tp->ptid),
+			  ptid_get_lwp (tp->ptid),
+			  ptid_get_tid (tp->ptid));
+      xfree (statstr);
+    }
+
+  /* Record for later.  */
+  tp->suspend.waitstatus = *ws;
+  tp->suspend.waitstatus_pending_p = 1;
+
+  regcache = get_thread_regcache (tp->ptid);
+  aspace = get_regcache_aspace (regcache);
+
+  if (ws->kind == TARGET_WAITKIND_STOPPED
+      && ws->value.sig == GDB_SIGNAL_TRAP)
+    {
+      CORE_ADDR pc = regcache_read_pc (regcache);
+
+      adjust_pc_after_break (tp, &tp->suspend.waitstatus);
+
+      if (thread_stopped_by_watchpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_WATCHPOINT;
+	}
+      else if (target_supports_stopped_by_sw_breakpoint ()
+	       && thread_stopped_by_sw_breakpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+	}
+      else if (target_supports_stopped_by_hw_breakpoint ()
+	       && thread_stopped_by_hw_breakpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+	}
+      else if (!target_supports_stopped_by_hw_breakpoint ()
+	       && hardware_breakpoint_inserted_here_p (aspace,
+						       pc))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+	}
+      else if (!target_supports_stopped_by_sw_breakpoint ()
+	       && software_breakpoint_inserted_here_p (aspace,
+						       pc))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+	}
+      else if (!thread_has_single_step_breakpoints_set (tp)
+	       && currently_stepping (tp))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SINGLE_STEP;
+	}
+    }
+}
+
 /* Stop all threads.  */
 
 static void
@@ -4317,61 +4393,11 @@ stop_all_threads (void)
 		    }
 
 		  /* Record for later.  */
-		  t->suspend.waitstatus = ws;
-		  t->suspend.waitstatus_pending_p = 1;
+		  save_waitstatus (t, &ws);
 
 		  sig = (ws.kind == TARGET_WAITKIND_STOPPED
 			 ? ws.value.sig : GDB_SIGNAL_0);
 
-		  regcache = get_thread_regcache (t->ptid);
-		  aspace = get_regcache_aspace (regcache);
-
-		  if (ws.kind == TARGET_WAITKIND_STOPPED
-		      && ws.value.sig == GDB_SIGNAL_TRAP)
-		    {
-		      CORE_ADDR pc = regcache_read_pc (regcache);
-
-		      adjust_pc_after_break (t, &t->suspend.waitstatus);
-
-		      if (thread_stopped_by_watchpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_WATCHPOINT;
-			}
-		      else if (target_supports_stopped_by_sw_breakpoint ()
-			       && thread_stopped_by_sw_breakpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
-			}
-		      else if (target_supports_stopped_by_hw_breakpoint ()
-			       && thread_stopped_by_hw_breakpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
-			}
-		      else if (!target_supports_stopped_by_hw_breakpoint ()
-			       && hardware_breakpoint_inserted_here_p (aspace,
-								       pc))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
-			}
-		      else if (!target_supports_stopped_by_sw_breakpoint ()
-			       && software_breakpoint_inserted_here_p (aspace,
-								       pc))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
-			}
-		      else if (!thread_has_single_step_breakpoints_set (t)
-			       && currently_stepping (t))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SINGLE_STEP;
-			}
-		    }
-
 		  if (displaced_step_fixup (t->ptid, sig) < 0)
 		    {
 		      /* Add it back to the step-over queue.  */
@@ -4379,6 +4405,7 @@ stop_all_threads (void)
 		      thread_step_over_chain_enqueue (t);
 		    }
 
+		  regcache = get_thread_regcache (t->ptid);
 		  t->suspend.stop_pc = regcache_read_pc (regcache);
 
 		  if (debug_infrun)
@@ -5033,7 +5060,13 @@ restart_threads (struct thread_info *event_thread)
       /* If some thread needs to start a step-over at this point, it
 	 should still be in the step-over queue, and thus skipped
 	 above.  */
-      gdb_assert (!thread_still_needs_step_over (tp));
+      if (thread_still_needs_step_over (tp))
+	{
+	  internal_error (__FILE__, __LINE__,
+			  "thread [%s] needs a step-over, but not in "
+			  "step-over queue\n",
+			  target_pid_to_str (tp->ptid));
+	}
 
       if (currently_stepping (tp))
 	{
@@ -5056,10 +5089,24 @@ restart_threads (struct thread_info *event_thread)
     }
 }
 
+/* Callback for iterate_over_threads.  Find a resumed thread that has
+   a pending waitstatus.  */
+
+static int
+resumed_thread_with_pending_status (struct thread_info *tp,
+				    void *arg)
+{
+  return (tp->resumed
+	  && tp->suspend.waitstatus_pending_p);
+}
+
 /* Called when we get an event that may finish an in-line or
-   out-of-line (displaced stepping) step-over started previously.  */
+   out-of-line (displaced stepping) step-over started previously.
+   Return true if the event is processed and we should go back to the
+   event loop; false if the caller should continue processing the
+   event.  */
 
-static void
+static int
 finish_step_over (struct execution_control_state *ecs)
 {
   int had_step_over_info;
@@ -5081,7 +5128,7 @@ finish_step_over (struct execution_control_state *ecs)
     }
 
   if (!target_is_non_stop_p ())
-    return;
+    return 0;
 
   /* Start a new step-over in another thread if there's one that
      needs it.  */
@@ -5094,10 +5141,67 @@ finish_step_over (struct execution_control_state *ecs)
      these other threads stop.  */
   if (had_step_over_info && !step_over_info_valid_p ())
     {
+      struct thread_info *pending;
+
       restart_threads (ecs->event_thread);
 
-      gdb_assert (!ecs->event_thread->resumed);
+      /* If we have events pending, go through handle_inferior_event
+	 again, picking up a pending event at random.  This avoids
+	 thread starvation.  */
+      pending = iterate_over_threads (resumed_thread_with_pending_status,
+				      NULL);
+      if (pending != NULL)
+	{
+	  struct thread_info *tp = ecs->event_thread;
+	  struct regcache *regcache;
+
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: found resumed threads with "
+				  "pending events, saving status\n");
+	    }
+
+	  gdb_assert (pending != tp);
+
+	  /* Record the event thread's event for later.  */
+	  save_waitstatus (tp, &ecs->ws);
+	  /* This was cleared early, by handle_inferior_event.  Set it
+	     so this pending event is considered by
+	     do_target_wait.  */
+	  tp->resumed = 1;
+
+	  gdb_assert (!tp->executing);
+
+	  regcache = get_thread_regcache (tp->ptid);
+	  tp->suspend.stop_pc = regcache_read_pc (regcache);
+
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: saved stop_pc=%s for %s "
+				  "(currently_stepping=%d)\n",
+				  paddress (target_gdbarch (),
+					    tp->suspend.stop_pc),
+				  target_pid_to_str (tp->ptid),
+				  currently_stepping (tp));
+	    }
+
+	  /* This in-line step-over finished; clear this so we won't
+	     start a new one.  This is what handle_signal_stop would
+	     do, if we returned false.  */
+	  tp->stepping_over_breakpoint = 0;
+	  tp->stepping_over_watchpoint = 0;
+
+	  /* Wake up the event loop again.  */
+	  mark_async_event_handler (infrun_async_inferior_event_token);
+
+	  prepare_to_wait (ecs);
+	  return 1;
+	}
     }
+
+  return 0;
 }
 
 /* Come here when the program has stopped with a signal.  */
@@ -5116,7 +5220,8 @@ handle_signal_stop (struct execution_control_state *ecs)
   /* Do we need to clean up the state of a thread that has
      completed a displaced single-step?  (Doing so usually affects
      the PC, so do it here, before we set stop_pc.)  */
-  finish_step_over (ecs);
+  if (finish_step_over (ecs))
+    return;
 
   /* If we either finished a single-step or hit a breakpoint, but
      the user wanted this thread to be stopped, pretend we got a

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-13 15:28       ` Pedro Alves
@ 2015-04-13 16:16         ` Yao Qi
  2015-04-13 16:23           ` Pedro Alves
  2015-04-13 16:23           ` Pedro Alves
  0 siblings, 2 replies; 47+ messages in thread
From: Yao Qi @ 2015-04-13 16:16 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Yao Qi, gdb-patches

Pedro Alves <palves@redhat.com> writes:

Pedro,
I can't apply this patch cleanly, so unable to test it for
aarch64-linux.  I'll give a test once your V3 is posted, in which this
patch is included, I assume.

> +      /* If we have events pending, go through handle_inferior_event
> +	 again, picking up a pending event at random.  This avoids
> +	 thread starvation.  */
> +      pending = iterate_over_threads (resumed_thread_with_pending_status,
> +				      NULL);

A quick question, I don't see how pending events are picked up at
random.  Do you mean target_ops->to_wait, such as linux_nat_wait, can
get event at random?

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-13 16:16         ` Yao Qi
@ 2015-04-13 16:23           ` Pedro Alves
  2015-04-13 16:23           ` Pedro Alves
  1 sibling, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-13 16:23 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/13/2015 05:16 PM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
> Pedro,
> I can't apply this patch cleanly, so unable to test it for
> aarch64-linux.  I'll give a test once your V3 is posted, in which this
> patch is included, I assume.

Oh, sorry for not being clearer, I didn't meant for you to try
the patch, only to say that I got a handle in the issue, to avoid you
wasting any time trying to debug it, in case you felt compelled to do
that.  I'll post something testable once I clean things up a bit more.

> 
>> +      /* If we have events pending, go through handle_inferior_event
>> +	 again, picking up a pending event at random.  This avoids
>> +	 thread starvation.  */
>> +      pending = iterate_over_threads (resumed_thread_with_pending_status,
>> +				      NULL);
> 
> A quick question, I don't see how pending events are picked up at
> random.  Do you mean target_ops->to_wait, such as linux_nat_wait, can
> get event at random?
> 

It's done in do_target_wait.  So we go back to the event loop,
and end up in fetch_inferior_event again.  In the series/branch, that
fetch_inferior_event calls do_target_wait instead of target_wait directly:

/* Wrapper for target_wait that first checks whether threads have
   pending status to report before actually asking the target for more
   events.  */

static ptid_t
do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
{

which calls random_pending_event_thread, and that is what takes care
of the randomization.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v2 00/23] All-stop on top of non-stop
  2015-04-13 16:16         ` Yao Qi
  2015-04-13 16:23           ` Pedro Alves
@ 2015-04-13 16:23           ` Pedro Alves
  1 sibling, 0 replies; 47+ messages in thread
From: Pedro Alves @ 2015-04-13 16:23 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 04/13/2015 05:16 PM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
> Pedro,
> I can't apply this patch cleanly, so unable to test it for
> aarch64-linux.  I'll give a test once your V3 is posted, in which this
> patch is included, I assume.

Oh, sorry for not being clearer, I didn't meant for you to try
the patch, only to say that I got a handle in the issue, to avoid you
wasting any time trying to debug it, in case you felt compelled to do
that.  I'll post something testable once I clean things up a bit more.

> 
>> +      /* If we have events pending, go through handle_inferior_event
>> +	 again, picking up a pending event at random.  This avoids
>> +	 thread starvation.  */
>> +      pending = iterate_over_threads (resumed_thread_with_pending_status,
>> +				      NULL);
> 
> A quick question, I don't see how pending events are picked up at
> random.  Do you mean target_ops->to_wait, such as linux_nat_wait, can
> get event at random?
> 

It's done in do_target_wait.  So we go back to the event loop,
and end up in fetch_inferior_event again.  In the series/branch, that
fetch_inferior_event calls do_target_wait instead of target_wait directly:

/* Wrapper for target_wait that first checks whether threads have
   pending status to report before actually asking the target for more
   events.  */

static ptid_t
do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
{

which calls random_pending_event_thread, and that is what takes care
of the randomization.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2015-04-13 16:23 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-07 12:49 [PATCH v2 00/23] All-stop on top of non-stop Pedro Alves
2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
2015-04-07 13:36   ` Eli Zaretskii
2015-04-08  9:34   ` Yao Qi
2015-04-08  9:53     ` Pedro Alves
2015-04-08 11:08       ` Pedro Alves
2015-04-08 19:35         ` Pedro Alves
2015-04-08 19:41           ` Pedro Alves
2015-04-07 12:50 ` [PATCH v2 16/23] Fix signal-while-stepping-over-bp-other-thread.exp on targets always in non-stop Pedro Alves
2015-04-07 12:50 ` [PATCH v2 02/23] Fix and test "checkpoint" in non-stop mode Pedro Alves
2015-04-07 12:50 ` [PATCH v2 12/23] Misc switch_back_to_stepped_thread cleanups Pedro Alves
2015-04-07 12:50 ` [PATCH v2 20/23] PPC64: symbol-file + exec-file results in broken displaced stepping Pedro Alves
2015-04-07 12:50 ` [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with " Pedro Alves
2015-04-07 12:50 ` [PATCH v2 11/23] Use keep_going in proceed and start_step_over too Pedro Alves
2015-04-07 12:50 ` [PATCH v2 04/23] Change adjust_pc_after_break's prototype Pedro Alves
2015-04-07 12:50 ` [PATCH v2 22/23] S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions Pedro Alves
2015-04-07 12:50 ` [PATCH v2 10/23] PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping on Pedro Alves
2015-04-07 12:50 ` [PATCH v2 05/23] remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and TARGET_WNOHANG Pedro Alves
2015-04-07 12:50 ` [PATCH v2 09/23] Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86 Pedro Alves
2015-04-07 12:50 ` [PATCH v2 23/23] native Linux: enable always non-stop by default Pedro Alves
2015-04-07 12:50 ` [PATCH v2 19/23] Disable displaced stepping if trying it fails Pedro Alves
2015-04-07 12:50 ` [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets Pedro Alves
2015-04-10  9:56   ` Pedro Alves
2015-04-07 12:50 ` [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols Pedro Alves
2015-04-09 12:46   ` Pedro Alves
2015-04-07 12:55 ` [PATCH v2 17/23] Fix interrupt-noterm.exp on targets always in non-stop Pedro Alves
2015-04-07 12:57 ` [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping Pedro Alves
2015-04-10 14:54   ` Pedro Alves
2015-04-07 12:59 ` [PATCH v2 07/23] Embed the pending step-over chain in thread_info objects Pedro Alves
2015-04-07 12:59 ` [PATCH v2 13/23] Factor out code to re-resume stepped thread Pedro Alves
2015-04-07 12:59 ` [PATCH v2 14/23] Teach non-stop to do in-line step-overs (stop all, step, restart) Pedro Alves
2015-04-07 13:30 ` [PATCH v2 18/23] Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race Pedro Alves
2015-04-07 13:30 ` [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too Pedro Alves
2015-04-08  9:28   ` Yao Qi
2015-04-13 10:47     ` Pedro Alves
2015-04-08  9:45 ` [PATCH v2 00/23] All-stop on top of non-stop Yao Qi
2015-04-08 10:17   ` Pedro Alves
2015-04-08 10:30     ` Pedro Alves
2015-04-10  8:41     ` Yao Qi
2015-04-10  8:50       ` Pedro Alves
2015-04-10  8:22 ` Yao Qi
2015-04-10  8:34   ` Pedro Alves
2015-04-10  9:26     ` Yao Qi
2015-04-13 15:28       ` Pedro Alves
2015-04-13 16:16         ` Yao Qi
2015-04-13 16:23           ` Pedro Alves
2015-04-13 16:23           ` Pedro Alves

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).