Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [commit] Support displaced stepping on S/390
@ 2009-09-27 21:00 Ulrich Weigand
  2009-09-27 21:12 ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Ulrich Weigand @ 2009-09-27 21:00 UTC (permalink / raw)
  To: gdb-patches

Hello,

on s390 the non-stop cases were failing because we do not yet support
displaced stepping at all.  The following patch implements a basic
version that should support most common compiler-generated code.

Tested on s390(x)-linux, fixes the non-stop test cases.
Committed to mainline.

Bye,
Ulrich

ChangeLog:

	* s390-tdep.c (op_bctr, op_bctgr, op_bct, op1_bctg, op2_bctg,
	op_bxh, op1_bxhg, op2_bxhg, op_bxle, op1_bxleg, op2_bxleg,
	op1_brct, op2_brct, op1_brctg, op2_brctg, op_brxh, op1_brxhg,
	op2_brxhg, op_brxle, op1_brxlg, op2_brxlg): New enum values.
	(is_rsi, is_rie): New insn format decoder routines.
	(s390_displaced_step_fixup): New function.
	(s390_gdbarch_init): Install displaced stepping routines.


Index: gdb/s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.184
diff -c -p -r1.184 s390-tdep.c
*** gdb/s390-tdep.c	2 Jul 2009 17:25:58 -0000	1.184
--- gdb/s390-tdep.c	26 Sep 2009 01:05:19 -0000
*************** enum
*** 491,500 ****
--- 491,514 ----
      op_bas   = 0x4d,
      op_bcr   = 0x07,
      op_bc    = 0x0d,
+     op_bctr  = 0x06,
+     op_bctgr = 0xb946,
+     op_bct   = 0x46,
+     op1_bctg = 0xe3,   op2_bctg = 0x46,
+     op_bxh   = 0x86,
+     op1_bxhg = 0xeb,   op2_bxhg = 0x44,
+     op_bxle  = 0x87,
+     op1_bxleg= 0xeb,   op2_bxleg= 0x45,
      op1_bras = 0xa7,   op2_bras = 0x05,
      op1_brasl= 0xc0,   op2_brasl= 0x05,
      op1_brc  = 0xa7,   op2_brc  = 0x04,
      op1_brcl = 0xc0,   op2_brcl = 0x04,
+     op1_brct = 0xa7,   op2_brct = 0x06,
+     op1_brctg= 0xa7,   op2_brctg= 0x07,
+     op_brxh  = 0x84,
+     op1_brxhg= 0xec,   op2_brxhg= 0x44,
+     op_brxle = 0x85,
+     op1_brxlg= 0xec,   op2_brxlg= 0x45,
    };
  
  
*************** is_rsy (bfd_byte *insn, int op1, int op2
*** 635,640 ****
--- 649,689 ----
  
  
  static int
+ is_rsi (bfd_byte *insn, int op,
+         unsigned int *r1, unsigned int *r3, int *i2)
+ {
+   if (insn[0] == op)
+     {
+       *r1 = (insn[1] >> 4) & 0xf;
+       *r3 = insn[1] & 0xf;
+       /* i2 is a 16-bit signed quantity.  */
+       *i2 = (((insn[2] << 8) | insn[3]) ^ 0x8000) - 0x8000;
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ static int
+ is_rie (bfd_byte *insn, int op1, int op2,
+         unsigned int *r1, unsigned int *r3, int *i2)
+ {
+   if (insn[0] == op1
+       && insn[5] == op2)
+     {
+       *r1 = (insn[1] >> 4) & 0xf;
+       *r3 = insn[1] & 0xf;
+       /* i2 is a 16-bit signed quantity.  */
+       *i2 = (((insn[2] << 8) | insn[3]) ^ 0x8000) - 0x8000;
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ static int
  is_rx (bfd_byte *insn, int op,
         unsigned int *r1, unsigned int *d2, unsigned int *x2, unsigned int *b2)
  {
*************** s390_in_function_epilogue_p (struct gdba
*** 1159,1164 ****
--- 1208,1316 ----
    return 0;
  }
  
+ /* Displaced stepping.  */
+ 
+ /* Fix up the state of registers and memory after having single-stepped
+    a displaced instruction.  */
+ static void
+ s390_displaced_step_fixup (struct gdbarch *gdbarch,
+ 			   struct displaced_step_closure *closure,
+ 			   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.  */
+   gdb_byte *insn = (gdb_byte *) closure;
+   static int s390_instrlen[] = { 2, 4, 4, 6 };
+   int insnlen = s390_instrlen[insn[0] >> 6];
+ 
+   /* Fields for various kinds of instructions.  */
+   unsigned int b2, r1, r2, x2, r3;
+   int i2, d2;
+ 
+   /* Get current PC and addressing mode bit.  */
+   CORE_ADDR pc = regcache_read_pc (regs);
+   CORE_ADDR amode = 0;
+ 
+   if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+     {
+       regcache_cooked_read_unsigned (regs, S390_PSWA_REGNUM, &amode);
+       amode &= 0x80000000;
+     }
+ 
+   if (debug_displaced)
+     fprintf_unfiltered (gdb_stdlog,
+ 			"displaced: (s390) fixup (%s, %s) pc %s amode 0x%x\n",
+ 			paddress (gdbarch, from), paddress (gdbarch, to),
+ 			paddress (gdbarch, pc), (int) amode);
+ 
+   /* Handle absolute branch and save instructions.  */
+   if (is_rr (insn, op_basr, &r1, &r2)
+       || is_rx (insn, op_bas, &r1, &d2, &x2, &b2))
+     {
+       /* Recompute saved return address in R1.  */
+       regcache_cooked_write_unsigned (regs, S390_R0_REGNUM + r1,
+ 				      amode | (from + insnlen));
+     }
+ 
+   /* Handle absolute branch instructions.  */
+   else if (is_rr (insn, op_bcr, &r1, &r2)
+ 	   || is_rx (insn, op_bc, &r1, &d2, &x2, &b2)
+ 	   || is_rr (insn, op_bctr, &r1, &r2)
+ 	   || is_rre (insn, op_bctgr, &r1, &r2)
+ 	   || is_rx (insn, op_bct, &r1, &d2, &x2, &b2)
+ 	   || is_rxy (insn, op1_bctg, op2_brctg, &r1, &d2, &x2, &b2)
+ 	   || is_rs (insn, op_bxh, &r1, &r3, &d2, &b2)
+ 	   || is_rsy (insn, op1_bxhg, op2_bxhg, &r1, &r3, &d2, &b2)
+ 	   || is_rs (insn, op_bxle, &r1, &r3, &d2, &b2)
+ 	   || is_rsy (insn, op1_bxleg, op2_bxleg, &r1, &r3, &d2, &b2))
+     {
+       /* Update PC iff branch was *not* taken.  */
+       if (pc == to + insnlen)
+ 	regcache_write_pc (regs, from + insnlen);
+     }
+ 
+   /* Handle PC-relative branch and save instructions.  */
+   else if (is_ri (insn, op1_bras, op2_bras, &r1, &i2)
+            || is_ril (insn, op1_brasl, op2_brasl, &r1, &i2))
+     {
+       /* Update PC.  */
+       regcache_write_pc (regs, pc - to + from);
+       /* Recompute saved return address in R1.  */
+       regcache_cooked_write_unsigned (regs, S390_R0_REGNUM + r1,
+ 				      amode | (from + insnlen));
+     }
+ 
+   /* Handle PC-relative branch instructions.  */
+   else if (is_ri (insn, op1_brc, op2_brc, &r1, &i2)
+ 	   || is_ril (insn, op1_brcl, op2_brcl, &r1, &i2)
+ 	   || is_ri (insn, op1_brct, op2_brct, &r1, &i2)
+ 	   || is_ri (insn, op1_brctg, op2_brctg, &r1, &i2)
+ 	   || is_rsi (insn, op_brxh, &r1, &r3, &i2)
+ 	   || is_rie (insn, op1_brxhg, op2_brxhg, &r1, &r3, &i2)
+ 	   || is_rsi (insn, op_brxle, &r1, &r3, &i2)
+ 	   || is_rie (insn, op1_brxlg, op2_brxlg, &r1, &r3, &i2))
+     {
+       /* Update PC.  */
+       regcache_write_pc (regs, pc - to + from);
+     }
+ 
+   /* Handle LOAD ADDRESS RELATIVE LONG.  */
+   else if (is_ril (insn, op1_larl, op2_larl, &r1, &i2))
+     {
+       /* Recompute output address in R1.  */ 
+       regcache_cooked_write_unsigned (regs, S390_R0_REGNUM + r1,
+ 				      amode | (from + insnlen + i2*2));
+     }
+ 
+   /* If we executed a breakpoint instruction, point PC right back at it.  */
+   else if (insn[0] == 0x0 && insn[1] == 0x1)
+     regcache_write_pc (regs, from);
+ 
+   /* For any other insn, PC points right after the original instruction.  */
+   else
+     regcache_write_pc (regs, from + insnlen);
+ }
  
  /* Normal stack frames.  */
  
*************** s390_gdbarch_init (struct gdbarch_info i
*** 2398,2403 ****
--- 2550,2565 ----
    set_gdbarch_unwind_pc (gdbarch, s390_unwind_pc);
    set_gdbarch_unwind_sp (gdbarch, s390_unwind_sp);
  
+   /* Displaced stepping.  */
+   set_gdbarch_displaced_step_copy_insn (gdbarch,
+                                         simple_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);
+   set_gdbarch_displaced_step_location (gdbarch,
+                                        displaced_step_at_entry_point);
+   set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE);
+ 
    switch (info.bfd_arch_info->mach)
      {
      case bfd_mach_s390_31:
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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

* Re: [commit] Support displaced stepping on S/390
  2009-09-27 21:00 [commit] Support displaced stepping on S/390 Ulrich Weigand
@ 2009-09-27 21:12 ` Daniel Jacobowitz
  2009-09-28  9:24   ` Ulrich Weigand
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2009-09-27 21:12 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

On Sun, Sep 27, 2009 at 11:00:13PM +0200, Ulrich Weigand wrote:
> Hello,
> 
> on s390 the non-stop cases were failing because we do not yet support
> displaced stepping at all.  The following patch implements a basic
> version that should support most common compiler-generated code.
> 
> Tested on s390(x)-linux, fixes the non-stop test cases.
> Committed to mainline.

FYI, I have a local patch to issue an error if you try to connect to a
remote target in non-stop mode and the target supports non-stop but
gdb does not know how to do displaced stepping.  Clearly the check
shouldn't be remote specific - but I didn't post it because I couldn't
figure out how where to put the error to work for native too.

Attached for reference.  I am perfectly happy to commit this if
someone thinks it's an improvement, but I'd rather figure out where to
handle native first...

-- 
Daniel Jacobowitz
CodeSourcery

2009-09-21  Daniel Jacobowitz  <dan@codesourcery.com>

	gdb/
	* inferior.h (missing_displaced_stepping): Declare.
	* infrun.c (need_displaced_stepping): New function, from
	use_displaced_stepping.
	(use_displaced_stepping): Use need_displaced_stepping.
	(missing_displaced_stepping): New function.
	* remote.c (remote_start_remote): Require displaced stepping support
	for non-stop.

	gdb/testsuite/
	* lib/mi-support.exp (mi_gdb_target_cmd): Loosen non-stop error check.
	* gdb.mi/mi-nonstop-exit.exp, gdb.mi/mi-nonstop.exp,
	gdb.mi/mi-nsintrall.exp, gdb.mi/mi-nsmoribund.exp,
	gdb.mi/mi-nsthrexec.exp: Remove perror and fail after mi_run_to_main.

Index: gdb/inferior.h
===================================================================
--- gdb/inferior.h	(revision 262049)
+++ gdb/inferior.h	(revision 262050)
@@ -357,6 +357,11 @@ extern int debug_displaced;
 void displaced_step_dump_bytes (struct ui_file *file,
                                 const gdb_byte *buf, size_t len);
 
+/* Return non-zero if displaced stepping should be used to step
+   over breakpoints, but is not supported.  */
+
+int missing_displaced_stepping (struct gdbarch *gdbarch);
+
 \f
 /* Possible values for gdbarch_call_dummy_location.  */
 #define ON_STACK 1
Index: gdb/remote.c
===================================================================
--- gdb/remote.c	(revision 262049)
+++ gdb/remote.c	(revision 262050)
@@ -2788,6 +2788,9 @@ remote_start_remote (struct ui_out *uiou
       if (!rs->non_stop_aware)
 	error (_("Non-stop mode requested, but remote does not support non-stop"));
 
+      if (missing_displaced_stepping (target_gdbarch))
+	error (_("Non-stop mode requested, but displaced stepping is not supported on this architecture"));
+
       putpkt ("QNonStop:1");
       getpkt (&rs->buf, &rs->buf_size, 0);
 
Index: gdb/testsuite/lib/mi-support.exp
===================================================================
--- gdb/testsuite/lib/mi-support.exp	(revision 262049)
+++ gdb/testsuite/lib/mi-support.exp	(revision 262050)
@@ -365,7 +365,7 @@ proc mi_gdb_target_cmd { targetname seri
 		sleep 5
 		continue
 	    }
-	    -re "Non-stop mode requested, but remote does not support non-stop.*$mi_gdb_prompt" {
+	    -re "Non-stop mode requested, but .*$mi_gdb_prompt" {
 		unsupported "Non-stop mode not supported"
 		return 1
 	    }
Index: gdb/testsuite/gdb.mi/mi-nsthrexec.exp
===================================================================
--- gdb/testsuite/gdb.mi/mi-nsthrexec.exp	(revision 262049)
+++ gdb/testsuite/gdb.mi/mi-nsthrexec.exp	(revision 262050)
@@ -63,7 +63,6 @@ mi_gdb_test "-gdb-set target-async 1" ".
 detect_async
 
 if { [mi_run_to_main] < 0 } {
-    perror "mi-nsthrexec.exp tests suppressed"
     continue
 }
 
Index: gdb/testsuite/gdb.mi/mi-nsintrall.exp
===================================================================
--- gdb/testsuite/gdb.mi/mi-nsintrall.exp	(revision 262049)
+++ gdb/testsuite/gdb.mi/mi-nsintrall.exp	(revision 262050)
@@ -53,7 +53,6 @@ mi_gdb_test "-gdb-set target-async 1" ".
 detect_async
 
 if { [mi_run_to_main] < 0 } {
-    perror "mi-nsintrall.exp tests suppressed"
     continue
 }
 
Index: gdb/testsuite/gdb.mi/mi-nsmoribund.exp
===================================================================
--- gdb/testsuite/gdb.mi/mi-nsmoribund.exp	(revision 262049)
+++ gdb/testsuite/gdb.mi/mi-nsmoribund.exp	(revision 262050)
@@ -53,7 +53,6 @@ mi_gdb_test "-gdb-set target-async 1" ".
 detect_async
 
 if { [mi_run_to_main] < 0 } {
-    perror "mi-nsmoribund.exp tests suppressed"
     continue
 }
 
Index: gdb/testsuite/gdb.mi/mi-nonstop-exit.exp
===================================================================
--- gdb/testsuite/gdb.mi/mi-nonstop-exit.exp	(revision 262049)
+++ gdb/testsuite/gdb.mi/mi-nonstop-exit.exp	(revision 262050)
@@ -54,7 +54,6 @@ mi_gdb_test "-gdb-set target-async 1" ".
 detect_async
 
 if { [mi_run_to_main] < 0 } {
-    perror "mi-nonstop-exit.exp tests suppressed"
     continue
 }
 
@@ -65,7 +64,6 @@ mi_expect_stop "exited-normally" "" "" "
 # Run the program again.
 
 if { [mi_run_to_main] < 0 } {
-    fail "run (2)"
     continue
 }
 
Index: gdb/testsuite/gdb.mi/mi-nonstop.exp
===================================================================
--- gdb/testsuite/gdb.mi/mi-nonstop.exp	(revision 262049)
+++ gdb/testsuite/gdb.mi/mi-nonstop.exp	(revision 262050)
@@ -54,7 +54,6 @@ mi_gdb_test "-gdb-set target-async 1" ".
 detect_async
 
 if { [mi_run_to_main] < 0 } {
-    perror "mi-nonstop.exp tests suppressed"
     continue
 }
 
Index: gdb/infrun.c
===================================================================
--- gdb/infrun.c	(revision 262049)
+++ gdb/infrun.c	(revision 262050)
@@ -739,19 +739,38 @@ Debugger's willingness to use displaced 
 breakpoints is %s.\n"), value);
 }
 
-/* Return non-zero if displaced stepping can/should be used to step
+/* Return non-zero if displaced stepping should be used to step
    over breakpoints.  */
 
 static int
-use_displaced_stepping (struct gdbarch *gdbarch)
+need_displaced_stepping (struct gdbarch *gdbarch)
 {
   return (((can_use_displaced_stepping == can_use_displaced_stepping_auto
 	    && non_stop)
 	   || can_use_displaced_stepping == can_use_displaced_stepping_on)
-	  && gdbarch_displaced_step_copy_insn_p (gdbarch)
 	  && !RECORD_IS_USED);
 }
 
+/* Return non-zero if displaced stepping can/should be used to step
+   over breakpoints.  */
+
+static int
+use_displaced_stepping (struct gdbarch *gdbarch)
+{
+  return (need_displaced_stepping (gdbarch)
+	  && gdbarch_displaced_step_copy_insn_p (gdbarch));
+}
+
+/* Return non-zero if displaced stepping should be used to step
+   over breakpoints, but is not supported.  */
+
+int
+missing_displaced_stepping (struct gdbarch *gdbarch)
+{
+  return (need_displaced_stepping (gdbarch)
+	  && !gdbarch_displaced_step_copy_insn_p (gdbarch));
+}
+
 /* Clean out any stray displaced stepping state.  */
 static void
 displaced_step_clear (void)


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

* Re: [commit] Support displaced stepping on S/390
  2009-09-27 21:12 ` Daniel Jacobowitz
@ 2009-09-28  9:24   ` Ulrich Weigand
  2009-09-28 16:32     ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Ulrich Weigand @ 2009-09-28  9:24 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

Daniel Jacobowitz wrote:

> FYI, I have a local patch to issue an error if you try to connect to a
> remote target in non-stop mode and the target supports non-stop but
> gdb does not know how to do displaced stepping.  Clearly the check
> shouldn't be remote specific - but I didn't post it because I couldn't
> figure out how where to put the error to work for native too.
> 
> Attached for reference.  I am perfectly happy to commit this if
> someone thinks it's an improvement, but I'd rather figure out where to
> handle native first...

FWIW I agree that we should handle all targets ...

Does the decision need to be made at "attach" time?  Maybe we should
allow attaching in non-stop mode, but refuse to install breakpoints
if displaced stepping is not available?  That would at least allow
attaching to a process in non-stop mode and stopping/restarting
selected threads and inspecting their state.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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

* Re: [commit] Support displaced stepping on S/390
  2009-09-28  9:24   ` Ulrich Weigand
@ 2009-09-28 16:32     ` Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2009-09-28 16:32 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

On Mon, Sep 28, 2009 at 11:24:22AM +0200, Ulrich Weigand wrote:
> Does the decision need to be made at "attach" time?  Maybe we should
> allow attaching in non-stop mode, but refuse to install breakpoints
> if displaced stepping is not available?  That would at least allow
> attaching to a process in non-stop mode and stopping/restarting
> selected threads and inspecting their state.

We have to be able to make the decision ahead of time, though - or
we'll "run" and get an error after creating the executable that GDB
can't continue it.

-- 
Daniel Jacobowitz
CodeSourcery


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

end of thread, other threads:[~2009-09-28 16:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-27 21:00 [commit] Support displaced stepping on S/390 Ulrich Weigand
2009-09-27 21:12 ` Daniel Jacobowitz
2009-09-28  9:24   ` Ulrich Weigand
2009-09-28 16:32     ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox