public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 5/8] gdbserver/s390: Switch on tracepoint support.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (4 preceding siblings ...)
  2016-01-24 12:12 ` [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-02-07 14:04   ` Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks Marcin Kościelnicki
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Also adds s390 support to gdb.trace testsuite.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (s390_supports_tracepoints): New function.
	(struct linux_target_ops): Fill supports_tracepoints hook.

gdb/testsuite/ChangeLog:

	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
	placeholder.
	* lib/trace-support.exp: Add s390 registers.
---
 gdb/gdbserver/ChangeLog                              |  5 +++++
 gdb/gdbserver/linux-s390-low.c                       |  8 +++++++-
 gdb/testsuite/ChangeLog                              |  8 ++++++++
 gdb/testsuite/gdb.trace/ftrace.exp                   |  2 ++
 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 14 +++++++++++---
 gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
 gdb/testsuite/lib/trace-support.exp                  |  4 ++++
 7 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 5e47b46..e0d8c67 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* linux-s390-low.c (s390_supports_tracepoints): New function.
+	(struct linux_target_ops): Fill supports_tracepoints hook.
+
 2016-01-21  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* linux-s390-low.c (s390_supports_z_point_type): New function.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 420430b..ab3e62b 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -688,6 +688,12 @@ s390_regs_info (void)
   return &regs_info;
 }
 
+static int
+s390_supports_tracepoints (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -714,7 +720,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
+  s390_supports_tracepoints,
   NULL, /* get_thread_area */
   NULL, /* install_fast_tracepoint_jump_pad */
   NULL, /* emit_ops */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index a201b66..98e7970 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
+	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
+	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
+	placeholder.
+	* lib/trace-support.exp: Add s390 registers.
+
 2016-01-23  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* gdb.trace/backtrace.exp: Bump stack collection fudge factor.
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index 15ad7e7..cca3a9c 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -246,6 +246,8 @@ if [is_amd64_regs_target] {
     set arg0exp "*(int *) (\$ebp + 8)"
 } elseif { [istarget "aarch64*-*-*"] } {
     set arg0exp "\$x0"
+} elseif { [istarget "s390*-*-*"] } {
+    set arg0exp "\$r2"
 } else {
     set arg0exp ""
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 0daaa25..499d3fb 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -93,9 +93,17 @@ proc test_trace_frame_collected { data_source } {
 
 	# Test MI command '-trace-frame-collected' dumps only
 	# collected registers.
-	mi_gdb_test "-trace-frame-collected" \
-	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
-	    "-trace-frame-collected (register)"
+	if { [istarget "s390*-*-*"] } {
+	    # Only PC is collected, but on s390 PC is a pseudo-register -
+	    # collecting it also collects the underlying PSWA register.
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\},\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	} else {
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	}
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index eceb182..a330024 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -48,6 +48,14 @@ x86_trace_dummy ()
        "    nop\n" \
        )
 
+#elif (defined __s390__)
+
+#define FAST_TRACEPOINT_LABEL(name) \
+  asm ("    .global " SYMBOL(name) "\n" \
+       SYMBOL(name) ":\n" \
+       "    mvc 0(8, %r15), 0(%r15)\n" \
+       )
+
 #else
 
 #error "unsupported architecture for trace tests"
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
index f593c43..70f7b7f 100644
--- a/gdb/testsuite/lib/trace-support.exp
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -36,6 +36,10 @@ if [is_amd64_regs_target] {
     set fpreg "x29"
     set spreg "sp"
     set pcreg "pc"
+} elseif [istarget "s390*-*-*"] {
+    set fpreg "r11"
+    set spreg "r15"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
-- 
2.7.0

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

* [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (3 preceding siblings ...)
  2016-01-24 12:12 ` [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-01-26 14:58   ` Andreas Arnez
  2016-01-24 12:12 ` [PATCH 5/8] gdbserver/s390: Switch on tracepoint support Marcin Kościelnicki
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

When we're looking at a tracefile trace frame where registers are not
available, and the tracepoint has only one location, we supply
the location's address as the PC register.  However, this only works
if PC is not a pseudo register.  Add a gdbarch hook that will handle
that for pseudo registers.

gdb/ChangeLog:

	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Add write_guessed_tracepoint_pc hook.
	* tracefile.c (tracefile_fetch_registers): When PC is a pseudo,
	ask gdbarch to handle guessed PC via the new hook.
---
 gdb/ChangeLog   |  8 ++++++++
 gdb/gdbarch.c   | 32 ++++++++++++++++++++++++++++++++
 gdb/gdbarch.h   |  6 ++++++
 gdb/gdbarch.sh  |  1 +
 gdb/tracefile.c | 40 +++++++++++++++++++++++++++-------------
 5 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 057c14f..983a243 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add write_guessed_tracepoint_pc hook.
+	* tracefile.c (tracefile_fetch_registers): When PC is a pseudo,
+	ask gdbarch to handle guessed PC via the new hook.
+
 2016-01-22  John Baldwin  <jhb@FreeBSD.org>
 
 	* fbsd-nat.c (fbsd_pid_to_str): Adjust string format.
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..21942b0 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -181,6 +181,7 @@ struct gdbarch
   int char_signed;
   gdbarch_read_pc_ftype *read_pc;
   gdbarch_write_pc_ftype *write_pc;
+  gdbarch_write_guessed_tracepoint_pc_ftype *write_guessed_tracepoint_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
   gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
@@ -523,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
     gdbarch->char_signed = 1;
   /* Skip verify of read_pc, has predicate.  */
   /* Skip verify of write_pc, has predicate.  */
+  /* Skip verify of write_guessed_tracepoint_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
   /* Skip verify of pseudo_register_read_value, has predicate.  */
@@ -1402,6 +1404,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: vtable_function_descriptors = %s\n",
                       plongest (gdbarch->vtable_function_descriptors));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_write_guessed_tracepoint_pc_p() = %d\n",
+                      gdbarch_write_guessed_tracepoint_pc_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: write_guessed_tracepoint_pc = <%s>\n",
+                      host_address_to_string (gdbarch->write_guessed_tracepoint_pc));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_write_pc_p() = %d\n",
                       gdbarch_write_pc_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1821,6 +1829,30 @@ set_gdbarch_write_pc (struct gdbarch *gdbarch,
   gdbarch->write_pc = write_pc;
 }
 
+int
+gdbarch_write_guessed_tracepoint_pc_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->write_guessed_tracepoint_pc != NULL;
+}
+
+void
+gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->write_guessed_tracepoint_pc != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_write_guessed_tracepoint_pc called\n");
+  gdbarch->write_guessed_tracepoint_pc (regcache, val);
+}
+
+void
+set_gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch,
+                                         gdbarch_write_guessed_tracepoint_pc_ftype write_guessed_tracepoint_pc)
+{
+  gdbarch->write_guessed_tracepoint_pc = write_guessed_tracepoint_pc;
+}
+
 void
 gdbarch_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..9e24d15 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -239,6 +239,12 @@ typedef void (gdbarch_write_pc_ftype) (struct regcache *regcache, CORE_ADDR val)
 extern void gdbarch_write_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
 extern void set_gdbarch_write_pc (struct gdbarch *gdbarch, gdbarch_write_pc_ftype *write_pc);
 
+extern int gdbarch_write_guessed_tracepoint_pc_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_write_guessed_tracepoint_pc_ftype) (struct regcache *regcache, CORE_ADDR val);
+extern void gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
+extern void set_gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, gdbarch_write_guessed_tracepoint_pc_ftype *write_guessed_tracepoint_pc);
+
 /* Function for getting target's idea of a frame pointer.  FIXME: GDB's
    whole scheme for dealing with "frames" and "frame pointers" needs a
    serious shakedown. */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..b67ea72 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -417,6 +417,7 @@ v:int:char_signed:::1:-1:1
 #
 F:CORE_ADDR:read_pc:struct regcache *regcache:regcache
 F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
+F:void:write_guessed_tracepoint_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 # Function for getting target's idea of a frame pointer.  FIXME: GDB's
 # whole scheme for dealing with "frames" and "frame pointers" needs a
 # serious shakedown.
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index fef4ed9..7c2649d 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -396,16 +396,18 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
      as the address of the tracepoint.  */
   pc_regno = gdbarch_pc_regnum (gdbarch);
 
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (pc_regno < 0)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* We try to guess PC if:
+
+     1) We want all registers, or
+     2) PC is a real register, and we want exactly it, or
+     3) PC is a pseudo register (we don't know which real register it
+        corresponds to, so let's try to play safe).  */
+
+  if (regno == -1 || regno == pc_regno ||
+      pc_regno >= gdbarch_num_regs (gdbarch))
     {
       struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
       gdb_byte *regs;
@@ -429,11 +431,23 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 	      return;
 	    }
 
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
+	  if (pc_regno >= gdbarch_num_regs (gdbarch))
+	    {
+	      /* PC is a pseudo, let gdbarch deal with that.  If it doesn't
+	         know how, just bail.  */
+	      if (gdbarch_write_guessed_tracepoint_pc_p (gdbarch))
+	        gdbarch_write_guessed_tracepoint_pc (gdbarch, regcache,
+						     tp->base.loc->address);
+	    }
+	  else
+	    {
+	      /* PC is a real register.  */
+	      regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+	      store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+				      gdbarch_byte_order (gdbarch),
+				      tp->base.loc->address);
+	      regcache_raw_supply (regcache, pc_regno, regs);
+	    }
 	}
     }
 }
-- 
2.7.0

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

* [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-02-07 14:02   ` Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions Marcin Kościelnicki
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_gen_return_address): New function.
	(s390_gdbarch_init): Fill gen_return_address hook.
---
 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 11 +++++++++++
 2 files changed, 16 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2cfd088..e0eb258 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_gen_return_address): New function.
+	(s390_gdbarch_init): Fill gen_return_address hook.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
 	(s390_ax_pseudo_register_push_stack): New function.
 	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 00ff388..48801d2 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -617,6 +617,16 @@ s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
   return 0;
 }
 
+static void
+s390_gen_return_address (struct gdbarch *gdbarch,
+			 struct agent_expr *ax, struct axs_value *value,
+			 CORE_ADDR scope)
+{
+  value->type = register_type (gdbarch, S390_R14_REGNUM);
+  value->kind = axs_lvalue_register;
+  value->u.reg = S390_R14_REGNUM;
+}
+
 
 /* A helper for s390_software_single_step, decides if an instruction
    is a partial-execution instruction that needs to be executed until
@@ -7960,6 +7970,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					  s390_ax_pseudo_register_collect);
   set_gdbarch_ax_pseudo_register_push_stack
       (gdbarch, s390_ax_pseudo_register_push_stack);
+  set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
   set_gdbarch_register_name (gdbarch, s390_register_name);
 
-- 
2.7.0

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

* [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (5 preceding siblings ...)
  2016-01-24 12:12 ` [PATCH 5/8] gdbserver/s390: Switch on tracepoint support Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-02-07 14:01   ` Marcin Kościelnicki
  2016-01-24 12:13 ` [PATCH 6/8] gdbserver/s390: Add fast tracepoint support Marcin Kościelnicki
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
	(s390_ax_pseudo_register_push_stack): New function.
	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
	ax_pseudo_register_push_stack hooks.
---
 gdb/ChangeLog         |  7 +++++
 gdb/s390-linux-tdep.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9e92ae3..2cfd088 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
+	(s390_ax_pseudo_register_push_stack): New function.
+	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
+	ax_pseudo_register_push_stack hooks.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* s390-linux-tdep.c (s390_write_guessed_tracepoint_pc): New function.
 	(s390_gdbarch_init): Fill write_guessed_tracepoint_pc hook.
 
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index c4d25d2..00ff388 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -541,6 +541,82 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
+static int
+s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+				 struct agent_expr *ax, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (regnum == tdep->pc_regnum)
+    {
+      ax_reg_mask (ax, S390_PSWA_REGNUM);
+    }
+  else if (regnum == tdep->cc_regnum)
+    {
+      ax_reg_mask (ax, S390_PSWM_REGNUM);
+    }
+  else if (regnum_is_gpr_full (tdep, regnum))
+    {
+      regnum -= tdep->gpr_full_regnum;
+      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
+      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
+    }
+  else if (regnum_is_vxr_full (tdep, regnum))
+    {
+      regnum -= tdep->v0_full_regnum;
+      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
+      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
+  return 0;
+}
+
+static int
+s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+				    struct agent_expr *ax, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (regnum == tdep->pc_regnum)
+    {
+      ax_reg (ax, S390_PSWA_REGNUM);
+      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+        {
+	  ax_zero_ext (ax, 31);
+        }
+    }
+  else if (regnum == tdep->cc_regnum)
+    {
+      ax_reg (ax, S390_PSWM_REGNUM);
+      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+        ax_const_l (ax, 12);
+      else
+        ax_const_l (ax, 44);
+      ax_simple (ax, aop_rsh_unsigned);
+      ax_zero_ext (ax, 2);
+    }
+  else if (regnum_is_gpr_full (tdep, regnum))
+    {
+      regnum -= tdep->gpr_full_regnum;
+      ax_reg (ax, S390_R0_REGNUM + regnum);
+      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
+      ax_const_l (ax, 32);
+      ax_simple (ax, aop_lsh);
+      ax_simple (ax, aop_bit_or);
+    }
+  else if (regnum_is_vxr_full (tdep, regnum))
+    {
+      /* Too large to stuff on the stack.  */
+      return 1;
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
+  return 0;
+}
+
 
 /* A helper for s390_software_single_step, decides if an instruction
    is a partial-execution instruction that needs to be executed until
@@ -7880,6 +7956,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
   set_tdesc_pseudo_register_reggroup_p (gdbarch,
 					s390_pseudo_register_reggroup_p);
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+					  s390_ax_pseudo_register_collect);
+  set_gdbarch_ax_pseudo_register_push_stack
+      (gdbarch, s390_ax_pseudo_register_push_stack);
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
   set_gdbarch_register_name (gdbarch, s390_register_name);
 
-- 
2.7.0

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

* [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-01-26 18:12   ` Andreas Arnez
  2016-01-24 12:12 ` [PATCH 4/8] gdb/s390: Fill gen_return_address hook Marcin Kościelnicki
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_write_guessed_tracepoint_pc): New function.
	(s390_gdbarch_init): Fill write_guessed_tracepoint_pc hook.
---
 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 17 +++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 983a243..9e92ae3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_write_guessed_tracepoint_pc): New function.
+	(s390_gdbarch_init): Fill write_guessed_tracepoint_pc hook.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* gdbarch.c: Regenerate.
 	* gdbarch.h: Regenerate.
 	* gdbarch.sh: Add write_guessed_tracepoint_pc hook.
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index e827684..c4d25d2 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -167,6 +167,22 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
     regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
 }
 
+static void
+s390_write_guessed_tracepoint_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
+  gdb_byte *reg = (gdb_byte *) alloca (sz);
+
+  /* 31-bit PSWA needs high bit set.  */
+  if (tdep->abi == ABI_LINUX_S390)
+    pc |= 0x80000000;
+
+  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pc);
+  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
+}
+
 
 /* DWARF Register Mapping.  */
 
@@ -7857,6 +7873,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					    s390_iterate_over_regset_sections);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
   set_gdbarch_write_pc (gdbarch, s390_write_pc);
+  set_gdbarch_write_guessed_tracepoint_pc (gdbarch, s390_write_guessed_tracepoint_pc);
   set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
   set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
-- 
2.7.0

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

* [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-01-26 18:17   ` Andreas Arnez
  2016-01-24 12:12 ` [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook Marcin Kościelnicki
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

It seems the 180 seconds timeout is quite tight on my z13 machine,
and causes failures when the machine is somewhat loaded.

gdb/testsuite/ChangeLog:

	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
---
 gdb/testsuite/ChangeLog            | 4 ++++
 gdb/testsuite/gdb.trace/tspeed.exp | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 98e7970..9fe269f 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
 	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
 	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
index e638839..204eda7 100644
--- a/gdb/testsuite/gdb.trace/tspeed.exp
+++ b/gdb/testsuite/gdb.trace/tspeed.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
 }
 
 # Typically we need a little extra time for this test.
-set timeout 180
+set timeout 300
 
 set ws "\[\r\n\t \]+"
 set cr "\[\r\n\]+"
-- 
2.7.0

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

* [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
@ 2016-01-24 12:12 Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
                   ` (10 more replies)
  0 siblings, 11 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches

This patchset adds support for regular and fast tracepoints on
s390-ibm-linux-gnu and s390x-ibm-linux-gnu.  It depends on the following
yet-unlanded patches:

- https://sourceware.org/ml/gdb-patches/2016-01/msg00597.html (for 31-bit
  fast tracepoint support)
- https://sourceware.org/ml/gdb-patches/2016-01/msg00596.html (just
  a testsuite fix)
- https://sourceware.org/ml/gdb-patches/2016-01/msg00510.html (fixes
  setting a breakpoint and a tracepoint on the same location)

Patches 1-5 add working regular tracepoint support, patches 6-7 add
working fast tracepoint support on top of that, and patch 8 makes fast
tracepoints use compiled agent expressions.

Patches 1 and 7 are in target-independent code, the remaining ones
are in s390-specific code.

It has been tested on s390-ibm-linux-gnu and s390x-ibm-linux-gnu on
a z13 machine (without vector extensions).  The parts handling vector
extensions are untested.  It has also been regression-tested on x86_64.

There are 2 test failures still left in gdb.trace:

- gdb.trace/unavailable.exp: print derived_whole has 4 failures on 64-bit
  only.  The same failure happens on x86_64, so it's unlikely to be
  s390-specific.
- gdb.trace/mi-tsv-changed.exp: create delete modify: tvariable $tvar3
  modified is an intermittent failure.  It seems to be a race of some
  kind - in the failing runs, gdb shows the same messages, but in
  different order.  I strongly suspect this is a target-independent
  issues that only happens on s390 due to timing factors.

There are also three issues affecting s390 tracepoints that don't show
up in the testsuite:

1. Target independent: tfile format doesn't contain target information
   (tdesc).  While this affects all platforms with multiple tdescs
   (eg. x86_64 is unable to pull AVX registers from tfile for that
   reason), it horribly breaks 31-bit s390 with high GPRs - it has
   a completely different GPR layout from plain 31-bit s390, so the
   collected registers will be garbled.  I suppose the proper fix to
   that would be to add tdesc information to tfile format.  Unfortunately,
   I don't see a way to extend it in a backwards-compatible way.

2. Target independent: 32-bit (or 31-bit for us) IPA cannot be used with
   64-bit gdbserver, due to communication involving lots of structs with
   pointer types.  Fixing that would be quite involved, but possible
   (I don't suppose we have to maintain compatibility between IPA/gdbserver
   from different gdb versions?).

3. s390 specific: 31-bit gdbserver doesn't know about high GPRs, and
   cannot collect them if they're in use.  Seems fixable with average
   effort.  Unfortunately, fixing that will break tfile, unless (1)
   is fixed first...

These three interact in bad ways, summarised below:

- 64-bit linux, 64-bit gdbserver, 64-bit target: works OK, but you won't be
  able to see VX registers in tfile.

- 64-bit linux, 64-bit gdbserver, 31-bit target: 

  - no fast tracepoint support due to (2)
  - tfile completely broken due to (1)

- 64-bit linux, 31-bit gdbserver, 31-bit target:

  - works OK, but you won't be able to see VX registers or high GPRs at all,
    due to (3)
  - if (3) were fixed, tfile will be completely broken due to (1)

- 31-bit linux, 31-bit gdbserver, 31-bit target: works OK

In summary, there's no way at all to use fast tracepoints on 31-bit target
if what you want to collect involves high GPRs.  While there's support for
it in the IPA, it's currently disabled, to match what gdbserver supports.

Fast tracepoint support assumes z900+ CPU.  The g5/g6 CPUs only have jump
instuctions with +-64kiB of range, making them pretty much useless for
our purposes, so not much loss here.

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

* [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (2 preceding siblings ...)
  2016-01-24 12:12 ` [PATCH 4/8] gdb/s390: Fill gen_return_address hook Marcin Kościelnicki
@ 2016-01-24 12:12 ` Marcin Kościelnicki
  2016-03-04 10:41   ` [PATCH v2] " Marcin Kościelnicki
  2016-01-24 12:12 ` [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch Marcin Kościelnicki
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

These sequences assume a z900+ CPU, like the rest of fast tracepoint
support.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (add_insns): New function.
	(s390_emit_prologue): New function.
	(s390_emit_epilogue): New function.
	(s390_emit_add): New function.
	(s390_emit_sub): New function.
	(s390_emit_mul): New function.
	(s390_emit_lsh): New function.
	(s390_emit_rsh_signed): New function.
	(s390_emit_rsh_unsigned): New function.
	(s390_emit_ext): New function.
	(s390_emit_log_not): New function.
	(s390_emit_bit_and): New function.
	(s390_emit_bit_or): New function.
	(s390_emit_bit_xor): New function.
	(s390_emit_bit_not): New function.
	(s390_emit_equal): New function.
	(s390_emit_less_signed): New function.
	(s390_emit_less_unsigned): New function.
	(s390_emit_ref): New function.
	(s390_emit_if_goto): New function.
	(s390_emit_goto): New function.
	(s390_write_goto_address): New function.
	(s390_emit_litpool): New function.
	(s390_emit_const): New function.
	(s390_emit_call): New function.
	(s390_emit_reg): New function.
	(s390_emit_pop): New function.
	(s390_emit_stack_flush): New function.
	(s390_emit_zero_ext): New function.
	(s390_emit_swap): New function.
	(s390_emit_stack_adjust): New function.
	(s390_emit_set_r2): New function.
	(s390_emit_int_call_1): New function.
	(s390_emit_void_call_2): New function.
	(s390_emit_eq_goto): New function.
	(s390_emit_ne_goto): New function.
	(s390_emit_lt_goto): New function.
	(s390_emit_le_goto): New function.
	(s390_emit_gt_goto): New function.
	(s390_emit_ge_goto): New function.
	(s390x_emit_prologue): New function.
	(s390x_emit_epilogue): New function.
	(s390x_emit_add): New function.
	(s390x_emit_sub): New function.
	(s390x_emit_mul): New function.
	(s390x_emit_lsh): New function.
	(s390x_emit_rsh_signed): New function.
	(s390x_emit_rsh_unsigned): New function.
	(s390x_emit_ext): New function.
	(s390x_emit_log_not): New function.
	(s390x_emit_bit_and): New function.
	(s390x_emit_bit_or): New function.
	(s390x_emit_bit_xor): New function.
	(s390x_emit_bit_not): New function.
	(s390x_emit_equal): New function.
	(s390x_emit_less_signed): New function.
	(s390x_emit_less_unsigned): New function.
	(s390x_emit_ref): New function.
	(s390x_emit_if_goto): New function.
	(s390x_emit_goto): New function.
	(s390x_emit_const): New function.
	(s390x_emit_call): New function.
	(s390x_emit_reg): New function.
	(s390x_emit_pop): New function.
	(s390x_emit_stack_flush): New function.
	(s390x_emit_zero_ext): New function.
	(s390x_emit_swap): New function.
	(s390x_emit_stack_adjust): New function.
	(s390x_emit_int_call_1): New function.
	(s390x_emit_void_call_2): New function.
	(s390x_emit_eq_goto): New function.
	(s390x_emit_ne_goto): New function.
	(s390x_emit_lt_goto): New function.
	(s390x_emit_le_goto): New function.
	(s390x_emit_gt_goto): New function.
	(s390x_emit_ge_goto): New function.
	(s390_emit_ops): New function.
	(struct linux_target_ops): Fill in emit_ops hook.
---
 gdb/gdbserver/ChangeLog        |   81 +++
 gdb/gdbserver/linux-s390-low.c | 1206 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 1286 insertions(+), 1 deletion(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 1cd1a7e..a368c11 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,86 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* linux-s390-low.c (add_insns): New function.
+	(s390_emit_prologue): New function.
+	(s390_emit_epilogue): New function.
+	(s390_emit_add): New function.
+	(s390_emit_sub): New function.
+	(s390_emit_mul): New function.
+	(s390_emit_lsh): New function.
+	(s390_emit_rsh_signed): New function.
+	(s390_emit_rsh_unsigned): New function.
+	(s390_emit_ext): New function.
+	(s390_emit_log_not): New function.
+	(s390_emit_bit_and): New function.
+	(s390_emit_bit_or): New function.
+	(s390_emit_bit_xor): New function.
+	(s390_emit_bit_not): New function.
+	(s390_emit_equal): New function.
+	(s390_emit_less_signed): New function.
+	(s390_emit_less_unsigned): New function.
+	(s390_emit_ref): New function.
+	(s390_emit_if_goto): New function.
+	(s390_emit_goto): New function.
+	(s390_write_goto_address): New function.
+	(s390_emit_litpool): New function.
+	(s390_emit_const): New function.
+	(s390_emit_call): New function.
+	(s390_emit_reg): New function.
+	(s390_emit_pop): New function.
+	(s390_emit_stack_flush): New function.
+	(s390_emit_zero_ext): New function.
+	(s390_emit_swap): New function.
+	(s390_emit_stack_adjust): New function.
+	(s390_emit_set_r2): New function.
+	(s390_emit_int_call_1): New function.
+	(s390_emit_void_call_2): New function.
+	(s390_emit_eq_goto): New function.
+	(s390_emit_ne_goto): New function.
+	(s390_emit_lt_goto): New function.
+	(s390_emit_le_goto): New function.
+	(s390_emit_gt_goto): New function.
+	(s390_emit_ge_goto): New function.
+	(s390x_emit_prologue): New function.
+	(s390x_emit_epilogue): New function.
+	(s390x_emit_add): New function.
+	(s390x_emit_sub): New function.
+	(s390x_emit_mul): New function.
+	(s390x_emit_lsh): New function.
+	(s390x_emit_rsh_signed): New function.
+	(s390x_emit_rsh_unsigned): New function.
+	(s390x_emit_ext): New function.
+	(s390x_emit_log_not): New function.
+	(s390x_emit_bit_and): New function.
+	(s390x_emit_bit_or): New function.
+	(s390x_emit_bit_xor): New function.
+	(s390x_emit_bit_not): New function.
+	(s390x_emit_equal): New function.
+	(s390x_emit_less_signed): New function.
+	(s390x_emit_less_unsigned): New function.
+	(s390x_emit_ref): New function.
+	(s390x_emit_if_goto): New function.
+	(s390x_emit_goto): New function.
+	(s390x_emit_const): New function.
+	(s390x_emit_call): New function.
+	(s390x_emit_reg): New function.
+	(s390x_emit_pop): New function.
+	(s390x_emit_stack_flush): New function.
+	(s390x_emit_zero_ext): New function.
+	(s390x_emit_swap): New function.
+	(s390x_emit_stack_adjust): New function.
+	(s390x_emit_int_call_1): New function.
+	(s390x_emit_void_call_2): New function.
+	(s390x_emit_eq_goto): New function.
+	(s390x_emit_ne_goto): New function.
+	(s390x_emit_lt_goto): New function.
+	(s390x_emit_le_goto): New function.
+	(s390x_emit_gt_goto): New function.
+	(s390x_emit_ge_goto): New function.
+	(s390_emit_ops): New function.
+	(struct linux_target_ops): Fill in emit_ops hook.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* Makefile.in: Add s390 IPA files.
 	* configure.srv: Build IPA for s390.
 	* linux-s390-ipa.c: New file.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index bc8c484..ac56a82 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -22,6 +22,8 @@
 #include "server.h"
 #include "linux-low.h"
 #include "elf/common.h"
+#include "ax.h"
+#include "tracepoint.h"
 
 #include <asm/ptrace.h>
 #include "nat/gdb_ptrace.h"
@@ -1346,6 +1348,1208 @@ s390_get_min_fast_tracepoint_insn_len (void)
      seem to be worth the effort.  */
   return 6;
 }
+
+static void
+add_insns (const unsigned char *start, int len)
+{
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  if (debug_threads)
+    debug_printf ("Adding %d bytes of insn at %s\n",
+		  len, paddress (buildaddr));
+
+  append_insns (&buildaddr, len, start);
+  current_insn_ptr = buildaddr;
+}
+
+/* Register usage in emit:
+
+   - %r0, %r1: temp
+   - %r2: top of stack (high word for 31-bit)
+   - %r3: low word of top of stack (for 31-bit)
+   - %r4, %r5: temp
+   - %r6, %r7, %r8: don't use
+   - %r9: saved arg1
+   - %r10: saved arg2
+   - %r11: frame pointer
+   - %r12: saved top of stack for void_call_2 (high word for 31-bit)
+   - %r13: low word of saved top of stack (for 31-bit)
+   - %r14: return address for calls
+   - %r15: stack pointer
+
+  */
+
+static void
+s390_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x9f, 0xf0, 0x24,		/* stm %r9, %r15, 0x24(%r15) */
+    0x18, 0x92,				/* lr %r9, %r2 */
+    0x18, 0xa3,				/* lr %r10, %r3 */
+    0x18, 0xbf,				/* lr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x23, 0xa0, 0x00,		/* stm %r2, %r3, 0(%r10) */
+    0xa7, 0x28, 0x00, 0x00,		/* lhi %r2, 0 */
+    0x98, 0x9f, 0xb0, 0x24,		/* lm %r9, %r15, 0x24(%r11) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0x5e, 0x30, 0xf0, 0x04,		/* al %r3, 4(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98,	/* al %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x1f, 0x53,			/* slr %r5, %r3 */
+    0xb9, 0x99, 0x00, 0x42,	/* slbr %r4, %r2 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+    0x18, 0x35,			/* lr %r3, %r5 */
+    0x18, 0x24,			/* lr %r2, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+static void
+s390_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8d, 0x20, 0x40, 0x00,	/* sldl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8e, 0x20, 0x40, 0x00,	/* srda %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8c, 0x20, 0x40, 0x00,	/* srdl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8e, 0x20, 0x00, 64-arg,	/* srda %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,			/* or %r2, %r3 */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0x74, 0x00, 0x04,	/* jne .Lskip */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lskip: */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0x54, 0x20, 0xf0, 0x00,	/* n %r2, 0(%r15) */
+    0x54, 0x30, 0xf0, 0x04,	/* n %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0x56, 0x20, 0xf0, 0x00,	/* o %r2, 0(%r15) */
+    0x56, 0x30, 0xf0, 0x04,	/* o %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,	/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,	/* x %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x48, 0xff, 0xff,	/* lhi %r4, -1 */
+    0x17, 0x24,			/* xr %r2, %r4 */
+    0x17, 0x34,			/* xr %r3, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_equal (void)
+{
+  s390_emit_bit_xor ();
+  s390_emit_log_not ();
+}
+
+static void
+s390_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,	/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x55, 0x20, 0xf0, 0x00,	/* cl %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x43, 0x30, 0x30, 0x00,	/* ic %r3, 0(%r3) */
+  };
+  static const unsigned char buf2[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x48, 0x30, 0x30, 0x00,	/* lh %r3, 0(%r3) */
+  };
+  static const unsigned char buf4[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x58, 0x30, 0x30, 0x00,	/* l %r3, 0(%r3) */
+  };
+  static const unsigned char buf8[] = {
+    0x98, 0x23, 0x30, 0x00,	/* lm %r2, %r3, 0(%r3) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+s390_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x00,		/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+s390_emit_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 2;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  long diff = ((long) (to - (from - 2))) / 2;
+  int sdiff = diff;
+  unsigned char buf[sizeof sdiff];
+
+  /* We're only doing 4-byte sizes at the moment.  */
+  if (size != sizeof sdiff || sdiff != diff)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  memcpy (buf, &sdiff, sizeof sdiff);
+  write_inferior_memory (from, buf, sizeof sdiff);
+}
+
+static void
+s390_emit_litpool (int size)
+{
+  static const unsigned char nop[] = {
+    0x07, 0x07,
+  };
+  unsigned char buf[] = {
+    0xa7, 0x15, 0x00, (size + 4) / 2,	/* bras %r1, .Lend+size */
+    /* .Lend: */
+  };
+  if (size == 4)
+    {
+      /* buf needs to start at even halfword for litpool to be aligned */
+      if (current_insn_ptr & 2)
+        add_insns (nop, sizeof nop);
+    }
+  else
+    {
+      while ((current_insn_ptr & 6) != 4)
+        add_insns (nop, sizeof nop);
+    }
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x38, num >> 8, num,	/* lhi %r3, <num> */
+    0x17, 0x22,			/* xr %r2, %r2 */
+  };
+  static const unsigned char buf_l[] = {
+    0x98, 0x23, 0x10, 0x00,	/* lm %r2, %r3, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= 0)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+static void
+s390_emit_call (CORE_ADDR fn)
+{
+  unsigned int n = fn;
+  static const unsigned char buf[] = {
+    0x58, 0x10, 0x10, 0x00,	/* l %r1, 0(%r1) */
+    0xa7, 0xfa, 0xff, 0xa0,	/* ahi %r15, -0x60 */
+    0x0d, 0xe1,			/* basr %r14, %r1 */
+    0xa7, 0xfa, 0x00, 0x60,	/* ahi %r15, 0x60 */
+  };
+  s390_emit_litpool (4);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_reg (int reg)
+{
+  unsigned char bufpre[] = {
+    0x18, 0x29,			/* lr %r2, %r9 */
+    0xa7, 0x38, reg >> 8, reg,	/* lhi %r3, <reg> */
+  };
+  add_insns (bufpre, sizeof bufpre);
+  s390_emit_call (get_raw_reg_func_addr ());
+}
+
+static void
+s390_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfa, 0xff, 0xf8,	/* ahi %r15, -8 */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8c, 0x20, 0x00, 64-arg,	/* srdl %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+    0x18, 0x24,			/* lr %r2, %r4 */
+    0x18, 0x35,			/* lr %r3, %r5 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfa, n * 8 >> 8, n * 8,	/* ahi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390_emit_set_r2 (int arg1)
+{
+  unsigned char buf_s[] = {
+    0xa7, 0x28, arg1 >> 8, arg1,	/* lhi %r2, <arg1> */
+  };
+  static const unsigned char buf_l[] = {
+    0x58, 0x20, 0x10, 0x00,	/* l %r2, 0(%r1) */
+  };
+  if (arg1 < 0x8000 && arg1 >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (4);
+    add_insns ((unsigned char *) &arg1, sizeof arg1);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.  */
+
+static void
+s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+}
+
+/* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+
+static void
+s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  static const unsigned char buf[] = {
+    0x18, 0xc2,			/* lr %r12, %r2 */
+    0x18, 0xd3,			/* lr %r13, %r3 */
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x18, 0x32,			/* lr %r3, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0x18, 0x2c,			/* lr %r2, %r12 */
+    0x18, 0x3d,			/* lr %r3, %r13 */
+  };
+  add_insns (buf, sizeof buf);
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+void
+s390_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x08,		/* jh .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xa4, 0x00, 0x08,		/* jhe .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x44, 0x00, 0x08,		/* jl .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xc4, 0x00, 0x08,		/* jle .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+struct emit_ops s390_emit_ops_impl =
+  {
+    s390_emit_prologue,
+    s390_emit_epilogue,
+    s390_emit_add,
+    s390_emit_sub,
+    s390_emit_mul,
+    s390_emit_lsh,
+    s390_emit_rsh_signed,
+    s390_emit_rsh_unsigned,
+    s390_emit_ext,
+    s390_emit_log_not,
+    s390_emit_bit_and,
+    s390_emit_bit_or,
+    s390_emit_bit_xor,
+    s390_emit_bit_not,
+    s390_emit_equal,
+    s390_emit_less_signed,
+    s390_emit_less_unsigned,
+    s390_emit_ref,
+    s390_emit_if_goto,
+    s390_emit_goto,
+    s390_write_goto_address,
+    s390_emit_const,
+    s390_emit_call,
+    s390_emit_reg,
+    s390_emit_pop,
+    s390_emit_stack_flush,
+    s390_emit_zero_ext,
+    s390_emit_swap,
+    s390_emit_stack_adjust,
+    s390_emit_int_call_1,
+    s390_emit_void_call_2,
+    s390_emit_eq_goto,
+    s390_emit_ne_goto,
+    s390_emit_lt_goto,
+    s390_emit_le_goto,
+    s390_emit_gt_goto,
+    s390_emit_ge_goto
+  };
+
+#ifdef __s390x__
+
+static void
+s390x_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24,	/* stmg %r9, %r15, 0x48(%r15) */
+    0xb9, 0x04, 0x00, 0x92,		/* lgr %r9, %r2 */
+    0xb9, 0x04, 0x00, 0xa3,		/* lgr %r10, %r3 */
+    0xb9, 0x04, 0x00, 0xbf,		/* lgr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r10) */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04,	/* lmg %r9, %r15, 0x48(%r15) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a,	/* alg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xb9, 0x0b, 0x00, 0x32,		/* slgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+static void
+s390x_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d,	/* sllg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a,	/* srag %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c,	/* srlg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0a,	/* srag %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x00, 0x00, 0x22,		/* lpgr %r2, %r2 */
+    0xa7, 0x2b, 0xff, 0xff,		/* aghi %r2, -1 */
+    0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c,	/* srlg %r2, %r2, 63 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80,	/* ng %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81,	/* og %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82,	/* xg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x39, 0xff, 0xff,	/* lghi %r3, -1 */
+    0xb9, 0x82, 0x00, 0x23,	/* xgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_equal (void)
+{
+  s390x_emit_bit_xor ();
+  s390x_emit_log_not ();
+}
+
+static void
+s390x_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21,	/* clg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x90,	/* llgc %r2, 0(%r2) */
+  };
+  static const unsigned char buf2[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x91	/* llgh %r2, 0(%r2) */
+  };
+  static const unsigned char buf4[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x16,	/* llgf %r2, 0(%r2) */
+  };
+  static const unsigned char buf8[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r2) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+s390x_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x02, 0x00, 0x22,		/* ltgr %r2, %r2 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 16;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+s390x_emit_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 2;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+s390x_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x29, num >> 8, num,		/* lghi %r2, <num> */
+  };
+  static const unsigned char buf_l[] = {
+    0xe3, 0x20, 0x10, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+static void
+s390x_emit_call (CORE_ADDR fn)
+{
+  unsigned long n = fn;
+  static const unsigned char buf[] = {
+    0xe3, 0x10, 0x10, 0x00, 0x00, 0x04,	/* lg %r1, 0(%r1) */
+    0xa7, 0xfb, 0xff, 0x60,		/* aghi %r15, -0xa0 */
+    0x0d, 0xe1,				/* basr %r14, %r1 */
+    0xa7, 0xfb, 0x00, 0xa0,		/* aghi %r15, 0xa0 */
+  };
+  s390_emit_litpool (8);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_reg (int reg)
+{
+  unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x29,		/* lgr %r2, %r9 */
+    0xa7, 0x39, reg >> 8, reg,		/* lghi %r3, <reg> */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_call (get_raw_reg_func_addr ());
+}
+
+static void
+s390x_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfb, 0xff, 0xf8,		/* aghi %r15, -8 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0c,	/* srlg %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+static void
+s390x_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfb, n * 8 >> 8, n * 8,	/* aghi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.  */
+
+static void
+s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+}
+
+/* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+
+static void
+s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x32,		/* lgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0xc2,		/* lgr %r12, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0xb9, 0x04, 0x00, 0x2c,		/* lgr %r2, %r12 */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+void
+s390x_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390x_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390x_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x24, 0x00, 0x00, 0x00, 0x00,	/* jgh <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390x_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00,	/* jghe <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390x_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x44, 0x00, 0x00, 0x00, 0x00,	/* jgl <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+void
+s390x_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00,	/* jgle <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+struct emit_ops s390x_emit_ops =
+  {
+    s390x_emit_prologue,
+    s390x_emit_epilogue,
+    s390x_emit_add,
+    s390x_emit_sub,
+    s390x_emit_mul,
+    s390x_emit_lsh,
+    s390x_emit_rsh_signed,
+    s390x_emit_rsh_unsigned,
+    s390x_emit_ext,
+    s390x_emit_log_not,
+    s390x_emit_bit_and,
+    s390x_emit_bit_or,
+    s390x_emit_bit_xor,
+    s390x_emit_bit_not,
+    s390x_emit_equal,
+    s390x_emit_less_signed,
+    s390x_emit_less_unsigned,
+    s390x_emit_ref,
+    s390x_emit_if_goto,
+    s390x_emit_goto,
+    s390_write_goto_address,
+    s390x_emit_const,
+    s390x_emit_call,
+    s390x_emit_reg,
+    s390x_emit_pop,
+    s390x_emit_stack_flush,
+    s390x_emit_zero_ext,
+    s390x_emit_swap,
+    s390x_emit_stack_adjust,
+    s390x_emit_int_call_1,
+    s390x_emit_void_call_2,
+    s390x_emit_eq_goto,
+    s390x_emit_ne_goto,
+    s390x_emit_lt_goto,
+    s390x_emit_le_goto,
+    s390x_emit_gt_goto,
+    s390x_emit_ge_goto
+  };
+
+#endif
+
+static struct emit_ops *
+s390_emit_ops (void)
+{
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  if (register_size (regcache->tdesc, 0) == 8)
+    return &s390x_emit_ops;
+  else
+#endif
+    return &s390_emit_ops_impl;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -1375,7 +2579,7 @@ struct linux_target_ops the_low_target = {
   s390_supports_tracepoints,
   s390_get_thread_area,
   s390_install_fast_tracepoint_jump_pad,
-  NULL, /* emit_ops */
+  s390_emit_ops,
   s390_get_min_fast_tracepoint_insn_len,
   NULL, /* supports_range_stepping */
   NULL, /* breakpoint_kind_from_current_state */
-- 
2.7.0

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

* [PATCH 6/8] gdbserver/s390: Add fast tracepoint support.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (6 preceding siblings ...)
  2016-01-24 12:12 ` [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks Marcin Kościelnicki
@ 2016-01-24 12:13 ` Marcin Kościelnicki
  2016-01-25 14:34   ` Antoine Tremblay
  2016-01-25 13:27 ` [PATCH 0/8] gdb/s390: Add regular and " Antoine Tremblay
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-24 12:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Fast tracepoints will only work on 6-byte intructions, and assume at least
a z900 CPU.  s390 also has 4-byte jump instructions, which also work on
pre-z900, but their range is limitted to +-64kiB, which is not very useful
(and wouldn't work at all with current jump pad allocation).

Due to lack of support for using 31-bit agent with 64-bit gdbserver, and
lack of support for high GPRs when 31-bit gdbserver is in use, there's
no way to collect the high GPR halves on 31-bit targets (even though
the support is there in IPA).  Fixing that would require teaching 31-bit
gdbserver about high GPRs, or fixing IPA for multilib.

There's a little problem with s390_relocate_instruction function: it
converts BRAS/BRASL instructions to LARL of the return address + JG
to the target address.  On 31-bit, this sets the high bit of the target
register to 0, while BRAS/BRASL would set it to 1.  While this is not
a problem when the result is only used to address memory, it could
possibly break something that expects to compare such addresses for
equality without first masking the bit off.  In particular, I'm not sure
whether leaving the return address high bit unset is ABI-compliant
(could confuse some unwinder?).  If that's a problem, it could be fixed
by handling it in the jump pad (since at that point we can just modify
the GPRs in the save area without having to worry about preserving
CCs and only having that one GPR to work with - I'm not sure if it's
even possible to set the high bit with such constraints).

gdb/gdbserver/ChangeLog:

	* Makefile.in: Add s390 IPA files.
	* configure.srv: Build IPA for s390.
	* linux-s390-ipa.c: New file.
	* linux-s390-low.c: New include - inttypes.h.
	(have_hwcap_s390_vx): New static variable.
	(s390_arch_setup): Fill have_hwcap_s390_vx.
	(s390_get_thread_area): New function.
	(s390_ft_entry_gpr_esa): New const.
	(s390_ft_entry_gpr_zarch): New const.
	(s390_ft_entry_misc): New const.
	(s390_ft_entry_fr): New const.
	(s390_ft_entry_vr): New const.
	(s390_ft_main_31): New const.
	(s390_ft_main_64): New const.
	(s390_ft_exit_fr): New const.
	(s390_ft_exit_vr): New const.
	(s390_ft_exit_misc): New const.
	(s390_ft_exit_gpr_esa): New const.
	(s390_ft_exit_gpr_zarch): New const.
	(append_insns): New function.
	(s390_relocate_instruction): New function.
	(s390_install_fast_tracepoint_jump_pad): New function.
	(s390_get_min_fast_tracepoint_insn_len): New function.
	(struct linux_target_ops): Wire in the above functions.
---
 gdb/gdbserver/ChangeLog        |  27 ++
 gdb/gdbserver/Makefile.in      |  24 ++
 gdb/gdbserver/configure.srv    |   7 +
 gdb/gdbserver/linux-s390-ipa.c | 445 ++++++++++++++++++++++++++++
 gdb/gdbserver/linux-s390-low.c | 658 ++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 1158 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdbserver/linux-s390-ipa.c

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index e0d8c67..1cd1a7e 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,32 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* Makefile.in: Add s390 IPA files.
+	* configure.srv: Build IPA for s390.
+	* linux-s390-ipa.c: New file.
+	* linux-s390-low.c: New include - inttypes.h.
+	(have_hwcap_s390_vx): New static variable.
+	(s390_arch_setup): Fill have_hwcap_s390_vx.
+	(s390_get_thread_area): New function.
+	(s390_ft_entry_gpr_esa): New const.
+	(s390_ft_entry_gpr_zarch): New const.
+	(s390_ft_entry_misc): New const.
+	(s390_ft_entry_fr): New const.
+	(s390_ft_entry_vr): New const.
+	(s390_ft_main_31): New const.
+	(s390_ft_main_64): New const.
+	(s390_ft_exit_fr): New const.
+	(s390_ft_exit_vr): New const.
+	(s390_ft_exit_misc): New const.
+	(s390_ft_exit_gpr_esa): New const.
+	(s390_ft_exit_gpr_zarch): New const.
+	(append_insns): New function.
+	(s390_relocate_instruction): New function.
+	(s390_install_fast_tracepoint_jump_pad): New function.
+	(s390_get_min_fast_tracepoint_insn_len): New function.
+	(struct linux_target_ops): Wire in the above functions.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* linux-s390-low.c (s390_supports_tracepoints): New function.
 	(struct linux_target_ops): Fill supports_tracepoints hook.
 
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index f9b9dbe..38218d2 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -510,6 +510,30 @@ linux-aarch64-ipa.o: linux-aarch64-ipa.c
 aarch64-ipa.o: aarch64.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
+linux-s390-ipa.o: linux-s390-ipa.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux32-ipa.o: s390-linux32.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux64-ipa.o: s390-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-vx-linux64-ipa.o: s390-vx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-tevx-linux64-ipa.o: s390-tevx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-linux64-ipa.o: s390x-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-vx-linux64-ipa.o: s390x-vx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-tevx-linux64-ipa.o: s390x-tevx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
 tdesc-ipa.o: tdesc.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 5f5112e..873830a 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -306,6 +306,13 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
+			ipa_obj="linux-s390-ipa.o s390-linux32-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390-vx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390-tevx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-vx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-tevx-linux64-ipa.o"
 			;;
   sh*-*-linux*)		srv_regobj=reg-sh.o
 			srv_tgtobj="$srv_linux_obj linux-sh-low.o"
diff --git a/gdb/gdbserver/linux-s390-ipa.c b/gdb/gdbserver/linux-s390-ipa.c
new file mode 100644
index 0000000..e2a95f9
--- /dev/null
+++ b/gdb/gdbserver/linux-s390-ipa.c
@@ -0,0 +1,445 @@
+/* GNU/Linux S/390 specific low level interface, for the in-process
+   agent library for GDB.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "server.h"
+#include "tracepoint.h"
+#include <sys/auxv.h>
+
+#ifndef HWCAP_S390_HIGH_GPRS
+#define HWCAP_S390_HIGH_GPRS 512
+#endif
+
+#ifndef HWCAP_S390_TE
+#define HWCAP_S390_TE 1024
+#endif
+
+#ifndef HWCAP_S390_VX
+#define HWCAP_S390_VX 2048
+#endif
+
+/* Only some of the tdescs are used in ipa.  We don't care about last_break,
+   syscall number, orig r2, or TDB (fast tracepoint has no way of saving
+   those), so we ignore linux*v[12] and te_linux64.  Unfortunately, we have
+   to handle both vx_linux* and tevx_linux*, since they have different
+   numbers for VX registers.  */
+
+#ifndef __s390x__
+
+/* Defined in auto-generated file s390-linux32.c.  */
+void init_registers_s390_linux32 (void);
+extern const struct target_desc *tdesc_s390_linux32;
+
+/* Defined in auto-generated file s390-linux64.c.  */
+void init_registers_s390_linux64 (void);
+extern const struct target_desc *tdesc_s390_linux64;
+
+/* Defined in auto-generated file s390-vx-linux64.c.  */
+void init_registers_s390_vx_linux64 (void);
+extern const struct target_desc *tdesc_s390_vx_linux64;
+
+/* Defined in auto-generated file s390-tevx-linux64.c.  */
+void init_registers_s390_tevx_linux64 (void);
+extern const struct target_desc *tdesc_s390_tevx_linux64;
+
+#else
+
+/* Defined in auto-generated file s390x-linux64.c.  */
+void init_registers_s390x_linux64 (void);
+extern const struct target_desc *tdesc_s390x_linux64;
+
+/* Defined in auto-generated file s390x-vx-linux64.c.  */
+void init_registers_s390x_vx_linux64 (void);
+extern const struct target_desc *tdesc_s390x_vx_linux64;
+
+/* Defined in auto-generated file s390x-tevx-linux64.c.  */
+void init_registers_s390x_tevx_linux64 (void);
+extern const struct target_desc *tdesc_s390x_tevx_linux64;
+
+#endif
+
+#define FT_FPR(x) (0x000 + (x) * 0x10)
+#define FT_VR(x) (0x000 + (x) * 0x10)
+#define FT_VR_L(x) (0x008 + (x) * 0x10)
+#define FT_GPR(x) (0x200 + (x) * 8)
+#define FT_GPR_U(x) (0x200 + (x) * 8)
+#define FT_GPR_L(x) (0x204 + (x) * 8)
+#define FT_GPR(x) (0x200 + (x) * 8)
+#define FT_ACR(x) (0x280 + (x) * 4)
+#define FT_PSWM 0x2c0
+#define FT_PSWM_U 0x2c0
+#define FT_PSWA 0x2c8
+#define FT_PSWA_L 0x2cc
+#define FT_FPC 0x2d0
+
+/* Mappings between registers collected by the jump pad and GDB's register
+   array layout used by regcache.
+
+   See linux-s390-low.c (s390_install_fast_tracepoint_jump_pad) for more
+   details.  */
+
+#ifndef __s390x__
+
+/* Used for s390-linux32, s390-linux32v1, s390-linux32v2.  */
+
+static const int s390_linux32_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit GPRs (mapped to lower halves of 64-bit slots).  */
+  FT_GPR_L (0), FT_GPR_L (1), FT_GPR_L (2), FT_GPR_L (3),
+  FT_GPR_L (4), FT_GPR_L (5), FT_GPR_L (6), FT_GPR_L (7),
+  FT_GPR_L (8), FT_GPR_L (9), FT_GPR_L (10), FT_GPR_L (11),
+  FT_GPR_L (12), FT_GPR_L (13), FT_GPR_L (14), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+};
+
+/* Used for s390-linux64, s390-linux64v1, s390-linux64v2, s390-vx-linux64.  */
+
+static const int s390_linux64_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit halves of 64-bit GPRs.  */
+  FT_GPR_U (0), FT_GPR_L (0),
+  FT_GPR_U (1), FT_GPR_L (1),
+  FT_GPR_U (2), FT_GPR_L (2),
+  FT_GPR_U (3), FT_GPR_L (3),
+  FT_GPR_U (4), FT_GPR_L (4),
+  FT_GPR_U (5), FT_GPR_L (5),
+  FT_GPR_U (6), FT_GPR_L (6),
+  FT_GPR_U (7), FT_GPR_L (7),
+  FT_GPR_U (8), FT_GPR_L (8),
+  FT_GPR_U (9), FT_GPR_L (9),
+  FT_GPR_U (10), FT_GPR_L (10),
+  FT_GPR_U (11), FT_GPR_L (11),
+  FT_GPR_U (12), FT_GPR_L (12),
+  FT_GPR_U (13), FT_GPR_L (13),
+  FT_GPR_U (14), FT_GPR_L (14),
+  FT_GPR_U (15), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+/* Used for s390-te-linux64, s390-tevx-linux64.  */
+
+static const int s390_te_linux64_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit halves of 64-bit GPRs.  */
+  FT_GPR_U (0), FT_GPR_L (0),
+  FT_GPR_U (1), FT_GPR_L (1),
+  FT_GPR_U (2), FT_GPR_L (2),
+  FT_GPR_U (3), FT_GPR_L (3),
+  FT_GPR_U (4), FT_GPR_L (4),
+  FT_GPR_U (5), FT_GPR_L (5),
+  FT_GPR_U (6), FT_GPR_L (6),
+  FT_GPR_U (7), FT_GPR_L (7),
+  FT_GPR_U (8), FT_GPR_L (8),
+  FT_GPR_U (9), FT_GPR_L (9),
+  FT_GPR_U (10), FT_GPR_L (10),
+  FT_GPR_U (11), FT_GPR_L (11),
+  FT_GPR_U (12), FT_GPR_L (12),
+  FT_GPR_U (13), FT_GPR_L (13),
+  FT_GPR_U (14), FT_GPR_L (14),
+  FT_GPR_U (15), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* TDB */
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+#else /* __s390x__ */
+
+/* Used for s390x-linux64, s390x-linux64v1, s390x-linux64v2, s390x-vx-linux64.  */
+
+static const int s390x_ft_collect_regmap[] = {
+  /* 64-bit PSWA and PSWM.  */
+  FT_PSWM, FT_PSWA,
+  /* 64-bit GPRs.  */
+  FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
+  FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
+  FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
+  FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+/* Used for s390x-te-linux64, s390x-tevx-linux64.  */
+
+static const int s390x_te_ft_collect_regmap[] = {
+  /* 64-bit PSWA and PSWM.  */
+  FT_PSWM, FT_PSWA,
+  /* 64-bit GPRs.  */
+  FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
+  FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
+  FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
+  FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* TDB */
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+#endif
+
+enum {
+#ifndef __s390x__
+  S390_LINUX32,
+#endif
+  S390_LINUX64,
+  S390_VX_LINUX64,
+  S390_TEVX_LINUX64,
+};
+
+
+static const struct {
+  const struct target_desc **tdesc;
+  void (*init) (void);
+  const int *regmap;
+  int regnum;
+} s390_targets[] = {
+#ifndef __s390x__
+  {
+    &tdesc_s390_linux32,
+    init_registers_s390_linux32,
+    s390_linux32_ft_collect_regmap,
+    (sizeof s390_linux32_ft_collect_regmap
+     / sizeof s390_linux32_ft_collect_regmap[0]),
+  },
+  {
+    &tdesc_s390_linux64,
+    init_registers_s390_linux64,
+    s390_linux64_ft_collect_regmap,
+    /* Subtract number of VX regs.  */
+    (sizeof s390_linux64_ft_collect_regmap
+     / sizeof s390_linux64_ft_collect_regmap[0]) - 32,
+  },
+  {
+    &tdesc_s390_vx_linux64,
+    init_registers_s390_vx_linux64,
+    s390_linux64_ft_collect_regmap,
+    (sizeof s390_linux64_ft_collect_regmap
+     / sizeof s390_linux64_ft_collect_regmap[0]),
+  },
+  {
+    &tdesc_s390_tevx_linux64,
+    init_registers_s390_tevx_linux64,
+    s390_te_linux64_ft_collect_regmap,
+    (sizeof s390_te_linux64_ft_collect_regmap
+     / sizeof s390_te_linux64_ft_collect_regmap[0]),
+  },
+#else
+  {
+    &tdesc_s390x_linux64,
+    init_registers_s390x_linux64,
+    s390x_ft_collect_regmap,
+    /* Subtract number of VX regs.  */
+    (sizeof s390x_ft_collect_regmap
+     / sizeof s390x_ft_collect_regmap[0]) - 32,
+  },
+  {
+    &tdesc_s390x_vx_linux64,
+    init_registers_s390x_vx_linux64,
+    s390x_ft_collect_regmap,
+    (sizeof s390x_ft_collect_regmap
+     / sizeof s390x_ft_collect_regmap[0]),
+  },
+  {
+    &tdesc_s390x_tevx_linux64,
+    init_registers_s390x_tevx_linux64,
+    s390x_te_ft_collect_regmap,
+    (sizeof s390x_te_ft_collect_regmap
+     / sizeof s390x_te_ft_collect_regmap[0]),
+  },
+#endif
+};
+
+
+static int s390_target;
+
+
+/* Fill in REGCACHE with registers saved by the jump pad in BUF.  */
+
+void
+supply_fast_tracepoint_registers (struct regcache *regcache,
+				  const unsigned char *buf)
+{
+  int i;
+  int regnum = s390_targets[s390_target].regnum;
+  const int *regmap =  s390_targets[s390_target].regmap;
+
+  for (i = 0; i < regnum; i++)
+    if (regmap[i] != -1)
+      supply_register (regcache, i, ((char *) buf) + regmap[i]);
+}
+
+IP_AGENT_EXPORT_FUNC ULONGEST
+gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
+{
+  const int *regmap =  s390_targets[s390_target].regmap;
+  int offset;
+  if (regnum >= s390_targets[s390_target].regnum)
+    return 0;
+  offset = regmap[regnum];
+  if (offset == -1)
+    return 0;
+
+  /* The regnums are variable, better to figure out size by FT offset.  */
+
+  /* 64-bit ones.  */
+  if (offset < FT_VR(16)
+#ifdef __s390x__
+      || (offset >= FT_GPR(0) && offset < FT_ACR(0))
+      || offset == FT_PSWM
+      || offset == FT_PSWA
+#endif
+     )
+    return *(uint64_t *) (raw_regs + offset);
+
+  if (offset >= FT_ACR(0 && offset < FT_PSWM)
+      || offset == FT_FPC
+#ifndef __s390x__
+      || (offset >= FT_GPR(0) && offset < FT_ACR(0))
+      || offset == FT_PSWM_U
+      || offset == FT_PSWA_L
+#endif
+     )
+    return *(uint32_t *) (raw_regs + offset);
+
+  /* This leaves 128-bit VX.  No way to return them.  */
+  return 0;
+}
+
+void
+initialize_low_tracepoint (void)
+{
+  unsigned long hwcap = getauxval (AT_HWCAP);
+#ifndef __s390x__
+  /* XXX Other targets temporarily disabled due to lack of support in
+     gdbserver.  */
+  s390_target = S390_LINUX32;
+#else
+  if (!(hwcap & HWCAP_S390_VX))
+    s390_target = S390_LINUX64;
+  else if (!(hwcap & HWCAP_S390_TE))
+    s390_target = S390_VX_LINUX64;
+  else
+    s390_target = S390_TEVX_LINUX64;
+#endif
+  s390_targets[s390_target].init ();
+  ipa_tdesc = *s390_targets[s390_target].tdesc;
+}
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index ab3e62b..bc8c484 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -27,6 +27,7 @@
 #include "nat/gdb_ptrace.h"
 #include <sys/uio.h>
 #include <elf.h>
+#include <inttypes.h>
 
 #ifndef HWCAP_S390_HIGH_GPRS
 #define HWCAP_S390_HIGH_GPRS 512
@@ -489,6 +490,7 @@ s390_check_regset (int pid, int regset, int regsize)
 /* For a 31-bit inferior, whether the kernel supports using the full
    64-bit GPRs.  */
 static int have_hwcap_s390_high_gprs = 0;
+static int have_hwcap_s390_vx = 0;
 #endif
 
 static void
@@ -570,6 +572,8 @@ s390_arch_setup (void)
 	else
 	  tdesc = tdesc_s390_linux64;
       }
+
+    have_hwcap_s390_vx = have_regset_vxrs;
   }
 #endif
 
@@ -694,6 +698,654 @@ s390_supports_tracepoints (void)
   return 1;
 }
 
+/* Implementation of linux_target_ops method "get_thread_area".  */
+
+static int
+s390_get_thread_area (int lwpid, CORE_ADDR *addrp)
+{
+  CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, (long) 0);
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  if (register_size (regcache->tdesc, 0) == 4)
+    res &= 0xffffffff;
+#endif
+  *addrp = res;
+  return 0;
+}
+
+
+/* Fast tracepoint support.
+
+   The register save area on stack is identical for all targets:
+
+   0x000+i*0x10: VR0-VR31
+   0x200+i*8: GR0-GR15
+   0x280+i*4: AR0-AR15
+   0x2c0: PSWM [64-bit]
+   0x2c8: PSWA [64-bit]
+   0x2d0: FPC
+
+   If we're on 31-bit linux, we just don't store the high parts of the GPRs.
+   Likewise, if there's no VX support, we just store the FRs into the slots
+   of low VR halves.  The agent code is responsible for rearranging that
+   into regcache.  */
+
+/* Code sequence saving GPRs for 31-bit target with no high GPRs.  There's
+   one trick used at the very beginning: since there's no way to allocate
+   stack space without destroying CC (lay instruction can do it, but it's
+   only supported on later CPUs), we take 4 different execution paths for
+   every possible value of CC, allocate stack space, save %r0, stuff the
+   CC value in %r0 (shifted to match its position in PSWM high word),
+   then branch to common path.  */
+
+static const unsigned char s390_ft_entry_gpr_esa[] = {
+  0xa7, 0x14, 0x00, 0x1e,		/* jo .Lcc3 */
+  0xa7, 0x24, 0x00, 0x14,		/* jh .Lcc2 */
+  0xa7, 0x44, 0x00, 0x0a,		/* jl .Lcc1 */
+  /* CC = 0 */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x00, 0x00,		/* lhi %r0, 0 */
+  0xa7, 0xf4, 0x00, 0x18,		/* j .Lccdone */
+  /* .Lcc1: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x10, 0x00,		/* lhi %r0, 0x1000 */
+  0xa7, 0xf4, 0x00, 0x10,		/* j .Lccdone */
+  /* .Lcc2: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x20, 0x00,		/* lhi %r0, 0x2000 */
+  0xa7, 0xf4, 0x00, 0x08,		/* j .Lccdone */
+  /* .Lcc3: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x30, 0x00,		/* lhi %r0, 0x3000 */
+  /* .Lccdone: */
+  0x50, 0x10, 0xf2, 0x0c,		/* st %r1, 0x20c(%r15) */
+  0x50, 0x20, 0xf2, 0x14,		/* st %r2, 0x214(%r15) */
+  0x50, 0x30, 0xf2, 0x1c,		/* st %r3, 0x21c(%r15) */
+  0x50, 0x40, 0xf2, 0x24,		/* st %r4, 0x224(%r15) */
+  0x50, 0x50, 0xf2, 0x2c,		/* st %r5, 0x22c(%r15) */
+  0x50, 0x60, 0xf2, 0x34,		/* st %r6, 0x234(%r15) */
+  0x50, 0x70, 0xf2, 0x3c,		/* st %r7, 0x23c(%r15) */
+  0x50, 0x80, 0xf2, 0x44,		/* st %r8, 0x244(%r15) */
+  0x50, 0x90, 0xf2, 0x4c,		/* st %r9, 0x24c(%r15) */
+  0x50, 0xa0, 0xf2, 0x54,		/* st %r10, 0x254(%r15) */
+  0x50, 0xb0, 0xf2, 0x5c,		/* st %r11, 0x25c(%r15) */
+  0x50, 0xc0, 0xf2, 0x64,		/* st %r12, 0x264(%r15) */
+  0x50, 0xd0, 0xf2, 0x6c,		/* st %r13, 0x26c(%r15) */
+  0x50, 0xe0, 0xf2, 0x74,		/* st %r14, 0x274(%r15) */
+  /* Compute original value of %r15 and store it.  We use ahi instead
+     of la to preserve the whole value, and not just the low 31 bits.
+     This is not particularly important here, but essential in the
+     zarch case where someone might be using the high word of %r15
+     as an extra register.  */
+  0x18, 0x1f,				/* lr %r1, %r15 */
+  0xa7, 0x1a, 0x03, 0x00,		/* ahi %r1, 0x300 */
+  0x50, 0x10, 0xf2, 0x7c,		/* st %r1, 0x27c(%r15) */
+};
+
+/* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
+   target.  Same as above, except this time we can use load/store multiple,
+   since the 64-bit regs are tightly packed.  */
+
+static const unsigned char s390_ft_entry_gpr_zarch[] = {
+  0xa7, 0x14, 0x00, 0x21,		/* jo .Lcc3 */
+  0xa7, 0x24, 0x00, 0x16,		/* jh .Lcc2 */
+  0xa7, 0x44, 0x00, 0x0b,		/* jl .Lcc1 */
+  /* CC = 0 */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x00, 0x00,		/* lhi %r0, 0 */
+  0xa7, 0xf4, 0x00, 0x1b,		/* j .Lccdone */
+  /* .Lcc1: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x10, 0x00,		/* lhi %r0, 0x1000 */
+  0xa7, 0xf4, 0x00, 0x12,		/* j .Lccdone */
+  /* .Lcc2: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x20, 0x00,		/* lhi %r0, 0x2000 */
+  0xa7, 0xf4, 0x00, 0x09,		/* j .Lccdone */
+  /* .Lcc3: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x30, 0x00,		/* lhi %r0, 0x3000 */
+  /* .Lccdone: */
+  0xb9, 0x04, 0x00, 0x1f,		/* lgr %r1, %r15 */
+  0xa7, 0x1b, 0x03, 0x00,		/* aghi %r1, 0x300 */
+  0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24,	/* stg %r1, 0x278(%r15) */
+};
+
+/* Code sequence saving ARs, PSWM and FPC.  PSWM has to be assembled from
+   current PSWM (read by epsw) and CC from entry (in %r0).  */
+
+static const unsigned char s390_ft_entry_misc[] = {
+  0x9b, 0x0f, 0xf2, 0x80,		/* stam %a0, %a15, 0x20(%%r15) */
+  0xb9, 0x8d, 0x00, 0x23,		/* epsw %r2, %r3 */
+  0xa7, 0x18, 0xcf, 0xff,		/* lhi %r1, ~0x3000 */
+  0x14, 0x21,				/* nr %r2, %r1 */
+  0x16, 0x20,				/* or %r2, %r0 */
+  0x50, 0x20, 0xf2, 0xc0,		/* st %r2, 0x2c0(%r15) */
+  0x50, 0x30, 0xf2, 0xc4,		/* st %r3, 0x2c4(%r15) */
+  0xb2, 0x9c, 0xf2, 0xd0,		/* stfpc 0x2d0(%r15) */
+};
+
+/* Code sequence saving FRs, used if VX not supported.  */
+
+static const unsigned char s390_ft_entry_fr[] = {
+  0x60, 0x00, 0xf0, 0x00,		/* std %f0, 0x000(%r15) */
+  0x60, 0x10, 0xf0, 0x10,		/* std %f1, 0x010(%r15) */
+  0x60, 0x20, 0xf0, 0x20,		/* std %f2, 0x020(%r15) */
+  0x60, 0x30, 0xf0, 0x30,		/* std %f3, 0x030(%r15) */
+  0x60, 0x40, 0xf0, 0x40,		/* std %f4, 0x040(%r15) */
+  0x60, 0x50, 0xf0, 0x50,		/* std %f5, 0x050(%r15) */
+  0x60, 0x60, 0xf0, 0x60,		/* std %f6, 0x060(%r15) */
+  0x60, 0x70, 0xf0, 0x70,		/* std %f7, 0x070(%r15) */
+  0x60, 0x80, 0xf0, 0x80,		/* std %f8, 0x080(%r15) */
+  0x60, 0x90, 0xf0, 0x90,		/* std %f9, 0x090(%r15) */
+  0x60, 0xa0, 0xf0, 0xa0,		/* std %f10, 0x0a0(%r15) */
+  0x60, 0xb0, 0xf0, 0xb0,		/* std %f11, 0x0b0(%r15) */
+  0x60, 0xc0, 0xf0, 0xc0,		/* std %f12, 0x0c0(%r15) */
+  0x60, 0xd0, 0xf0, 0xd0,		/* std %f13, 0x0d0(%r15) */
+  0x60, 0xe0, 0xf0, 0xe0,		/* std %f14, 0x0e0(%r15) */
+  0x60, 0xf0, 0xf0, 0xf0,		/* std %f15, 0x0f0(%r15) */
+};
+
+/* Code sequence saving VRs, used if VX not supported.  */
+
+static const unsigned char s390_ft_entry_vr[] = {
+  0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e,	/* vstm %v0, %v15, 0x000(%r15) */
+  0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e,	/* vstm %v16, %v31, 0x100(%r15) */
+};
+
+/* Code sequence doing the collection call for 31-bit target.  %r1 contains
+   the address of the literal pool.  */
+
+static const unsigned char s390_ft_main_31[] = {
+  /* Load the literals into registers.  */
+  0x58, 0x50, 0x10, 0x00,		/* l %r5, 0x0(%r1) */
+  0x58, 0x20, 0x10, 0x04,		/* l %r2, 0x4(%r1) */
+  0x58, 0x40, 0x10, 0x08,		/* l %r4, 0x8(%r1) */
+  0x58, 0x60, 0x10, 0x0c,		/* l %r6, 0xc(%r1) */
+  /* Save original PSWA (tracepoint address | 0x80000000).  */
+  0x50, 0x50, 0xf2, 0xcc,		/* st %r5, 0x2cc(%r15) */
+  /* Construct a collecting_t object at %r15+0x2e0.  */
+  0x50, 0x20, 0xf2, 0xe0,		/* st %r2, 0x2e0(%r15) */
+  0x9b, 0x00, 0xf2, 0xe4,		/* stam %a0, %a0, 0x2e4(%r15) */
+  /* Move its address to %r0.  */
+  0x41, 0x00, 0xf2, 0xe0,		/* la %r0, 0x2e0(%r15) */
+  /* Take the lock.  */
+  /* .Lloop:  */
+  0xa7, 0x18, 0x00, 0x00,		/* lhi %r1, 0 */
+  0xba, 0x10, 0x60, 0x00,		/* cs %r1, %r0, 0(%r6) */
+  0xa7, 0x74, 0xff, 0xfc,		/* jne .Lloop */
+  /* Address of the register save block to %r3.  */
+  0x18, 0x3f,				/* lr %r3, %r15 */
+  /* Make a stack frame, so that we can call the collector.  */
+  0xa7, 0xfa, 0xff, 0xa0,		/* ahi %r15, -0x60 */
+  /* Call it.  */
+  0x0d, 0xe4,				/* basr %r14, %r4 */
+  /* And get rid of the stack frame again.  */
+  0x41, 0xf0, 0xf0, 0x60,		/* la %r15, 0x60(%r15) */
+  /* Leave the lock.  */
+  0x07, 0xf0, 				/* br %r0 */
+  0xa7, 0x18, 0x00, 0x00,		/* lhi %r1, 0 */
+  0x50, 0x10, 0x60, 0x00,		/* st %t1, 0(%r6) */
+};
+
+/* Code sequence doing the collection call for 64-bit target.  %r1 contains
+   the address of the literal pool.  */
+
+static const unsigned char s390_ft_main_64[] = {
+  /* Load the literals into registers.  */
+  0xe3, 0x50, 0x10, 0x00, 0x00, 0x04,	/* lg %r5, 0x00(%r1) */
+  0xe3, 0x20, 0x10, 0x08, 0x00, 0x04,	/* lg %r2, 0x08(%r1) */
+  0xe3, 0x40, 0x10, 0x10, 0x00, 0x04,	/* lg %r4, 0x10(%r1) */
+  0xe3, 0x60, 0x10, 0x18, 0x00, 0x04,	/* lg %r6, 0x18(%r1) */
+  /* Save original PSWA (tracepoint address).  */
+  0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24,	/* stg %r5, 0x2c8(%r15) */
+  /* Construct a collecting_t object at %r15+0x2e0.  */
+  0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24,	/* stg %r2, 0x2e0(%r15) */
+  0x9b, 0x01, 0xf2, 0xe8,		/* stam %a0, %a1, 0x2e8(%r15) */
+  /* Move its address to %r0.  */
+  0x41, 0x00, 0xf2, 0xe0,		/* la %r0, 0x2e0(%r15) */
+  /* Take the lock.  */
+  /* .Lloop:  */
+  0xa7, 0x19, 0x00, 0x00,		/* lghi %r1, 0 */
+  0xeb, 0x10, 0x60, 0x00, 0x00, 0x30,	/* csg %r1, %r0, 0(%r6) */
+  0xa7, 0x74, 0xff, 0xfb,		/* jne .Lloop */
+  /* Address of the register save block to %r3.  */
+  0xb9, 0x04, 0x00, 0x3f,		/* lgr %r3, %r15 */
+  /* Make a stack frame, so that we can call the collector.  */
+  0xa7, 0xfb, 0xff, 0x60,		/* aghi %r15, -0xa0 */
+  /* Call it.  */
+  0x0d, 0xe4,				/* basr %r14, %r4 */
+  /* And get rid of the stack frame again.  */
+  0x41, 0xf0, 0xf0, 0xa0,		/* la %r15, 0xa0(%r15) */
+  /* Leave the lock.  */
+  0x07, 0xf0,				/* br %r0 */
+  0xa7, 0x19, 0x00, 0x00,		/* lghi %r1, 0 */
+  0xe3, 0x10, 0x60, 0x00, 0x00, 0x24,	/* stg %t1, 0(%r6) */
+};
+
+/* Code sequence restoring FRs, for targets with no VX support.  */
+
+static const unsigned char s390_ft_exit_fr[] = {
+  0x68, 0x00, 0xf0, 0x00,		/* ld %f0, 0x000(%r15) */
+  0x68, 0x10, 0xf0, 0x10,		/* ld %f1, 0x010(%r15) */
+  0x68, 0x20, 0xf0, 0x20,		/* ld %f2, 0x020(%r15) */
+  0x68, 0x30, 0xf0, 0x30,		/* ld %f3, 0x030(%r15) */
+  0x68, 0x40, 0xf0, 0x40,		/* ld %f4, 0x040(%r15) */
+  0x68, 0x50, 0xf0, 0x50,		/* ld %f5, 0x050(%r15) */
+  0x68, 0x60, 0xf0, 0x60,		/* ld %f6, 0x060(%r15) */
+  0x68, 0x70, 0xf0, 0x70,		/* ld %f7, 0x070(%r15) */
+  0x68, 0x80, 0xf0, 0x80,		/* ld %f8, 0x080(%r15) */
+  0x68, 0x90, 0xf0, 0x90,		/* ld %f9, 0x090(%r15) */
+  0x68, 0xa0, 0xf0, 0xa0,		/* ld %f10, 0x0a0(%r15) */
+  0x68, 0xb0, 0xf0, 0xb0,		/* ld %f11, 0x0b0(%r15) */
+  0x68, 0xc0, 0xf0, 0xc0,		/* ld %f12, 0x0c0(%r15) */
+  0x68, 0xd0, 0xf0, 0xd0,		/* ld %f13, 0x0d0(%r15) */
+  0x68, 0xe0, 0xf0, 0xe0,		/* ld %f14, 0x0e0(%r15) */
+  0x68, 0xf0, 0xf0, 0xf0,		/* ld %f15, 0x0f0(%r15) */
+};
+
+/* Code sequence restoring VRs.  */
+
+static const unsigned char s390_ft_exit_vr[] = {
+  0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36,	/* vlm %v0, %v15, 0x000(%r15) */
+  0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36,	/* vlm %v16, %v31, 0x100(%r15) */
+};
+
+/* Code sequence restoring misc registers.  As for PSWM, only CC should be
+   modified by C code, so we use the alr instruction to restore it by
+   manufacturing an operand that'll result in the original flags.  */
+
+static const unsigned char s390_ft_exit_misc[] = {
+  0xb2, 0x9d, 0xf2, 0xd0,		/* lfpc 0x2d0(%r15) */
+  0x58, 0x00, 0xf2, 0xc0,		/* l %r0, 0x2c0(%r15) */
+  /* Extract CC to high 2 bits of %r0.  */
+  0x88, 0x00, 0x00, 0x0c,		/* srl %r0, 12 */
+  0x89, 0x00, 0x00, 0x1e,		/* sll %r0, 30 */
+  /* Add %r0 to itself.  Result will be nonzero iff CC bit 0 is set, and
+     will have carry iff CC bit 1 is set - resulting in the same flags
+     as the original.  */
+  0x1e, 0x00,				/* alr %r0, %r0 */
+  0x9a, 0x0f, 0xf2, 0x80,		/* lam %a0, %a15, 0x280(%r15) */
+};
+
+/* Code sequence restoring GPRs, for 31-bit targets with no high GPRs.  */
+
+static const unsigned char s390_ft_exit_gpr_esa[] = {
+  0x58, 0x00, 0xf2, 0x04,		/* l %r0, 0x204(%r15) */
+  0x58, 0x10, 0xf2, 0x0c,		/* l %r1, 0x20c(%r15) */
+  0x58, 0x20, 0xf2, 0x14,		/* l %r2, 0x214(%r15) */
+  0x58, 0x30, 0xf2, 0x1c,		/* l %r3, 0x21c(%r15) */
+  0x58, 0x40, 0xf2, 0x24,		/* l %r4, 0x224(%r15) */
+  0x58, 0x50, 0xf2, 0x2c,		/* l %r5, 0x22c(%r15) */
+  0x58, 0x60, 0xf2, 0x34,		/* l %r6, 0x234(%r15) */
+  0x58, 0x70, 0xf2, 0x3c,		/* l %r7, 0x23c(%r15) */
+  0x58, 0x80, 0xf2, 0x44,		/* l %r8, 0x244(%r15) */
+  0x58, 0x90, 0xf2, 0x4c,		/* l %r9, 0x24c(%r15) */
+  0x58, 0xa0, 0xf2, 0x54,		/* l %r10, 0x254(%r15) */
+  0x58, 0xb0, 0xf2, 0x5c,		/* l %r11, 0x25c(%r15) */
+  0x58, 0xc0, 0xf2, 0x64,		/* l %r12, 0x264(%r15) */
+  0x58, 0xd0, 0xf2, 0x6c,		/* l %r13, 0x26c(%r15) */
+  0x58, 0xe0, 0xf2, 0x74,		/* l %r14, 0x274(%r15) */
+  0x58, 0xf0, 0xf2, 0x7c,		/* l %r15, 0x27c(%r15) */
+};
+
+/* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
+   with high GPRs.  */
+
+static const unsigned char s390_ft_exit_gpr_zarch[] = {
+  0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04,	/* lmg %r0, %r15, 0x200(%r15) */
+};
+
+static void
+append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
+{
+  write_inferior_memory (*to, buf, len);
+  *to += len;
+}
+
+static int
+s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
+{
+  gdb_byte buf[6];
+  int ilen;
+  int op2;
+  /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup.  */
+  int mode = 0;
+  int is_bras = 0;
+  read_inferior_memory (oldloc, buf, sizeof buf);
+  if (buf[0] < 0x40)
+    ilen = 2;
+  else if (buf[0] < 0xc0)
+    ilen = 4;
+  else
+    ilen = 6;
+  switch (buf[0])
+    {
+    case 0x05: /* BALR */
+    case 0x0c: /* BASSM */
+    case 0x0d: /* BASR */
+    case 0x45: /* BAL */
+    case 0x4d: /* BAS */
+      /* These save a return address and mess around with registers.
+         We can't relocate them.  */
+      return 1;
+    case 0x84: /* BRXH */
+    case 0x85: /* BRXLE */
+      mode = 1;
+      break;
+    case 0xa7:
+      op2 = buf[1] & 0xf;
+      /* BRC, BRAS, BRCT, BRCTG */
+      if (op2 >= 4 && op2 <= 7)
+	mode = 1;
+      /* BRAS */
+      if (op2 == 5)
+	is_bras = 1;
+      break;
+    case 0xc0:
+      op2 = buf[1] & 0xf;
+      /* LARL, BRCL, BRASL */
+      if (op2 == 0 || op2 == 4 || op2 == 5)
+	mode = 2;
+      /* BRASL */
+      if (op2 == 5)
+	is_bras = 1;
+      break;
+    case 0xc4:
+    case 0xc6:
+      /* PC-relative addressing instructions.  */
+      mode = 2;
+      break;
+    case 0xc5: /* BPRP */
+    case 0xc7: /* BPP */
+      /* Branch prediction - just skip it.  */
+      return 0;
+    case 0xcc:
+      op2 = buf[1] & 0xf;
+      /* BRCTH */
+      if (op2 == 6)
+	mode = 2;
+      break;
+    case 0xec:
+      op2 = buf[5];
+      switch (op2)
+        {
+	case 0x44: /* BRXHG */
+	case 0x45: /* BRXLG */
+	case 0x64: /* CGRJ */
+	case 0x65: /* CLGRJ */
+	case 0x76: /* CRJ */
+	case 0x77: /* CLRJ */
+	  mode = 1;
+	  break;
+        }
+      break;
+    }
+
+  if (mode != 0)
+    {
+      /* We'll have to relocate an instruction with a PC-relative field.
+	 First, compute the target.  */
+      int64_t loffset = 0;
+      CORE_ADDR target;
+      if (mode == 1)
+        {
+	  int16_t soffset = 0;
+	  memcpy (&soffset, buf+2, 2);
+	  loffset = soffset;
+        }
+      else if (mode == 2)
+        {
+	  int32_t soffset = 0;
+	  memcpy (&soffset, buf+2, 4);
+	  loffset = soffset;
+        }
+      target = oldloc + loffset * 2;
+      if (!is_64)
+	target &= 0x7fffffff;
+
+      if (is_bras)
+        {
+	  /* BRAS or BRASL was used.  We cannot just relocate those, since
+	     they save the return address in a register.  We can, however,
+	     replace them with a LARL+JG sequence.  */
+
+	  /* Make the LARL.  */
+	  int32_t soffset;
+	  buf[0] = 0xc0;
+	  buf[1] &= 0xf0;
+	  loffset = oldloc + ilen - *to;
+	  loffset >>= 1;
+	  soffset = loffset;
+	  if (soffset != loffset && is_64)
+	    return 1;
+	  memcpy (buf+2, &soffset, 4);
+	  append_insns (to, 6, buf);
+
+	  /* XXX: this is not fully correct.  In 31-bit mode, LARL will write
+	     an address with the top bit 0, while BRAS/BRASL will write it
+	     with top bit 1.  It should not matter much, since linux compilers
+	     use BR and not BSM to return from functions, but it could confuse
+	     some poor stack unwinder.  */
+
+	  /* We'll now be writing a JG.  */
+	  mode = 2;
+	  buf[0] = 0xc0;
+	  buf[1] = 0xf4;
+	  ilen = 6;
+	}
+
+      /* Compute the new offset and write it to the buffer.  */
+      loffset = target - *to;
+      loffset >>= 1;
+
+      if (mode == 1)
+        {
+	  int16_t soffset = loffset;
+	  if (soffset != loffset)
+	    return 1;
+	  memcpy (buf+2, &soffset, 2);
+        }
+      else if (mode == 2)
+        {
+	  int32_t soffset = loffset;
+	  if (soffset != loffset && is_64)
+	    return 1;
+	  memcpy (buf+2, &soffset, 4);
+        }
+    }
+  append_insns (to, ilen, buf);
+  return 0;
+}
+
+/* Implementation of linux_target_ops method
+   "install_fast_tracepoint_jump_pad".  */
+
+static int
+s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
+				       CORE_ADDR tpaddr,
+				       CORE_ADDR collector,
+				       CORE_ADDR lockaddr,
+				       ULONGEST orig_size,
+				       CORE_ADDR *jump_entry,
+				       CORE_ADDR *trampoline,
+				       ULONGEST *trampoline_size,
+				       unsigned char *jjump_pad_insn,
+				       ULONGEST *jjump_pad_insn_size,
+				       CORE_ADDR *adjusted_insn_addr,
+				       CORE_ADDR *adjusted_insn_addr_end,
+				       char *err)
+{
+  int i;
+  int64_t loffset;
+  int32_t offset;
+  unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 };	/* jg ... */
+  CORE_ADDR buildaddr = *jump_entry;
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  int is_64 = register_size (regcache->tdesc, 0) == 8;
+  int is_zarch = is_64 || have_hwcap_s390_high_gprs;
+  int has_vx = have_hwcap_s390_vx;
+#else
+  int is_64 = 0, is_zarch = 0, has_vx = 0;
+#endif
+  CORE_ADDR literals[4] = {
+    tpaddr,
+    tpoint,
+    collector,
+    lockaddr,
+  };
+
+  /* First, store the GPRs.  */
+  if (!is_zarch)
+    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa, s390_ft_entry_gpr_esa);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch, s390_ft_entry_gpr_zarch);
+
+  /* Second, misc registers (ARs, PSWM, FPC).  PSWA will be stored below.  */
+  append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
+
+  /* Third, FRs or VRs.  */
+  if (!has_vx)
+    append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
+
+  /* Now, the main part of code - store PSWA, take lock, call collector,
+     leave lock.  First, we'll need to fetch 4 literals.  */
+  if (!is_64) {
+    unsigned char buf[] = {
+      0x07, 0x07,		/* nopr %r7 */
+      0xa7, 0x15, 0x00, 0x0a,	/* bras %r1, .Lend */
+      0, 0, 0, 0,		/* tpaddr */
+      0, 0, 0, 0,		/* tpoint */
+      0, 0, 0, 0,		/* collector */
+      0, 0, 0, 0,		/* lockaddr */
+      /* .Lend: */
+    };
+    /* Find the proper start place in buf, so that literals will be
+       aligned. */
+    int bufpos = (buildaddr + 2) & 3;
+    /* First literal will be saved as the PSWA, make sure it has the high bit
+       set.  */
+    literals[0] |= 0x80000000;
+    /* Stuff the literals into the buffer. */
+    for (i = 0; i < 4; i++) {
+      uint32_t lit = literals[i];
+      memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
+    }
+    append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
+    append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
+  } else {
+    unsigned char buf[] = {
+      0x07, 0x07,		/* nopr %r7 */
+      0x07, 0x07,		/* nopr %r7 */
+      0x07, 0x07,		/* nopr %r7 */
+      0xa7, 0x15, 0x00, 0x12,	/* bras %r1, .Lend */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* tpaddr */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* tpoint */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* collector */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* lockaddr */
+      /* .Lend: */
+    };
+    /* Find the proper start place in buf, so that literals will be
+       aligned. */
+    int bufpos = (buildaddr + 2) & 7;
+    /* Stuff the literals into the buffer. */
+    for (i = 0; i < 4; i++) {
+      uint64_t lit = literals[i];
+      memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
+    }
+    append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
+    append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
+  }
+
+  /* Restore FRs or VRs.  */
+  if (!has_vx)
+    append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
+
+  /* Restore misc registers.  */
+  append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
+
+  /* Restore the GPRs.  */
+  if (!is_zarch)
+    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa, s390_ft_exit_gpr_esa);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch, s390_ft_exit_gpr_zarch);
+
+  /* Now, adjust the original instruction to execute in the jump
+     pad.  */
+  *adjusted_insn_addr = buildaddr;
+  if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
+    {
+      sprintf (err, "E.Could not relocate instruction for tracepoint.");
+      return 1;
+    }
+  *adjusted_insn_addr_end = buildaddr;
+
+  /* Finally, write a jump back to the program.  */
+
+  loffset = (tpaddr + orig_size) - buildaddr;
+  loffset >>= 1;
+  offset = loffset;
+  if (is_64 && offset != loffset)
+    {
+      sprintf (err,
+	       "E.Jump back from jump pad too far from tracepoint "
+	       "(offset 0x%" PRIx64 " > int33).", loffset);
+      return 1;
+    }
+  memcpy (jbuf + 2, &offset, 4);
+  append_insns (&buildaddr, sizeof jbuf, jbuf);
+
+  /* The jump pad is now built.  Wire in a jump to our jump pad.  This
+     is always done last (by our caller actually), so that we can
+     install fast tracepoints with threads running.  This relies on
+     the agent's atomic write support.  */
+  loffset = *jump_entry - tpaddr;
+  loffset >>= 1;
+  offset = loffset;
+  if (is_64 && offset != loffset)
+    {
+      sprintf (err,
+	       "E.Jump back from jump pad too far from tracepoint "
+	       "(offset 0x%" PRIx64 " > int33).", loffset);
+      return 1;
+    }
+  memcpy (jbuf + 2, &offset, 4);
+  memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
+  *jjump_pad_insn_size = sizeof jbuf;
+
+  /* Return the end address of our pad.  */
+  *jump_entry = buildaddr;
+
+  return 0;
+}
+
+/* Implementation of linux_target_ops method
+   "get_min_fast_tracepoint_insn_len".  */
+
+static int
+s390_get_min_fast_tracepoint_insn_len (void)
+{
+  /* We only support using 6-byte jumps to reach the tracepoint code.
+     If the tracepoint buffer were allocated sufficiently close (64kiB)
+     to the executable code, and the traced instruction itself was close
+     enough to the beginning, we could use 4-byte jumps, but this doesn't
+     seem to be worth the effort.  */
+  return 6;
+}
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -721,10 +1373,10 @@ struct linux_target_ops the_low_target = {
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
   s390_supports_tracepoints,
-  NULL, /* get_thread_area */
-  NULL, /* install_fast_tracepoint_jump_pad */
+  s390_get_thread_area,
+  s390_install_fast_tracepoint_jump_pad,
   NULL, /* emit_ops */
-  NULL, /* get_min_fast_tracepoint_insn_len */
+  s390_get_min_fast_tracepoint_insn_len,
   NULL, /* supports_range_stepping */
   NULL, /* breakpoint_kind_from_current_state */
   s390_supports_hardware_single_step,
-- 
2.7.0

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (7 preceding siblings ...)
  2016-01-24 12:13 ` [PATCH 6/8] gdbserver/s390: Add fast tracepoint support Marcin Kościelnicki
@ 2016-01-25 13:27 ` Antoine Tremblay
  2016-01-25 13:56 ` Pedro Alves
  2016-02-12 11:04 ` Marcin Kościelnicki
  10 siblings, 0 replies; 89+ messages in thread
From: Antoine Tremblay @ 2016-01-25 13:27 UTC (permalink / raw)
  To: Marcin Kościelnicki, gdb-patches



On 01/24/2016 07:12 AM, Marcin Kościelnicki wrote:
>
> There are also three issues affecting s390 tracepoints that don't show
> up in the testsuite:
>
> 1. Target independent: tfile format doesn't contain target information
>     (tdesc).  While this affects all platforms with multiple tdescs
>     (eg. x86_64 is unable to pull AVX registers from tfile for that
>     reason), it horribly breaks 31-bit s390 with high GPRs - it has
>     a completely different GPR layout from plain 31-bit s390, so the
>     collected registers will be garbled.  I suppose the proper fix to
>     that would be to add tdesc information to tfile format.  Unfortunately,
>     I don't see a way to extend it in a backwards-compatible way.

I've had this problem too with tracepoint support for arm.. for me it 
creates problems in the test suite see : unavailable locals, 
https://sourceware.org/ml/gdb-patches/2016-01/msg00113.html

I'm also wondering how this could be fixed...

This patch might also be of interest for targets with multiple tdesc:
https://sourceware.org/ml/gdb-patches/2016-01/msg00115.html

>
> 2. Target independent: 32-bit (or 31-bit for us) IPA cannot be used with
>     64-bit gdbserver, due to communication involving lots of structs with
>     pointer types.  Fixing that would be quite involved, but possible
>     (I don't suppose we have to maintain compatibility between IPA/gdbserver
>     from different gdb versions?).
>

Note, I've come across other problems with these structs like their 
alignment, I have a patch to pack them in the pipeline and thus I assume 
we don't have to keep compatibility too.

A more flexible ABI to communicate would be nice.

> 3. s390 specific: 31-bit gdbserver doesn't know about high GPRs, and
>     cannot collect them if they're in use.  Seems fixable with average
>     effort.  Unfortunately, fixing that will break tfile, unless (1)
>     is fixed first...
>

It seems a good idea to tech 31-bit gdbserver about the high GPRS, at 
least it should work when you have a gdbserver connected since the 
proper tdesc would be read, even if tfile doesn't work it would be a plus ?

And using set tdesc could then be a workaround for tfile to work too ?
At least until there's a better solution.

Regards,
Antoine

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (8 preceding siblings ...)
  2016-01-25 13:27 ` [PATCH 0/8] gdb/s390: Add regular and " Antoine Tremblay
@ 2016-01-25 13:56 ` Pedro Alves
  2016-01-25 14:28   ` Marcin Kościelnicki
  2016-02-12 11:04 ` Marcin Kościelnicki
  10 siblings, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-01-25 13:56 UTC (permalink / raw)
  To: Marcin Kościelnicki, gdb-patches

On 01/24/2016 12:12 PM, Marcin Kościelnicki wrote:

> 1. Target independent: tfile format doesn't contain target information
>    (tdesc).  While this affects all platforms with multiple tdescs
>    (eg. x86_64 is unable to pull AVX registers from tfile for that
>    reason), it horribly breaks 31-bit s390 with high GPRs - it has
>    a completely different GPR layout from plain 31-bit s390, so the
>    collected registers will be garbled.  I suppose the proper fix to
>    that would be to add tdesc information to tfile format.  

Yes, I think so too.

> Unfortunately, I don't see a way to extend it in a backwards-compatible way.

The trace file header is just a list of newline-terminated lines.
We're free to add more header lines - older gdb's just warn about
unknown lines.  See tfile_interp_line.

Thanks,
Pedro Alves

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-25 13:56 ` Pedro Alves
@ 2016-01-25 14:28   ` Marcin Kościelnicki
  2016-01-25 15:57     ` Pedro Alves
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-25 14:28 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

On 25/01/16 14:56, Pedro Alves wrote:
> On 01/24/2016 12:12 PM, Marcin Kościelnicki wrote:
>
>> 1. Target independent: tfile format doesn't contain target information
>>     (tdesc).  While this affects all platforms with multiple tdescs
>>     (eg. x86_64 is unable to pull AVX registers from tfile for that
>>     reason), it horribly breaks 31-bit s390 with high GPRs - it has
>>     a completely different GPR layout from plain 31-bit s390, so the
>>     collected registers will be garbled.  I suppose the proper fix to
>>     that would be to add tdesc information to tfile format.
>
> Yes, I think so too.
>
>> Unfortunately, I don't see a way to extend it in a backwards-compatible way.
>
> The trace file header is just a list of newline-terminated lines.
> We're free to add more header lines - older gdb's just warn about
> unknown lines.  See tfile_interp_line.
>
> Thanks,
> Pedro Alves
>

Very well.

I was thinking of just stuffing the XML in the header.  We can avoid 
embedded newlines through hex-encoding it (or just stripping them, 
shouldn't hurt XML...), and copy it straight from the target.  That 
would fail for targets that don't get tdesc from XML, but I'm not sure 
we should worry about it.  An alternative would be to invent some 
serialization format for tdesc in tfile, but why do that when we already 
have a perfectly good one...

Should be quite simple, really.  Does that sound OK?

Marcin Kościelnicki

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

* Re: [PATCH 6/8] gdbserver/s390: Add fast tracepoint support.
  2016-01-24 12:13 ` [PATCH 6/8] gdbserver/s390: Add fast tracepoint support Marcin Kościelnicki
@ 2016-01-25 14:34   ` Antoine Tremblay
  2016-02-19 13:41     ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Antoine Tremblay @ 2016-01-25 14:34 UTC (permalink / raw)
  To: gdb-patches, Marcin Kościelnicki



On 01/24/2016 07:12 AM, Marcin Kościelnicki wrote:

> +void
> +initialize_low_tracepoint (void)
> +{
> +  unsigned long hwcap = getauxval (AT_HWCAP);

You might consider also using proc if getauxval is not available ?

unsigned long hwcap = 0;

#ifdef HAVE_GETAUXVAL
   hwcap = getauxval (AT_HWCAP);
#else
   unsigned long data[2];
   FILE *f = fopen ("/proc/self/auxv", "r");

   if (f == NULL)
     return;

   while (fread (data, sizeof (data), 1, f) > 0)
     {
      if (data[0] == AT_HWCAP)
        {
          hwcap = data[1];
          break;
        }
     }

   fclose (f);


Regards,
Antoine

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-25 14:28   ` Marcin Kościelnicki
@ 2016-01-25 15:57     ` Pedro Alves
  2016-01-25 16:03       ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-01-25 15:57 UTC (permalink / raw)
  To: Marcin Kościelnicki, gdb-patches

On 01/25/2016 02:28 PM, Marcin Kościelnicki wrote:
> On 25/01/16 14:56, Pedro Alves wrote:
>> On 01/24/2016 12:12 PM, Marcin Kościelnicki wrote:
>>
>>> 1. Target independent: tfile format doesn't contain target information
>>>     (tdesc).  While this affects all platforms with multiple tdescs
>>>     (eg. x86_64 is unable to pull AVX registers from tfile for that
>>>     reason), it horribly breaks 31-bit s390 with high GPRs - it has
>>>     a completely different GPR layout from plain 31-bit s390, so the
>>>     collected registers will be garbled.  I suppose the proper fix to
>>>     that would be to add tdesc information to tfile format.
>>
>> Yes, I think so too.
>>
>>> Unfortunately, I don't see a way to extend it in a backwards-compatible way.
>>
>> The trace file header is just a list of newline-terminated lines.
>> We're free to add more header lines - older gdb's just warn about
>> unknown lines.  See tfile_interp_line.
>>
>> Thanks,
>> Pedro Alves
>>
> 
> Very well.
> 
> I was thinking of just stuffing the XML in the header.  We can avoid 
> embedded newlines through hex-encoding it (or just stripping them, 
> shouldn't hurt XML...), and copy it straight from the target.  That 
> would fail for targets that don't get tdesc from XML, but I'm not sure 
> we should worry about it.  An alternative would be to invent some 
> serialization format for tdesc in tfile, but why do that when we already 
> have a perfectly good one...
> 
> Should be quite simple, really.  Does that sound OK?

Yes.

Thanks,
Pedro Alves

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-25 15:57     ` Pedro Alves
@ 2016-01-25 16:03       ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-25 16:03 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

On 25/01/16 16:56, Pedro Alves wrote:
> On 01/25/2016 02:28 PM, Marcin Kościelnicki wrote:
>> On 25/01/16 14:56, Pedro Alves wrote:
>>> On 01/24/2016 12:12 PM, Marcin Kościelnicki wrote:
>>>
>>>> 1. Target independent: tfile format doesn't contain target information
>>>>      (tdesc).  While this affects all platforms with multiple tdescs
>>>>      (eg. x86_64 is unable to pull AVX registers from tfile for that
>>>>      reason), it horribly breaks 31-bit s390 with high GPRs - it has
>>>>      a completely different GPR layout from plain 31-bit s390, so the
>>>>      collected registers will be garbled.  I suppose the proper fix to
>>>>      that would be to add tdesc information to tfile format.
>>>
>>> Yes, I think so too.
>>>
>>>> Unfortunately, I don't see a way to extend it in a backwards-compatible way.
>>>
>>> The trace file header is just a list of newline-terminated lines.
>>> We're free to add more header lines - older gdb's just warn about
>>> unknown lines.  See tfile_interp_line.
>>>
>>> Thanks,
>>> Pedro Alves
>>>
>>
>> Very well.
>>
>> I was thinking of just stuffing the XML in the header.  We can avoid
>> embedded newlines through hex-encoding it (or just stripping them,
>> shouldn't hurt XML...), and copy it straight from the target.  That
>> would fail for targets that don't get tdesc from XML, but I'm not sure
>> we should worry about it.  An alternative would be to invent some
>> serialization format for tdesc in tfile, but why do that when we already
>> have a perfectly good one...
>>
>> Should be quite simple, really.  Does that sound OK?
>
> Yes.
>
> Thanks,
> Pedro Alves
>

Alright, I'm getting started on it, then.

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

* Re: [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch.
  2016-01-24 12:12 ` [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch Marcin Kościelnicki
@ 2016-01-26 14:58   ` Andreas Arnez
  2016-02-07 13:59     ` [PATCH 1/8] gdb: Add supply_pseudo_pc " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-01-26 14:58 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Jan 24 2016, Marcin Kościelnicki wrote:

> When we're looking at a tracefile trace frame where registers are not
> available, and the tracepoint has only one location, we supply
> the location's address as the PC register.  However, this only works
> if PC is not a pseudo register.  Add a gdbarch hook that will handle
> that for pseudo registers.

> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index 4ac6b90..b67ea72 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -417,6 +417,7 @@ v:int:char_signed:::1:-1:1
>  #
>  F:CORE_ADDR:read_pc:struct regcache *regcache:regcache
>  F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
> +F:void:write_guessed_tracepoint_pc:struct regcache *regcache, CORE_ADDR val:regcache, val

Rather than write_guessed_tracepoint_pc, maybe the method could be named
more generically, like "supply_pc"?  Also, a comment describing the
method's purpose and interface would be nice, particularly how it
differs from the "write_pc" method or from regcache_write_pc().

>  # Function for getting target's idea of a frame pointer.  FIXME: GDB's
>  # whole scheme for dealing with "frames" and "frame pointers" needs a
>  # serious shakedown.
> diff --git a/gdb/tracefile.c b/gdb/tracefile.c
> index fef4ed9..7c2649d 100644
> --- a/gdb/tracefile.c
> +++ b/gdb/tracefile.c
> @@ -396,16 +396,18 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
>       as the address of the tracepoint.  */
>    pc_regno = gdbarch_pc_regnum (gdbarch);
>  
> -  /* XXX This guessing code below only works if the PC register isn't
> -     a pseudo-register.  The value of a pseudo-register isn't stored
> -     in the (non-readonly) regcache -- instead it's recomputed
> -     (probably from some other cached raw register) whenever the
> -     register is read.  This guesswork should probably move to some
> -     higher layer.  */

I wonder whether the last statement in this comment still applies?

> -  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
> +  if (pc_regno < 0)
>      return;
>  
> -  if (regno == -1 || regno == pc_regno)
> +  /* We try to guess PC if:
> +
> +     1) We want all registers, or
> +     2) PC is a real register, and we want exactly it, or
> +     3) PC is a pseudo register (we don't know which real register it
> +        corresponds to, so let's try to play safe).  */
> +
> +  if (regno == -1 || regno == pc_regno ||
> +      pc_regno >= gdbarch_num_regs (gdbarch))
>      {
>        struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
>        gdb_byte *regs;
> @@ -429,11 +431,23 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
>  	      return;
>  	    }
>  
> -	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
> -	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
> -				  gdbarch_byte_order (gdbarch),
> -				  tp->base.loc->address);
> -	  regcache_raw_supply (regcache, pc_regno, regs);
> +	  if (pc_regno >= gdbarch_num_regs (gdbarch))
> +	    {
> +	      /* PC is a pseudo, let gdbarch deal with that.  If it doesn't
> +	         know how, just bail.  */

Nit: The indentation space of this line and the second one below
contains 8 consecutive spaces where a tab could be used instead.  This
occurs several times in the patch series.

> +	      if (gdbarch_write_guessed_tracepoint_pc_p (gdbarch))
> +	        gdbarch_write_guessed_tracepoint_pc (gdbarch, regcache,
> +						     tp->base.loc->address);
> +	    }
> +	  else
> +	    {
> +	      /* PC is a real register.  */
> +	      regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
> +	      store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
> +				      gdbarch_byte_order (gdbarch),
> +				      tp->base.loc->address);
> +	      regcache_raw_supply (regcache, pc_regno, regs);
> +	    }
>  	}
>      }
>  }

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

* Re: [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook.
  2016-01-24 12:12 ` [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook Marcin Kościelnicki
@ 2016-01-26 18:12   ` Andreas Arnez
  2016-01-26 19:26     ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-01-26 18:12 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Jan 24 2016, Marcin Kościelnicki wrote:

> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index e827684..c4d25d2 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -167,6 +167,22 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
>      regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
>  }
>  
> +static void
> +s390_write_guessed_tracepoint_pc (struct regcache *regcache, CORE_ADDR pc)

Please add documentation for this function, as described here:

  https://sourceware.org/gdb/wiki/Internals%20GDB-C-Coding-Standards#Document_Every_Subprogram

Note that this was not always done in the past; thus there are still
many undocumented functions in this file.  But for new functions we
should stick to it.

> +{
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
> +  gdb_byte *reg = (gdb_byte *) alloca (sz);
> +
> +  /* 31-bit PSWA needs high bit set.  */
> +  if (tdep->abi == ABI_LINUX_S390)
> +    pc |= 0x80000000;

This is done differently in s390_pseudo_register_write: the high bit is
copied from the original PSWA.  Of course, this only makes a difference
if a program ever switches to 24-bit mode (yikes).  I just wonder
whether both cases should be treated the same, or whether there's good
reason not to.

> +
> +  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pc);
> +  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
> +}
> +
>  
>  /* DWARF Register Mapping.  */
>  
> @@ -7857,6 +7873,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  					    s390_iterate_over_regset_sections);
>    set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
>    set_gdbarch_write_pc (gdbarch, s390_write_pc);
> +  set_gdbarch_write_guessed_tracepoint_pc (gdbarch, s390_write_guessed_tracepoint_pc);
>    set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
>    set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
>    set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);

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

* Re: [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds.
  2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
@ 2016-01-26 18:17   ` Andreas Arnez
  2016-01-29  9:53     ` [PATCH] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-01-26 18:17 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Jan 24 2016, Marcin Kościelnicki wrote:

> It seems the 180 seconds timeout is quite tight on my z13 machine,
> and causes failures when the machine is somewhat loaded.
>
> gdb/testsuite/ChangeLog:
>
> 	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
> ---

[...]


> diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
> index e638839..204eda7 100644
> --- a/gdb/testsuite/gdb.trace/tspeed.exp
> +++ b/gdb/testsuite/gdb.trace/tspeed.exp
> @@ -27,7 +27,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
>  }
>  
>  # Typically we need a little extra time for this test.
> -set timeout 180
> +set timeout 300

This doesn't match the ChangeLog entry and patch description ;-)

>  
>  set ws "\[\r\n\t \]+"
>  set cr "\[\r\n\]+"

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

* Re: [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook.
  2016-01-26 18:12   ` Andreas Arnez
@ 2016-01-26 19:26     ` Marcin Kościelnicki
  2016-01-29 18:57       ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-26 19:26 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 26/01/16 19:12, Andreas Arnez wrote:
> On Sun, Jan 24 2016, Marcin Kościelnicki wrote:
>
>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>> index e827684..c4d25d2 100644
>> --- a/gdb/s390-linux-tdep.c
>> +++ b/gdb/s390-linux-tdep.c
>> @@ -167,6 +167,22 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
>>       regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
>>   }
>>
>> +static void
>> +s390_write_guessed_tracepoint_pc (struct regcache *regcache, CORE_ADDR pc)
>
> Please add documentation for this function, as described here:
>
>    https://sourceware.org/gdb/wiki/Internals%20GDB-C-Coding-Standards#Document_Every_Subprogram
>
> Note that this was not always done in the past; thus there are still
> many undocumented functions in this file.  But for new functions we
> should stick to it.

OK, will do.
>
>> +{
>> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>> +  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
>> +  gdb_byte *reg = (gdb_byte *) alloca (sz);
>> +
>> +  /* 31-bit PSWA needs high bit set.  */
>> +  if (tdep->abi == ABI_LINUX_S390)
>> +    pc |= 0x80000000;
>
> This is done differently in s390_pseudo_register_write: the high bit is
> copied from the original PSWA.  Of course, this only makes a difference
> if a program ever switches to 24-bit mode (yikes).  I just wonder
> whether both cases should be treated the same, or whether there's good
> reason not to.

If write_guessed_tracepoint_pc is called, we explicitely have no 
registers data other than PC itself - there's no original PSWA to speak 
of.  The state of PSWA high bit probably doesn't matter all that much, 
but since we want to mark PSWA as known, we'd better write the 
reasonable value to it.
>
>> +
>> +  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pc);
>> +  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
>> +}
>> +
>>
>>   /* DWARF Register Mapping.  */
>>
>> @@ -7857,6 +7873,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>   					    s390_iterate_over_regset_sections);
>>     set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
>>     set_gdbarch_write_pc (gdbarch, s390_write_pc);
>> +  set_gdbarch_write_guessed_tracepoint_pc (gdbarch, s390_write_guessed_tracepoint_pc);
>>     set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
>>     set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
>>     set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
>

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

* [PATCH] gdb.trace: Bump tspeed.exp timeout to 600 seconds.
  2016-01-26 18:17   ` Andreas Arnez
@ 2016-01-29  9:53     ` Marcin Kościelnicki
  2016-02-12 11:20       ` Yao Qi
  2016-02-18 18:54       ` Marcin Kościelnicki
  0 siblings, 2 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-01-29  9:53 UTC (permalink / raw)
  To: arnez; +Cc: gdb-patches, Marcin Kościelnicki

It seems the 180 seconds timeout is quite tight on my z13 machine,
and causes failures when the machine is somewhat loaded.

gdb/testsuite/ChangeLog:

	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
---
Whoops, changing to 600.  300 was quite enough for me, and what I initially
selected, but I figured it'd be good to leave some more headroom for slower
machines.

 gdb/testsuite/ChangeLog            | 4 ++++
 gdb/testsuite/gdb.trace/tspeed.exp | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 17474de..fa61847 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
 	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
 	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
index e638839..59d6605 100644
--- a/gdb/testsuite/gdb.trace/tspeed.exp
+++ b/gdb/testsuite/gdb.trace/tspeed.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
 }
 
 # Typically we need a little extra time for this test.
-set timeout 180
+set timeout 600
 
 set ws "\[\r\n\t \]+"
 set cr "\[\r\n\]+"
-- 
2.7.0

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

* Re: [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook.
  2016-01-26 19:26     ` Marcin Kościelnicki
@ 2016-01-29 18:57       ` Andreas Arnez
  2016-02-07 14:00         ` [PATCH 2/8] gdb/s390: Fill supply_pseudo_pc hook Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-01-29 18:57 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches, Ulrich Weigand

On Tue, Jan 26 2016, Marcin Kościelnicki wrote:

> If write_guessed_tracepoint_pc is called, we explicitely have no
> registers data other than PC itself - there's no original PSWA to
> speak of.  The state of PSWA high bit probably doesn't matter all that
> much, but since we want to mark PSWA as known, we'd better write the
> reasonable value to it.

That's true if the new gdbarch method implements a very specific
semantic, tailored to the singular use in tracefile_fetch_registers and
not necessarily usable for any other purposes.  But I interpreted the
semantic more generically: "Supply VAL as the new PC to the given
REGCACHE".

Maybe the generic approach could be implemented like this (completely
untested):

  /* Adjust PSWA high bit if in 31-bit mode.  */
  if (sz == 4)
    {
      if (regcache_register_status (regcache, S390_PSWA_REGNUM)
	  == REG_VALID)
	{
	  gdb_byte pswa[4];

	  regcache_raw_collect (regcache, S390_PSWA_REGNUM, pswa);
	  pc |= 0x80000000 & extract_unsigned_integer (pswa, 4, byte_order);
	}
      else
	pc |= 0x80000000;
    }

BTW, even this may be considered a special case of a hypothetical
gdbarch method pseudo_register_supply().  *Or* we might think of it as
writing to a "cache-only" (rather than read-only) regcache via a usual
regcache_cooked_write().  In this case no new gdbarch method would be
needed.  Such a feature might also come handy when trying to support the
modification of cooked registers during core file debugging, such as
discussed in this thread:

  https://www.sourceware.org/ml/gdb/2011-02/msg00042.html

--
Andreas

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

* [PATCH 1/8] gdb: Add supply_pseudo_pc hook to gdbarch.
  2016-01-26 14:58   ` Andreas Arnez
@ 2016-02-07 13:59     ` Marcin Kościelnicki
  2016-02-16 18:28       ` Ulrich Weigand
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-07 13:59 UTC (permalink / raw)
  To: arnez; +Cc: gdb-patches, Marcin Kościelnicki

When we're looking at a tracefile trace frame where registers are not
available, and the tracepoint has only one location, we supply
the location's address as the PC register.  However, this only works
if PC is not a pseudo register.  Add a gdbarch hook that will handle
that for pseudo registers.

gdb/ChangeLog:

	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Add supply_pseudo_pc hook.
	* tracefile.c (tracefile_fetch_registers): When PC is a pseudo,
	ask gdbarch to handle guessed PC via the new hook.
---
I've changed the name of the hook to supply_pseudo_pc, added missing
comments, and fixed the indent issue.

I don't think generalizing that function to arbitrary pseudo registers
is a good idea - there's already a pseudo_register_write, which covers
writing them.  The only reason I'm not using it in tracepoint.c is
that there's no "current register state" to write over, I'm making
a new one from scratch.

Perhaps a better generalization would be to instead make a hook that's
supposed to provide a whole regcache based on the tracepoint location,
not just PC?  I can imagine a few uses for that:

- on machines like ARM where you have several instruction encodings,
  you could also supply whatever registers determine the encoding
  (arm vs thumb) based on the location.
- if you can determine from the debug information that the function
  keeps GOT pointer / literal pool pointer / whatever in some register
  at the tracepoint location, you can also guess the contents of these
  (although that's probably not all that useful, and can be a lie
  if something is horribly buggy).

 gdb/ChangeLog   |  8 ++++++++
 gdb/gdbarch.c   | 32 ++++++++++++++++++++++++++++++++
 gdb/gdbarch.h   | 11 +++++++++++
 gdb/gdbarch.sh  |  5 +++++
 gdb/tracefile.c | 40 +++++++++++++++++++++++++++-------------
 5 files changed, 83 insertions(+), 13 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a2b0d39..e0bfd21 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add supply_pseudo_pc hook.
+	* tracefile.c (tracefile_fetch_registers): When PC is a pseudo,
+	ask gdbarch to handle guessed PC via the new hook.
+
 2016-02-04  Yao Qi  <yao.qi@linaro.org>
 
 	* remote.c (remote_wait_as): Set rs->waiting_for_stop_reply to
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..b323d44 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -181,6 +181,7 @@ struct gdbarch
   int char_signed;
   gdbarch_read_pc_ftype *read_pc;
   gdbarch_write_pc_ftype *write_pc;
+  gdbarch_supply_pseudo_pc_ftype *supply_pseudo_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
   gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
@@ -523,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
     gdbarch->char_signed = 1;
   /* Skip verify of read_pc, has predicate.  */
   /* Skip verify of write_pc, has predicate.  */
+  /* Skip verify of supply_pseudo_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
   /* Skip verify of pseudo_register_read_value, has predicate.  */
@@ -1366,6 +1368,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: static_transform_name = <%s>\n",
                       host_address_to_string (gdbarch->static_transform_name));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_supply_pseudo_pc_p() = %d\n",
+                      gdbarch_supply_pseudo_pc_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: supply_pseudo_pc = <%s>\n",
+                      host_address_to_string (gdbarch->supply_pseudo_pc));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: syscalls_info = %s\n",
                       host_address_to_string (gdbarch->syscalls_info));
   fprintf_unfiltered (file,
@@ -1821,6 +1829,30 @@ set_gdbarch_write_pc (struct gdbarch *gdbarch,
   gdbarch->write_pc = write_pc;
 }
 
+int
+gdbarch_supply_pseudo_pc_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->supply_pseudo_pc != NULL;
+}
+
+void
+gdbarch_supply_pseudo_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->supply_pseudo_pc != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_supply_pseudo_pc called\n");
+  gdbarch->supply_pseudo_pc (regcache, val);
+}
+
+void
+set_gdbarch_supply_pseudo_pc (struct gdbarch *gdbarch,
+                              gdbarch_supply_pseudo_pc_ftype supply_pseudo_pc)
+{
+  gdbarch->supply_pseudo_pc = supply_pseudo_pc;
+}
+
 void
 gdbarch_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..bbb0ba3 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -239,6 +239,17 @@ typedef void (gdbarch_write_pc_ftype) (struct regcache *regcache, CORE_ADDR val)
 extern void gdbarch_write_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
 extern void set_gdbarch_write_pc (struct gdbarch *gdbarch, gdbarch_write_pc_ftype *write_pc);
 
+/* Supply given PC into an empty regcache.  Used for tracepoints where
+   no registers have been collected, but there's only one location,
+   allowing us to guess the PC value.  Only used on targets where PC
+   is a pseudo-register - otherwise PC is supplied directly. */
+
+extern int gdbarch_supply_pseudo_pc_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_supply_pseudo_pc_ftype) (struct regcache *regcache, CORE_ADDR val);
+extern void gdbarch_supply_pseudo_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
+extern void set_gdbarch_supply_pseudo_pc (struct gdbarch *gdbarch, gdbarch_supply_pseudo_pc_ftype *supply_pseudo_pc);
+
 /* Function for getting target's idea of a frame pointer.  FIXME: GDB's
    whole scheme for dealing with "frames" and "frame pointers" needs a
    serious shakedown. */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..346dc3a 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -417,6 +417,11 @@ v:int:char_signed:::1:-1:1
 #
 F:CORE_ADDR:read_pc:struct regcache *regcache:regcache
 F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
+# Supply given PC into an empty regcache.  Used for tracepoints where
+# no registers have been collected, but there's only one location,
+# allowing us to guess the PC value.  Only used on targets where PC
+# is a pseudo-register - otherwise PC is supplied directly.
+F:void:supply_pseudo_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 # Function for getting target's idea of a frame pointer.  FIXME: GDB's
 # whole scheme for dealing with "frames" and "frame pointers" needs a
 # serious shakedown.
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index fef4ed9..e3d7b0e 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -396,16 +396,18 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
      as the address of the tracepoint.  */
   pc_regno = gdbarch_pc_regnum (gdbarch);
 
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (pc_regno < 0)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* We try to guess PC if:
+
+     1) We want all registers, or
+     2) PC is a real register, and we want exactly it, or
+     3) PC is a pseudo register (we don't know which real register it
+	corresponds to, so let's try to play safe).  */
+
+  if (regno == -1 || regno == pc_regno ||
+      pc_regno >= gdbarch_num_regs (gdbarch))
     {
       struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
       gdb_byte *regs;
@@ -429,11 +431,23 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 	      return;
 	    }
 
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
+	  if (pc_regno >= gdbarch_num_regs (gdbarch))
+	    {
+	      /* PC is a pseudo, let gdbarch deal with that.  If it doesn't
+		 know how, just bail.  */
+	      if (gdbarch_supply_pseudo_pc_p (gdbarch))
+		gdbarch_supply_pseudo_pc (gdbarch, regcache,
+						     tp->base.loc->address);
+	    }
+	  else
+	    {
+	      /* PC is a real register.  */
+	      regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+	      store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+				      gdbarch_byte_order (gdbarch),
+				      tp->base.loc->address);
+	      regcache_raw_supply (regcache, pc_regno, regs);
+	    }
 	}
     }
 }
-- 
2.7.0

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

* [PATCH 2/8] gdb/s390: Fill supply_pseudo_pc hook.
  2016-01-29 18:57       ` Andreas Arnez
@ 2016-02-07 14:00         ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-07 14:00 UTC (permalink / raw)
  To: arnez; +Cc: gdb-patches, Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
---
Likewise, changed name and added comment.

 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e0bfd21..d24cccd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
+	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
+
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* gdbarch.c: Regenerate.
 	* gdbarch.h: Regenerate.
 	* gdbarch.sh: Add supply_pseudo_pc hook.
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index e827684..144365c 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -167,6 +167,28 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
     regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
 }
 
+/* The "supply_pseudo_pc" gdbarch method.  For s390, we have to supply
+   the PSWA register.  For 64-bit inferior, PC maps straight to PSWA.
+   For 31-bit, we additionally set the high bit to 1, since we have
+   to supply the whole register, and it's very unlikely the program
+   is in 24-bit addressing mode.  */
+
+static void
+s390_supply_pseudo_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
+  gdb_byte *reg = (gdb_byte *) alloca (sz);
+
+  /* 31-bit PSWA needs high bit set.  */
+  if (tdep->abi == ABI_LINUX_S390)
+    pc |= 0x80000000;
+
+  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pc);
+  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
+}
+
 
 /* DWARF Register Mapping.  */
 
@@ -7857,6 +7879,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					    s390_iterate_over_regset_sections);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
   set_gdbarch_write_pc (gdbarch, s390_write_pc);
+  set_gdbarch_supply_pseudo_pc (gdbarch, s390_supply_pseudo_pc);
   set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
   set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
-- 
2.7.0

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

* [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-01-24 12:12 ` [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks Marcin Kościelnicki
@ 2016-02-07 14:01   ` Marcin Kościelnicki
  2016-02-25 19:23     ` Marcin Kościelnicki
  2016-03-11  9:58     ` Andreas Arnez
  0 siblings, 2 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-07 14:01 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
	(s390_ax_pseudo_register_push_stack): New function.
	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
	ax_pseudo_register_push_stack hooks.
---
Added missing comments.

 gdb/ChangeLog         |  7 +++++
 gdb/s390-linux-tdep.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d24cccd..6260040 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
+	(s390_ax_pseudo_register_push_stack): New function.
+	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
+	ax_pseudo_register_push_stack hooks.
+
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
 	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
 
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 144365c..97bd564 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
+/* The "ax_pseudo_register_collect" gdbarch method.  */
+
+static int
+s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+				 struct agent_expr *ax, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (regnum == tdep->pc_regnum)
+    {
+      ax_reg_mask (ax, S390_PSWA_REGNUM);
+    }
+  else if (regnum == tdep->cc_regnum)
+    {
+      ax_reg_mask (ax, S390_PSWM_REGNUM);
+    }
+  else if (regnum_is_gpr_full (tdep, regnum))
+    {
+      regnum -= tdep->gpr_full_regnum;
+      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
+      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
+    }
+  else if (regnum_is_vxr_full (tdep, regnum))
+    {
+      regnum -= tdep->v0_full_regnum;
+      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
+      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
+  return 0;
+}
+
+/* The "ax_pseudo_register_push_stack" gdbarch method.  */
+
+static int
+s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+				    struct agent_expr *ax, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (regnum == tdep->pc_regnum)
+    {
+      ax_reg (ax, S390_PSWA_REGNUM);
+      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+	{
+	  ax_zero_ext (ax, 31);
+	}
+    }
+  else if (regnum == tdep->cc_regnum)
+    {
+      ax_reg (ax, S390_PSWM_REGNUM);
+      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+	ax_const_l (ax, 12);
+      else
+	ax_const_l (ax, 44);
+      ax_simple (ax, aop_rsh_unsigned);
+      ax_zero_ext (ax, 2);
+    }
+  else if (regnum_is_gpr_full (tdep, regnum))
+    {
+      regnum -= tdep->gpr_full_regnum;
+      ax_reg (ax, S390_R0_REGNUM + regnum);
+      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
+      ax_const_l (ax, 32);
+      ax_simple (ax, aop_lsh);
+      ax_simple (ax, aop_bit_or);
+    }
+  else if (regnum_is_vxr_full (tdep, regnum))
+    {
+      /* Too large to stuff on the stack.  */
+      return 1;
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
+  return 0;
+}
+
 
 /* A helper for s390_software_single_step, decides if an instruction
    is a partial-execution instruction that needs to be executed until
@@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
   set_tdesc_pseudo_register_reggroup_p (gdbarch,
 					s390_pseudo_register_reggroup_p);
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+					  s390_ax_pseudo_register_collect);
+  set_gdbarch_ax_pseudo_register_push_stack
+      (gdbarch, s390_ax_pseudo_register_push_stack);
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
   set_gdbarch_register_name (gdbarch, s390_register_name);
 
-- 
2.7.0

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

* [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-01-24 12:12 ` [PATCH 4/8] gdb/s390: Fill gen_return_address hook Marcin Kościelnicki
@ 2016-02-07 14:02   ` Marcin Kościelnicki
  2016-02-25 19:23     ` Marcin Kościelnicki
  2016-03-11 11:20     ` Andreas Arnez
  0 siblings, 2 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-07 14:02 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_gen_return_address): New function.
	(s390_gdbarch_init): Fill gen_return_address hook.
---
Added missing comment.

 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 13 +++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6260040..0cf8bfc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_gen_return_address): New function.
+	(s390_gdbarch_init): Fill gen_return_address hook.
+
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
 	(s390_ax_pseudo_register_push_stack): New function.
 	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 97bd564..0b91ed1 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -627,6 +627,18 @@ s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
   return 0;
 }
 
+/* The "gen_return_address" gdbarch method.  */
+
+static void
+s390_gen_return_address (struct gdbarch *gdbarch,
+			 struct agent_expr *ax, struct axs_value *value,
+			 CORE_ADDR scope)
+{
+  value->type = register_type (gdbarch, S390_R14_REGNUM);
+  value->kind = axs_lvalue_register;
+  value->u.reg = S390_R14_REGNUM;
+}
+
 
 /* A helper for s390_software_single_step, decides if an instruction
    is a partial-execution instruction that needs to be executed until
@@ -7970,6 +7982,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					  s390_ax_pseudo_register_collect);
   set_gdbarch_ax_pseudo_register_push_stack
       (gdbarch, s390_ax_pseudo_register_push_stack);
+  set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
   set_gdbarch_register_name (gdbarch, s390_register_name);
 
-- 
2.7.0

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

* [PATCH 5/8] gdbserver/s390: Switch on tracepoint support.
  2016-01-24 12:12 ` [PATCH 5/8] gdbserver/s390: Switch on tracepoint support Marcin Kościelnicki
@ 2016-02-07 14:04   ` Marcin Kościelnicki
  2016-02-22  7:38     ` [PATCH] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-07 14:04 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Also adds s390 support to gdb.trace testsuite.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (s390_supports_tracepoints): New function.
	(struct linux_target_ops): Fill supports_tracepoints hook.

gdb/testsuite/ChangeLog:

	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
	placeholder.
	* lib/trace-support.exp: Add s390 registers.
---
Added missing comment.  I'll update patches 6-8 later, for now I'd like to
concentrate on getting regular tracepoints pushed.

 gdb/gdbserver/ChangeLog                              |  5 +++++
 gdb/gdbserver/linux-s390-low.c                       | 10 +++++++++-
 gdb/testsuite/ChangeLog                              | 13 ++++++++-----
 gdb/testsuite/gdb.trace/ftrace.exp                   |  2 ++
 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 14 +++++++++++---
 gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
 gdb/testsuite/lib/trace-support.exp                  |  4 ++++
 7 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 254341c..7ce325a 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* linux-s390-low.c (s390_supports_tracepoints): New function.
+	(struct linux_target_ops): Fill supports_tracepoints hook.
+
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* linux-s390-low.c (s390_supports_z_point_type): New function.
 	(struct linux_target_ops): Wire s390_supports_z_point_type in.
 
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 533e384..c85c331 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -690,6 +690,14 @@ s390_regs_info (void)
   return &regs_info;
 }
 
+/* The "supports_tracepoints" linux_target_ops method.  */
+
+static int
+s390_supports_tracepoints (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -716,7 +724,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
+  s390_supports_tracepoints,
   NULL, /* get_thread_area */
   NULL, /* install_fast_tracepoint_jump_pad */
   NULL, /* emit_ops */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 046f112..9ce9205 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.trace/ftrace.exp: Select $r2 as test register for s390.
+	* gdb.trace/mi-trace-frame-collected.exp: Expect 2 registers on s390.
+	* gdb.trace/trace-common.h (x86_trace_dummy): Add s390 fast tracepoint
+	placeholder.
+	* lib/trace-support.exp: Add s390 registers.
+
 2016-02-04  Yao Qi  <yao.qi@linaro.org>
 
 	* gdb.base/foll-exec-mode.c: Include limits.h.
@@ -84,11 +92,6 @@
 	(foreach_with_prefix): Likewise.
 	* lib/gdb.exp (foreach_with_prefix): New procedure.
 
-2016-01-25  Marcin Kościelnicki  <koriakin@0x04.net>
-
-	* gdb.trace/backtrace.exp: Bump stack collection fudge factor.
-	* gdb.trace/entry-values.exp: Bump stack collection fudge factor.
-
 2016-01-23  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* gdb.trace/unavailable-dwarf-piece.exp: Fix bitfield handling on big
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index 15ad7e7..cca3a9c 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -246,6 +246,8 @@ if [is_amd64_regs_target] {
     set arg0exp "*(int *) (\$ebp + 8)"
 } elseif { [istarget "aarch64*-*-*"] } {
     set arg0exp "\$x0"
+} elseif { [istarget "s390*-*-*"] } {
+    set arg0exp "\$r2"
 } else {
     set arg0exp ""
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 0daaa25..499d3fb 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -93,9 +93,17 @@ proc test_trace_frame_collected { data_source } {
 
 	# Test MI command '-trace-frame-collected' dumps only
 	# collected registers.
-	mi_gdb_test "-trace-frame-collected" \
-	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
-	    "-trace-frame-collected (register)"
+	if { [istarget "s390*-*-*"] } {
+	    # Only PC is collected, but on s390 PC is a pseudo-register -
+	    # collecting it also collects the underlying PSWA register.
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\},\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	} else {
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	}
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index eceb182..a330024 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -48,6 +48,14 @@ x86_trace_dummy ()
        "    nop\n" \
        )
 
+#elif (defined __s390__)
+
+#define FAST_TRACEPOINT_LABEL(name) \
+  asm ("    .global " SYMBOL(name) "\n" \
+       SYMBOL(name) ":\n" \
+       "    mvc 0(8, %r15), 0(%r15)\n" \
+       )
+
 #else
 
 #error "unsupported architecture for trace tests"
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
index f593c43..70f7b7f 100644
--- a/gdb/testsuite/lib/trace-support.exp
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -36,6 +36,10 @@ if [is_amd64_regs_target] {
     set fpreg "x29"
     set spreg "sp"
     set pcreg "pc"
+} elseif [istarget "s390*-*-*"] {
+    set fpreg "r11"
+    set spreg "r15"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
-- 
2.7.0

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

* Re: [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support.
  2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
                   ` (9 preceding siblings ...)
  2016-01-25 13:56 ` Pedro Alves
@ 2016-02-12 11:04 ` Marcin Kościelnicki
  10 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-12 11:04 UTC (permalink / raw)
  To: gdb-patches

A few updates on the status...

On 24/01/16 13:12, Marcin Kościelnicki wrote:
> This patchset adds support for regular and fast tracepoints on
> s390-ibm-linux-gnu and s390x-ibm-linux-gnu.  It depends on the following
> yet-unlanded patches:
>
> - https://sourceware.org/ml/gdb-patches/2016-01/msg00597.html (for 31-bit
>    fast tracepoint support)
> - https://sourceware.org/ml/gdb-patches/2016-01/msg00596.html (just
>    a testsuite fix)

These two have landed by now.

> - https://sourceware.org/ml/gdb-patches/2016-01/msg00510.html (fixes
>    setting a breakpoint and a tracepoint on the same location)

Still waiting for review.
>
> Patches 1-5 add working regular tracepoint support, patches 6-7 add
> working fast tracepoint support on top of that, and patch 8 makes fast
> tracepoints use compiled agent expressions.

I have updated the first 5 patches and hope to get them pushed first; 
there are outstanding issues on #6 and #8 (doc comments, indents, 
reading auxv from /proc) which I will fix soon (when I'm done with issue 
(3) below).
>
> Patches 1 and 7 are in target-independent code, the remaining ones
> are in s390-specific code.
>
> It has been tested on s390-ibm-linux-gnu and s390x-ibm-linux-gnu on
> a z13 machine (without vector extensions).  The parts handling vector
> extensions are untested.  It has also been regression-tested on x86_64.
>
> There are 2 test failures still left in gdb.trace:
>
> - gdb.trace/unavailable.exp: print derived_whole has 4 failures on 64-bit
>    only.  The same failure happens on x86_64, so it's unlikely to be
>    s390-specific.
> - gdb.trace/mi-tsv-changed.exp: create delete modify: tvariable $tvar3
>    modified is an intermittent failure.  It seems to be a race of some
>    kind - in the failing runs, gdb shows the same messages, but in
>    different order.  I strongly suspect this is a target-independent
>    issues that only happens on s390 due to timing factors.
>
> There are also three issues affecting s390 tracepoints that don't show
> up in the testsuite:
>
> 1. Target independent: tfile format doesn't contain target information
>     (tdesc).  While this affects all platforms with multiple tdescs
>     (eg. x86_64 is unable to pull AVX registers from tfile for that
>     reason), it horribly breaks 31-bit s390 with high GPRs - it has
>     a completely different GPR layout from plain 31-bit s390, so the
>     collected registers will be garbled.  I suppose the proper fix to
>     that would be to add tdesc information to tfile format.  Unfortunately,
>     I don't see a way to extend it in a backwards-compatible way.

This is fixed already.

> 2. Target independent: 32-bit (or 31-bit for us) IPA cannot be used with
>     64-bit gdbserver, due to communication involving lots of structs with
>     pointer types.  Fixing that would be quite involved, but possible
>     (I don't suppose we have to maintain compatibility between IPA/gdbserver
>     from different gdb versions?).
>
> 3. s390 specific: 31-bit gdbserver doesn't know about high GPRs, and
>     cannot collect them if they're in use.  Seems fixable with average
>     effort.  Unfortunately, fixing that will break tfile, unless (1)
>     is fixed first...

Since (1) is fixed, I'm going to work on that one now.

> These three interact in bad ways, summarised below:
>
> - 64-bit linux, 64-bit gdbserver, 64-bit target: works OK, but you won't be
>    able to see VX registers in tfile.

Works OK now, including VX in tfile.
>
> - 64-bit linux, 64-bit gdbserver, 31-bit target:
>
>    - no fast tracepoint support due to (2)
>    - tfile completely broken due to (1)

tfile should work now.
>
> - 64-bit linux, 31-bit gdbserver, 31-bit target:
>
>    - works OK, but you won't be able to see VX registers or high GPRs at all,
>      due to (3)
>    - if (3) were fixed, tfile will be completely broken due to (1)

Second line no longer applies.
>
> - 31-bit linux, 31-bit gdbserver, 31-bit target: works OK
>
> In summary, there's no way at all to use fast tracepoints on 31-bit target
> if what you want to collect involves high GPRs.  While there's support for
> it in the IPA, it's currently disabled, to match what gdbserver supports.
>
> Fast tracepoint support assumes z900+ CPU.  The g5/g6 CPUs only have jump
> instuctions with +-64kiB of range, making them pretty much useless for
> our purposes, so not much loss here.
>

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

* Re: [PATCH] gdb.trace: Bump tspeed.exp timeout to 600 seconds.
  2016-01-29  9:53     ` [PATCH] " Marcin Kościelnicki
@ 2016-02-12 11:20       ` Yao Qi
  2016-02-18 18:54       ` Marcin Kościelnicki
  1 sibling, 0 replies; 89+ messages in thread
From: Yao Qi @ 2016-02-12 11:20 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: arnez, gdb-patches

Marcin Kościelnicki <koriakin@0x04.net> writes:

>  # Typically we need a little extra time for this test.
> -set timeout 180
> +set timeout 600

Alternatively, you can wrap the slow test with with_timeout_factor.

-- 
Yao (齐尧)

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

* Re: [PATCH 1/8] gdb: Add supply_pseudo_pc hook to gdbarch.
  2016-02-07 13:59     ` [PATCH 1/8] gdb: Add supply_pseudo_pc " Marcin Kościelnicki
@ 2016-02-16 18:28       ` Ulrich Weigand
  2016-02-16 21:32         ` Marcin Kościelnicki
  2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
  0 siblings, 2 replies; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-16 18:28 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: arnez, gdb-patches, Marcin Kościelnicki

Marcin Kościelnicki wrote:

> I don't think generalizing that function to arbitrary pseudo registers
> is a good idea - there's already a pseudo_register_write, which covers
> writing them.  The only reason I'm not using it in tracepoint.c is
> that there's no "current register state" to write over, I'm making
> a new one from scratch.

Well, strictly speaking there is already a "current register state"
since tracefile_fetch_registers just initialized all registers to
the "unavailable" state.  At this point they could be fetched (and
would read all zeros).

So in principle you could just use regcache_write_pc at this point.
The reason this doesn't work is a different one: that routine would
attempt to *update target state*, i.e. it would call to the target's
to_store_registers method.  However, the tracefile target only
provides a to_fetch_registers method, and no to_store_registers,
and the default target to_store_registers method just errors out.

You *could* add a to_store_registers tracefile target method that
would simply ignore writes (in effect, making the tracefile regcache
modifyable without any underlying "real" target); then you could
just use regcache_write_pc.

However, this would not address the fact that there are potentially
target-specific settings beyond a pure PC value that must be
present in order to make a "synthetic" regcache at least minimally
consistent.  This includes e.g. the address mode bit on 31-bit.
Note that a default value of 0 isn't really valid for the PSWM
register either, even though probably nobody checks.  But there
are a number of bits that have to be set to make it a valid
user-space PSW (e.g. interrupts and address translation must be
enabled etc.).  If you'd ever try to load the PSW back to the
hardware via ptrace, a 0 PSWM would get rejected.

> Perhaps a better generalization would be to instead make a hook that's
> supposed to provide a whole regcache based on the tracepoint location,
> not just PC?  I can imagine a few uses for that:
> 
> - on machines like ARM where you have several instruction encodings,
>   you could also supply whatever registers determine the encoding
>   (arm vs thumb) based on the location.
> - if you can determine from the debug information that the function
>   keeps GOT pointer / literal pool pointer / whatever in some register
>   at the tracepoint location, you can also guess the contents of these
>   (although that's probably not all that useful, and can be a lie
>   if something is horribly buggy).

Given the above, I therefore agree that this is really probably
the preferable level of abstraction here.  You want a gdbarch hook
to synthesize a minimally-valid regcache given only information
statically known about the tracepoint.  Whether this hook gets
just the PC or a full tracepoint structure is probably not so
important right now; this could still be modified if necessary.

I'd also suggest that this hook doesn't get a predicate, but a
default implementation, which does the current handling of just
setting a real PC register.  If overridden by a gdbarch, the
platform can do anything that's necessary there instead.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 1/8] gdb: Add supply_pseudo_pc hook to gdbarch.
  2016-02-16 18:28       ` Ulrich Weigand
@ 2016-02-16 21:32         ` Marcin Kościelnicki
  2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
  1 sibling, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-16 21:32 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: arnez, gdb-patches

On 16/02/16 19:27, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>
>> I don't think generalizing that function to arbitrary pseudo registers
>> is a good idea - there's already a pseudo_register_write, which covers
>> writing them.  The only reason I'm not using it in tracepoint.c is
>> that there's no "current register state" to write over, I'm making
>> a new one from scratch.
>
> Well, strictly speaking there is already a "current register state"
> since tracefile_fetch_registers just initialized all registers to
> the "unavailable" state.  At this point they could be fetched (and
> would read all zeros).
>
> So in principle you could just use regcache_write_pc at this point.
> The reason this doesn't work is a different one: that routine would
> attempt to *update target state*, i.e. it would call to the target's
> to_store_registers method.  However, the tracefile target only
> provides a to_fetch_registers method, and no to_store_registers,
> and the default target to_store_registers method just errors out.
>
> You *could* add a to_store_registers tracefile target method that
> would simply ignore writes (in effect, making the tracefile regcache
> modifyable without any underlying "real" target); then you could
> just use regcache_write_pc.
>
> However, this would not address the fact that there are potentially
> target-specific settings beyond a pure PC value that must be
> present in order to make a "synthetic" regcache at least minimally
> consistent.  This includes e.g. the address mode bit on 31-bit.
> Note that a default value of 0 isn't really valid for the PSWM
> register either, even though probably nobody checks.  But there
> are a number of bits that have to be set to make it a valid
> user-space PSW (e.g. interrupts and address translation must be
> enabled etc.).  If you'd ever try to load the PSW back to the
> hardware via ptrace, a 0 PSWM would get rejected.
>
>> Perhaps a better generalization would be to instead make a hook that's
>> supposed to provide a whole regcache based on the tracepoint location,
>> not just PC?  I can imagine a few uses for that:
>>
>> - on machines like ARM where you have several instruction encodings,
>>    you could also supply whatever registers determine the encoding
>>    (arm vs thumb) based on the location.
>> - if you can determine from the debug information that the function
>>    keeps GOT pointer / literal pool pointer / whatever in some register
>>    at the tracepoint location, you can also guess the contents of these
>>    (although that's probably not all that useful, and can be a lie
>>    if something is horribly buggy).
>
> Given the above, I therefore agree that this is really probably
> the preferable level of abstraction here.  You want a gdbarch hook
> to synthesize a minimally-valid regcache given only information
> statically known about the tracepoint.  Whether this hook gets
> just the PC or a full tracepoint structure is probably not so
> important right now; this could still be modified if necessary.
>
> I'd also suggest that this hook doesn't get a predicate, but a
> default implementation, which does the current handling of just
> setting a real PC register.  If overridden by a gdbarch, the
> platform can do anything that's necessary there instead.
>
> Bye,
> Ulrich
>

Sounds good, I'll do that.

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

* [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-16 18:28       ` Ulrich Weigand
  2016-02-16 21:32         ` Marcin Kościelnicki
@ 2016-02-18 10:35         ` Marcin Kościelnicki
  2016-02-18 10:35           ` [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook Marcin Kościelnicki
  2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
  1 sibling, 2 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 10:35 UTC (permalink / raw)
  To: uweigand; +Cc: arnez, gdb-patches, Marcin Kościelnicki

When we're looking at a tracefile trace frame where registers are not
available, and the tracepoint has only one location, we supply
the location's address as the PC register.  However, this only works
if PC is not a pseudo register, and individual architectures may want
to guess more registers.  Add a gdbarch hook that will handle that.

gdb/ChangeLog:

	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Add guess_tracepoint_registers hook, struct tracepoint
	declaration, and tracepoint.h include.
	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
	* tracepoint.c (default_guess_tracepoint_registers): New function.
	* tracepoint.h (default_guess_tracepoint_registers): New prototype.
---
Here comes the updated patches.

 gdb/ChangeLog    | 10 ++++++++++
 gdb/gdbarch.c    | 24 +++++++++++++++++++++++
 gdb/gdbarch.h    | 10 ++++++++++
 gdb/gdbarch.sh   |  8 ++++++++
 gdb/tracefile.c  | 60 ++++++++++++++++++++------------------------------------
 gdb/tracepoint.c | 23 ++++++++++++++++++++++
 gdb/tracepoint.h |  4 ++++
 7 files changed, 100 insertions(+), 39 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e507dd1..95afe29 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add guess_tracepoint_registers hook, struct tracepoint
+	declaration, and tracepoint.h include.
+	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
+	* tracepoint.c (default_guess_tracepoint_registers): New function.
+	* tracepoint.h (default_guess_tracepoint_registers): New prototype.
+
 2016-02-17  Gary Benson  <gbenson@redhat.com>
 
 	* exec.c (exec_file_locate_attach): Add missing cleanup.
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..532b259 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -47,6 +47,7 @@
 #include "observer.h"
 #include "regcache.h"
 #include "objfiles.h"
+#include "tracepoint.h"
 
 /* Static function declarations */
 
@@ -312,6 +313,7 @@ struct gdbarch
   int has_global_breakpoints;
   gdbarch_has_shared_address_space_ftype *has_shared_address_space;
   gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at;
+  gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers;
   gdbarch_auto_charset_ftype *auto_charset;
   gdbarch_auto_wide_charset_ftype *auto_wide_charset;
   const char * solib_symbols_extension;
@@ -419,6 +421,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->relocate_instruction = NULL;
   gdbarch->has_shared_address_space = default_has_shared_address_space;
   gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at;
+  gdbarch->guess_tracepoint_registers = default_guess_tracepoint_registers;
   gdbarch->auto_charset = default_auto_charset;
   gdbarch->auto_wide_charset = default_auto_wide_charset;
   gdbarch->gen_return_address = default_gen_return_address;
@@ -658,6 +661,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of has_global_breakpoints, invalid_p == 0 */
   /* Skip verify of has_shared_address_space, invalid_p == 0 */
   /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */
+  /* Skip verify of guess_tracepoint_registers, invalid_p == 0 */
   /* Skip verify of auto_charset, invalid_p == 0 */
   /* Skip verify of auto_wide_charset, invalid_p == 0 */
   /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
@@ -1024,6 +1028,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: gnu_triplet_regexp = <%s>\n",
                       host_address_to_string (gdbarch->gnu_triplet_regexp));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: guess_tracepoint_registers = <%s>\n",
+                      host_address_to_string (gdbarch->guess_tracepoint_registers));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: half_bit = %s\n",
                       plongest (gdbarch->half_bit));
   fprintf_unfiltered (file,
@@ -4450,6 +4457,23 @@ set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
   gdbarch->fast_tracepoint_valid_at = fast_tracepoint_valid_at;
 }
 
+void
+gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->guess_tracepoint_registers != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_guess_tracepoint_registers called\n");
+  gdbarch->guess_tracepoint_registers (gdbarch, regcache, addr);
+}
+
+void
+set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch,
+                                        gdbarch_guess_tracepoint_registers_ftype guess_tracepoint_registers)
+{
+  gdbarch->guess_tracepoint_registers = guess_tracepoint_registers;
+}
+
 const char *
 gdbarch_auto_charset (struct gdbarch *gdbarch)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..be0e7e3 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -64,6 +64,7 @@ struct elf_internal_linux_prpsinfo;
 struct mem_range;
 struct syscalls_info;
 struct thread_info;
+struct tracepoint;
 
 #include "regcache.h"
 
@@ -1327,6 +1328,15 @@ typedef int (gdbarch_fast_tracepoint_valid_at_ftype) (struct gdbarch *gdbarch, C
 extern int gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, char **msg);
 extern void set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at);
 
+/* Guess register state based on tracepoint location.  Used for tracepoints
+   where no registers have been collected, but there's only one location,
+   allowing us to guess the PC value, and perhaps some other registers.
+   On entry, regcache has all registers marked as unavailable. */
+
+typedef void (gdbarch_guess_tracepoint_registers_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers);
+
 /* Return the "auto" target charset. */
 
 typedef const char * (gdbarch_auto_charset_ftype) (void);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..f3d8aa5 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1028,6 +1028,12 @@ m:int:has_shared_address_space:void:::default_has_shared_address_space::0
 # True if a fast tracepoint can be set at an address.
 m:int:fast_tracepoint_valid_at:CORE_ADDR addr, char **msg:addr, msg::default_fast_tracepoint_valid_at::0
 
+# Guess register state based on tracepoint location.  Used for tracepoints
+# where no registers have been collected, but there's only one location,
+# allowing us to guess the PC value, and perhaps some other registers.
+# On entry, regcache has all registers marked as unavailable.
+m:void:guess_tracepoint_registers:struct regcache *regcache, CORE_ADDR addr:regcache, addr::default_guess_tracepoint_registers::0
+
 # Return the "auto" target charset.
 f:const char *:auto_charset:void::default_auto_charset:default_auto_charset::0
 # Return the "auto" target wide charset.
@@ -1251,6 +1257,7 @@ struct elf_internal_linux_prpsinfo;
 struct mem_range;
 struct syscalls_info;
 struct thread_info;
+struct tracepoint;
 
 #include "regcache.h"
 
@@ -1599,6 +1606,7 @@ cat <<EOF
 #include "observer.h"
 #include "regcache.h"
 #include "objfiles.h"
+#include "tracepoint.h"
 
 /* Static function declarations */
 
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index de42165..609b7e5 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -388,7 +388,8 @@ void
 tracefile_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int regn, pc_regno;
+  struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
+  int regn;
 
   /* We get here if no register data has been found.  Mark registers
      as unavailable.  */
@@ -397,48 +398,29 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 
   /* We can often usefully guess that the PC is going to be the same
      as the address of the tracepoint.  */
-  pc_regno = gdbarch_pc_regnum (gdbarch);
-
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (tp == NULL || tp->base.loc == NULL)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* But don't try to guess if tracepoint is multi-location...  */
+  if (tp->base.loc->next)
     {
-      struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-      gdb_byte *regs;
-
-      if (tp && tp->base.loc)
-	{
-	  /* But don't try to guess if tracepoint is multi-location...  */
-	  if (tp->base.loc->next)
-	    {
-	      warning (_("Tracepoint %d has multiple "
-			 "locations, cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-	  /* ... or does while-stepping.  */
-	  if (tp->step_count > 0)
-	    {
-	      warning (_("Tracepoint %d does while-stepping, "
-			 "cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
-	}
+      warning (_("Tracepoint %d has multiple "
+		 "locations, cannot infer $pc"),
+	       tp->base.number);
+      return;
+    }
+  /* ... or does while-stepping.  */
+  else if (tp->step_count > 0)
+    {
+      warning (_("Tracepoint %d does while-stepping, "
+		 "cannot infer $pc"),
+	       tp->base.number);
+      return;
     }
+
+  /* Guess what we can from the tracepoint location.  */
+  gdbarch_guess_tracepoint_registers (gdbarch, regcache,
+				      tp->base.loc->address);
 }
 
 /* This is the implementation of target_ops method to_has_all_memory.  */
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 8b393db..198fc65 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -4341,6 +4341,29 @@ traceframe_available_memory (VEC(mem_range_s) **result,
   return 0;
 }
 
+void
+default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+				    struct regcache *regcache,
+				    CORE_ADDR addr)
+{
+  int pc_regno = gdbarch_pc_regnum (gdbarch);
+  gdb_byte *regs;
+
+  /* This guessing code below only works if the PC register isn't
+     a pseudo-register.  The value of a pseudo-register isn't stored
+     in the (non-readonly) regcache -- instead it's recomputed
+     (probably from some other cached raw register) whenever the
+     register is read.  In this case, a custom method implementation
+     should be used by the architecture.  */
+  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+    return;
+
+  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+			  gdbarch_byte_order (gdbarch), addr);
+  regcache_raw_supply (regcache, pc_regno, regs);
+}
+
 /* Implementation of `sdata' variable.  */
 
 static const struct internalvar_funcs sdata_funcs =
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 8985394..2cff32a 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -353,4 +353,8 @@ extern struct traceframe_info *get_traceframe_info (void);
 
 extern struct bp_location *get_traceframe_location (int *stepping_frame_p);
 
+extern void default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+						struct regcache *regcache,
+						CORE_ADDR addr);
+
 #endif	/* TRACEPOINT_H */
-- 
2.7.0

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

* [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook.
  2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
@ 2016-02-18 10:35           ` Marcin Kościelnicki
  2016-02-18 16:03             ` Ulrich Weigand
  2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 10:35 UTC (permalink / raw)
  To: uweigand; +Cc: arnez, gdb-patches, Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_guess_tracepoint_registers): New function.
	(s390_gdbarch_init): Fill guess_tracepoint_registers hook.
---
 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 24 ++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 95afe29..2823f70 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_guess_tracepoint_registers): New function.
+	(s390_gdbarch_init): Fill guess_tracepoint_registers hook.
+
+2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* gdbarch.c: Regenerate.
 	* gdbarch.h: Regenerate.
 	* gdbarch.sh: Add guess_tracepoint_registers hook, struct tracepoint
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index e827684..82902e4 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -167,6 +167,29 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
     regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
 }
 
+/* The "guess_tracepoint_registers" gdbarch method.  For s390, we have
+   to supply the PSWA register.  For 64-bit inferior, PC maps straight
+   to PSWA.  For 31-bit, we additionally set the high bit to 1, since we
+   have to supply the whole register, and it's very unlikely the program
+   is in 24-bit addressing mode.  */
+
+static void
+s390_guess_tracepoint_registers (struct gdbarch *gdbarch,
+				 struct regcache *regcache,
+				 CORE_ADDR addr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
+  gdb_byte *reg = (gdb_byte *) alloca (sz);
+
+  /* 31-bit PSWA needs high bit set.  */
+  if (tdep->abi == ABI_LINUX_S390)
+    addr |= 0x80000000;
+
+  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), addr);
+  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
+}
+
 
 /* DWARF Register Mapping.  */
 
@@ -7857,6 +7880,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					    s390_iterate_over_regset_sections);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
   set_gdbarch_write_pc (gdbarch, s390_write_pc);
+  set_gdbarch_guess_tracepoint_registers (gdbarch, s390_guess_tracepoint_registers);
   set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
   set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
-- 
2.7.0

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

* Re: [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
  2016-02-18 10:35           ` [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook Marcin Kościelnicki
@ 2016-02-18 11:38           ` Luis Machado
  2016-02-18 11:39             ` Marcin Kościelnicki
  2016-02-18 11:45             ` [PATCH] " Marcin Kościelnicki
  1 sibling, 2 replies; 89+ messages in thread
From: Luis Machado @ 2016-02-18 11:38 UTC (permalink / raw)
  To: Marcin Kościelnicki, uweigand; +Cc: arnez, gdb-patches

On 02/18/2016 08:35 AM, Marcin Kościelnicki wrote:
> When we're looking at a tracefile trace frame where registers are not
> available, and the tracepoint has only one location, we supply
> the location's address as the PC register.  However, this only works
> if PC is not a pseudo register, and individual architectures may want
> to guess more registers.  Add a gdbarch hook that will handle that.
>
> gdb/ChangeLog:
>
> 	* gdbarch.c: Regenerate.
> 	* gdbarch.h: Regenerate.
> 	* gdbarch.sh: Add guess_tracepoint_registers hook, struct tracepoint
> 	declaration, and tracepoint.h include.
> 	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
> 	* tracepoint.c (default_guess_tracepoint_registers): New function.
> 	* tracepoint.h (default_guess_tracepoint_registers): New prototype.

> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
> index 3fadcd1..be0e7e3 100644
> --- a/gdb/gdbarch.h
> +++ b/gdb/gdbarch.h
> @@ -64,6 +64,7 @@ struct elf_internal_linux_prpsinfo;
>   struct mem_range;
>   struct syscalls_info;
>   struct thread_info;
> +struct tracepoint;
>

Is this declaration needed here? struct tracepoint doesn't seem to be 
used anywhere in gdbarch.[c|h].

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

* Re: [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
@ 2016-02-18 11:39             ` Marcin Kościelnicki
  2016-02-18 11:45             ` [PATCH] " Marcin Kościelnicki
  1 sibling, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 11:39 UTC (permalink / raw)
  To: Luis Machado, uweigand; +Cc: arnez, gdb-patches

On 18/02/16 12:37, Luis Machado wrote:
> On 02/18/2016 08:35 AM, Marcin Kościelnicki wrote:
>> When we're looking at a tracefile trace frame where registers are not
>> available, and the tracepoint has only one location, we supply
>> the location's address as the PC register.  However, this only works
>> if PC is not a pseudo register, and individual architectures may want
>> to guess more registers.  Add a gdbarch hook that will handle that.
>>
>> gdb/ChangeLog:
>>
>>     * gdbarch.c: Regenerate.
>>     * gdbarch.h: Regenerate.
>>     * gdbarch.sh: Add guess_tracepoint_registers hook, struct tracepoint
>>     declaration, and tracepoint.h include.
>>     * tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
>>     * tracepoint.c (default_guess_tracepoint_registers): New function.
>>     * tracepoint.h (default_guess_tracepoint_registers): New prototype.
>
>> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
>> index 3fadcd1..be0e7e3 100644
>> --- a/gdb/gdbarch.h
>> +++ b/gdb/gdbarch.h
>> @@ -64,6 +64,7 @@ struct elf_internal_linux_prpsinfo;
>>   struct mem_range;
>>   struct syscalls_info;
>>   struct thread_info;
>> +struct tracepoint;
>>
>
> Is this declaration needed here? struct tracepoint doesn't seem to be
> used anywhere in gdbarch.[c|h].
>

Whoops, that's s leftover from a version that passed a struct 
tracepoint, I'll fix that.

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

* [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
  2016-02-18 11:39             ` Marcin Kościelnicki
@ 2016-02-18 11:45             ` Marcin Kościelnicki
  2016-02-18 15:40               ` Ulrich Weigand
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 11:45 UTC (permalink / raw)
  To: lgustavo; +Cc: uweigand, arnez, gdb-patches, Marcin Kościelnicki

When we're looking at a tracefile trace frame where registers are not
available, and the tracepoint has only one location, we supply
the location's address as the PC register.  However, this only works
if PC is not a pseudo register, and individual architectures may want
to guess more registers.  Add a gdbarch hook that will handle that.

gdb/ChangeLog:

	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Add guess_tracepoint_registers hook, include
	tracepoint.h.
	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
	* tracepoint.c (default_guess_tracepoint_registers): New function.
	* tracepoint.h (default_guess_tracepoint_registers): New prototype.
---
 gdb/ChangeLog    | 10 ++++++++++
 gdb/gdbarch.c    | 24 +++++++++++++++++++++++
 gdb/gdbarch.h    |  9 +++++++++
 gdb/gdbarch.sh   |  7 +++++++
 gdb/tracefile.c  | 60 ++++++++++++++++++++------------------------------------
 gdb/tracepoint.c | 23 ++++++++++++++++++++++
 gdb/tracepoint.h |  4 ++++
 7 files changed, 98 insertions(+), 39 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e507dd1..74b0f05 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add guess_tracepoint_registers hook, include
+	tracepoint.h.
+	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
+	* tracepoint.c (default_guess_tracepoint_registers): New function.
+	* tracepoint.h (default_guess_tracepoint_registers): New prototype.
+
 2016-02-17  Gary Benson  <gbenson@redhat.com>
 
 	* exec.c (exec_file_locate_attach): Add missing cleanup.
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..532b259 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -47,6 +47,7 @@
 #include "observer.h"
 #include "regcache.h"
 #include "objfiles.h"
+#include "tracepoint.h"
 
 /* Static function declarations */
 
@@ -312,6 +313,7 @@ struct gdbarch
   int has_global_breakpoints;
   gdbarch_has_shared_address_space_ftype *has_shared_address_space;
   gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at;
+  gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers;
   gdbarch_auto_charset_ftype *auto_charset;
   gdbarch_auto_wide_charset_ftype *auto_wide_charset;
   const char * solib_symbols_extension;
@@ -419,6 +421,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->relocate_instruction = NULL;
   gdbarch->has_shared_address_space = default_has_shared_address_space;
   gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at;
+  gdbarch->guess_tracepoint_registers = default_guess_tracepoint_registers;
   gdbarch->auto_charset = default_auto_charset;
   gdbarch->auto_wide_charset = default_auto_wide_charset;
   gdbarch->gen_return_address = default_gen_return_address;
@@ -658,6 +661,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of has_global_breakpoints, invalid_p == 0 */
   /* Skip verify of has_shared_address_space, invalid_p == 0 */
   /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */
+  /* Skip verify of guess_tracepoint_registers, invalid_p == 0 */
   /* Skip verify of auto_charset, invalid_p == 0 */
   /* Skip verify of auto_wide_charset, invalid_p == 0 */
   /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
@@ -1024,6 +1028,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: gnu_triplet_regexp = <%s>\n",
                       host_address_to_string (gdbarch->gnu_triplet_regexp));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: guess_tracepoint_registers = <%s>\n",
+                      host_address_to_string (gdbarch->guess_tracepoint_registers));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: half_bit = %s\n",
                       plongest (gdbarch->half_bit));
   fprintf_unfiltered (file,
@@ -4450,6 +4457,23 @@ set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
   gdbarch->fast_tracepoint_valid_at = fast_tracepoint_valid_at;
 }
 
+void
+gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->guess_tracepoint_registers != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_guess_tracepoint_registers called\n");
+  gdbarch->guess_tracepoint_registers (gdbarch, regcache, addr);
+}
+
+void
+set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch,
+                                        gdbarch_guess_tracepoint_registers_ftype guess_tracepoint_registers)
+{
+  gdbarch->guess_tracepoint_registers = guess_tracepoint_registers;
+}
+
 const char *
 gdbarch_auto_charset (struct gdbarch *gdbarch)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..7ffbf1f 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1327,6 +1327,15 @@ typedef int (gdbarch_fast_tracepoint_valid_at_ftype) (struct gdbarch *gdbarch, C
 extern int gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, char **msg);
 extern void set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at);
 
+/* Guess register state based on tracepoint location.  Used for tracepoints
+   where no registers have been collected, but there's only one location,
+   allowing us to guess the PC value, and perhaps some other registers.
+   On entry, regcache has all registers marked as unavailable. */
+
+typedef void (gdbarch_guess_tracepoint_registers_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers);
+
 /* Return the "auto" target charset. */
 
 typedef const char * (gdbarch_auto_charset_ftype) (void);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..18990db 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1028,6 +1028,12 @@ m:int:has_shared_address_space:void:::default_has_shared_address_space::0
 # True if a fast tracepoint can be set at an address.
 m:int:fast_tracepoint_valid_at:CORE_ADDR addr, char **msg:addr, msg::default_fast_tracepoint_valid_at::0
 
+# Guess register state based on tracepoint location.  Used for tracepoints
+# where no registers have been collected, but there's only one location,
+# allowing us to guess the PC value, and perhaps some other registers.
+# On entry, regcache has all registers marked as unavailable.
+m:void:guess_tracepoint_registers:struct regcache *regcache, CORE_ADDR addr:regcache, addr::default_guess_tracepoint_registers::0
+
 # Return the "auto" target charset.
 f:const char *:auto_charset:void::default_auto_charset:default_auto_charset::0
 # Return the "auto" target wide charset.
@@ -1599,6 +1605,7 @@ cat <<EOF
 #include "observer.h"
 #include "regcache.h"
 #include "objfiles.h"
+#include "tracepoint.h"
 
 /* Static function declarations */
 
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index de42165..609b7e5 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -388,7 +388,8 @@ void
 tracefile_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int regn, pc_regno;
+  struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
+  int regn;
 
   /* We get here if no register data has been found.  Mark registers
      as unavailable.  */
@@ -397,48 +398,29 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 
   /* We can often usefully guess that the PC is going to be the same
      as the address of the tracepoint.  */
-  pc_regno = gdbarch_pc_regnum (gdbarch);
-
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (tp == NULL || tp->base.loc == NULL)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* But don't try to guess if tracepoint is multi-location...  */
+  if (tp->base.loc->next)
     {
-      struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-      gdb_byte *regs;
-
-      if (tp && tp->base.loc)
-	{
-	  /* But don't try to guess if tracepoint is multi-location...  */
-	  if (tp->base.loc->next)
-	    {
-	      warning (_("Tracepoint %d has multiple "
-			 "locations, cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-	  /* ... or does while-stepping.  */
-	  if (tp->step_count > 0)
-	    {
-	      warning (_("Tracepoint %d does while-stepping, "
-			 "cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
-	}
+      warning (_("Tracepoint %d has multiple "
+		 "locations, cannot infer $pc"),
+	       tp->base.number);
+      return;
+    }
+  /* ... or does while-stepping.  */
+  else if (tp->step_count > 0)
+    {
+      warning (_("Tracepoint %d does while-stepping, "
+		 "cannot infer $pc"),
+	       tp->base.number);
+      return;
     }
+
+  /* Guess what we can from the tracepoint location.  */
+  gdbarch_guess_tracepoint_registers (gdbarch, regcache,
+				      tp->base.loc->address);
 }
 
 /* This is the implementation of target_ops method to_has_all_memory.  */
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 8b393db..198fc65 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -4341,6 +4341,29 @@ traceframe_available_memory (VEC(mem_range_s) **result,
   return 0;
 }
 
+void
+default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+				    struct regcache *regcache,
+				    CORE_ADDR addr)
+{
+  int pc_regno = gdbarch_pc_regnum (gdbarch);
+  gdb_byte *regs;
+
+  /* This guessing code below only works if the PC register isn't
+     a pseudo-register.  The value of a pseudo-register isn't stored
+     in the (non-readonly) regcache -- instead it's recomputed
+     (probably from some other cached raw register) whenever the
+     register is read.  In this case, a custom method implementation
+     should be used by the architecture.  */
+  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+    return;
+
+  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+			  gdbarch_byte_order (gdbarch), addr);
+  regcache_raw_supply (regcache, pc_regno, regs);
+}
+
 /* Implementation of `sdata' variable.  */
 
 static const struct internalvar_funcs sdata_funcs =
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 8985394..2cff32a 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -353,4 +353,8 @@ extern struct traceframe_info *get_traceframe_info (void);
 
 extern struct bp_location *get_traceframe_location (int *stepping_frame_p);
 
+extern void default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+						struct regcache *regcache,
+						CORE_ADDR addr);
+
 #endif	/* TRACEPOINT_H */
-- 
2.7.0

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 11:45             ` [PATCH] " Marcin Kościelnicki
@ 2016-02-18 15:40               ` Ulrich Weigand
  2016-02-18 15:41                 ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 15:40 UTC (permalink / raw)
  To: Marcin Kościelnicki
  Cc: lgustavo, arnez, gdb-patches, Marcin Kościelnicki

Marcin Kościelnicki wrote:

> 	* gdbarch.c: Regenerate.
> 	* gdbarch.h: Regenerate.
> 	* gdbarch.sh: Add guess_tracepoint_registers hook, include
> 	tracepoint.h.
> 	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
> 	* tracepoint.c (default_guess_tracepoint_registers): New function.
> 	* tracepoint.h (default_guess_tracepoint_registers): New prototype.

>  #include "observer.h"
>  #include "regcache.h"
>  #include "objfiles.h"
> +#include "tracepoint.h"

I don't think you actually need this include, do you?

Otherwise, this patch is OK.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 15:40               ` Ulrich Weigand
@ 2016-02-18 15:41                 ` Marcin Kościelnicki
  2016-02-18 15:58                   ` Ulrich Weigand
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 15:41 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: lgustavo, arnez, gdb-patches

On 18/02/16 16:40, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>
>> 	* gdbarch.c: Regenerate.
>> 	* gdbarch.h: Regenerate.
>> 	* gdbarch.sh: Add guess_tracepoint_registers hook, include
>> 	tracepoint.h.
>> 	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
>> 	* tracepoint.c (default_guess_tracepoint_registers): New function.
>> 	* tracepoint.h (default_guess_tracepoint_registers): New prototype.
>
>>   #include "observer.h"
>>   #include "regcache.h"
>>   #include "objfiles.h"
>> +#include "tracepoint.h"
>
> I don't think you actually need this include, do you?
>
> Otherwise, this patch is OK.
>
> Bye,
> Ulrich
>

I do, the default_guess_tracepoint_registers function is declared there, 
and gdbarch.c uses it.

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 15:41                 ` Marcin Kościelnicki
@ 2016-02-18 15:58                   ` Ulrich Weigand
  2016-02-18 16:01                     ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 15:58 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: lgustavo, arnez, gdb-patches

Marcin Kościelnicki wrote:
> On 18/02/16 16:40, Ulrich Weigand wrote:
> > I don't think you actually need this include, do you?
> >
> > Otherwise, this patch is OK.
> >
> > Bye,
> > Ulrich
> >
> 
> I do, the default_guess_tracepoint_registers function is declared there, 
> and gdbarch.c uses it.

Ah, right.  You should probably move the prototype to arch-utils.h
(and then the implementation to arch-utils.c) to go with the other
default_ functions.

Since gdbarch.h is included everywhere, we try to avoid having it
include other headers as far as possible.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 15:58                   ` Ulrich Weigand
@ 2016-02-18 16:01                     ` Marcin Kościelnicki
  2016-02-18 16:06                       ` Ulrich Weigand
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 16:01 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: lgustavo, arnez, gdb-patches

On 18/02/16 16:58, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>> On 18/02/16 16:40, Ulrich Weigand wrote:
>>> I don't think you actually need this include, do you?
>>>
>>> Otherwise, this patch is OK.
>>>
>>> Bye,
>>> Ulrich
>>>
>>
>> I do, the default_guess_tracepoint_registers function is declared there,
>> and gdbarch.c uses it.
>
> Ah, right.  You should probably move the prototype to arch-utils.h
> (and then the implementation to arch-utils.c) to go with the other
> default_ functions.

Alright, I'll do that.
>
> Since gdbarch.h is included everywhere, we try to avoid having it
> include other headers as far as possible.

FWIW, the header include I added only ends up in gdbarch.c, .h is 
unaffected.
>
> Bye,
> Ulrich
>

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

* Re: [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook.
  2016-02-18 10:35           ` [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook Marcin Kościelnicki
@ 2016-02-18 16:03             ` Ulrich Weigand
  2016-02-18 16:36               ` [PATCH] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 16:03 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: arnez, gdb-patches, Marcin Kościelnicki

Marcin Kościelnicki wrote:

> 	* s390-linux-tdep.c (s390_guess_tracepoint_registers): New function.
> 	(s390_gdbarch_init): Fill guess_tracepoint_registers hook.

I think it would be better to also initialize PSWM to a valid value,
in particular since on 64-bit the addressing mode bits are actually
in the PSWM instead of the PSWA (and at least in principle even GDB
itself occasionally may check the addressing mode bits).

A default valid value for PSWM would be
   0x070d0000UL           in ESA mode
   0x0705000180000000UL   in zArchitecture mode (64-bit addressing mode)

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 16:01                     ` Marcin Kościelnicki
@ 2016-02-18 16:06                       ` Ulrich Weigand
  2016-02-18 16:11                         ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 16:06 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: lgustavo, arnez, gdb-patches

Marcin Kościelnicki wrote:
> On 18/02/16 16:58, Ulrich Weigand wrote:
> > Ah, right.  You should probably move the prototype to arch-utils.h
> > (and then the implementation to arch-utils.c) to go with the other
> > default_ functions.
> 
> Alright, I'll do that.
> >
> > Since gdbarch.h is included everywhere, we try to avoid having it
> > include other headers as far as possible.
> 
> FWIW, the header include I added only ends up in gdbarch.c, .h is 
> unaffected.

Ah, I missed that, sorry.  Anyway, it's probably still better to
have the routine in arch-utils.[ch] like the others ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 16:06                       ` Ulrich Weigand
@ 2016-02-18 16:11                         ` Marcin Kościelnicki
  2016-02-18 16:13                           ` Ulrich Weigand
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 16:11 UTC (permalink / raw)
  To: uweigand; +Cc: lgustavo, arnez, gdb-patches, Marcin Kościelnicki

When we're looking at a tracefile trace frame where registers are not
available, and the tracepoint has only one location, we supply
the location's address as the PC register.  However, this only works
if PC is not a pseudo register, and individual architectures may want
to guess more registers.  Add a gdbarch hook that will handle that.

gdb/ChangeLog:

	* arch-utils.c (default_guess_tracepoint_registers): New function.
	* arch-utils.h (default_guess_tracepoint_registers): New prototype.
	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Add guess_tracepoint_registers hook.
	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
---
Here comes the fixed version.

 gdb/ChangeLog    |  9 +++++++++
 gdb/arch-utils.c | 23 ++++++++++++++++++++++
 gdb/arch-utils.h |  4 ++++
 gdb/gdbarch.c    | 23 ++++++++++++++++++++++
 gdb/gdbarch.h    |  9 +++++++++
 gdb/gdbarch.sh   |  6 ++++++
 gdb/tracefile.c  | 60 ++++++++++++++++++++------------------------------------
 7 files changed, 95 insertions(+), 39 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e507dd1..c8832c9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* arch-utils.c (default_guess_tracepoint_registers): New function.
+	* arch-utils.h (default_guess_tracepoint_registers): New prototype.
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add guess_tracepoint_registers hook.
+	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
+
 2016-02-17  Gary Benson  <gbenson@redhat.com>
 
 	* exec.c (exec_file_locate_attach): Add missing cleanup.
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index fe64627..c3d7802 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -897,6 +897,29 @@ default_addressable_memory_unit_size (struct gdbarch *gdbarch)
   return 1;
 }
 
+void
+default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+				    struct regcache *regcache,
+				    CORE_ADDR addr)
+{
+  int pc_regno = gdbarch_pc_regnum (gdbarch);
+  gdb_byte *regs;
+
+  /* This guessing code below only works if the PC register isn't
+     a pseudo-register.  The value of a pseudo-register isn't stored
+     in the (non-readonly) regcache -- instead it's recomputed
+     (probably from some other cached raw register) whenever the
+     register is read.  In this case, a custom method implementation
+     should be used by the architecture.  */
+  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+    return;
+
+  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+			  gdbarch_byte_order (gdbarch), addr);
+  regcache_raw_supply (regcache, pc_regno, regs);
+}
+
 /* -Wmissing-prototypes */
 extern initialize_file_ftype _initialize_gdbarch_utils;
 
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 3fad2c3..9e1e70e 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -204,4 +204,8 @@ extern char *default_gcc_target_options (struct gdbarch *gdbarch);
 extern const char *default_gnu_triplet_regexp (struct gdbarch *gdbarch);
 extern int default_addressable_memory_unit_size (struct gdbarch *gdbarch);
 
+extern void default_guess_tracepoint_registers (struct gdbarch *gdbarch,
+						struct regcache *regcache,
+						CORE_ADDR addr);
+
 #endif
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..0136c75 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -312,6 +312,7 @@ struct gdbarch
   int has_global_breakpoints;
   gdbarch_has_shared_address_space_ftype *has_shared_address_space;
   gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at;
+  gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers;
   gdbarch_auto_charset_ftype *auto_charset;
   gdbarch_auto_wide_charset_ftype *auto_wide_charset;
   const char * solib_symbols_extension;
@@ -419,6 +420,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->relocate_instruction = NULL;
   gdbarch->has_shared_address_space = default_has_shared_address_space;
   gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at;
+  gdbarch->guess_tracepoint_registers = default_guess_tracepoint_registers;
   gdbarch->auto_charset = default_auto_charset;
   gdbarch->auto_wide_charset = default_auto_wide_charset;
   gdbarch->gen_return_address = default_gen_return_address;
@@ -658,6 +660,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of has_global_breakpoints, invalid_p == 0 */
   /* Skip verify of has_shared_address_space, invalid_p == 0 */
   /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */
+  /* Skip verify of guess_tracepoint_registers, invalid_p == 0 */
   /* Skip verify of auto_charset, invalid_p == 0 */
   /* Skip verify of auto_wide_charset, invalid_p == 0 */
   /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
@@ -1024,6 +1027,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: gnu_triplet_regexp = <%s>\n",
                       host_address_to_string (gdbarch->gnu_triplet_regexp));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: guess_tracepoint_registers = <%s>\n",
+                      host_address_to_string (gdbarch->guess_tracepoint_registers));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: half_bit = %s\n",
                       plongest (gdbarch->half_bit));
   fprintf_unfiltered (file,
@@ -4450,6 +4456,23 @@ set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
   gdbarch->fast_tracepoint_valid_at = fast_tracepoint_valid_at;
 }
 
+void
+gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->guess_tracepoint_registers != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_guess_tracepoint_registers called\n");
+  gdbarch->guess_tracepoint_registers (gdbarch, regcache, addr);
+}
+
+void
+set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch,
+                                        gdbarch_guess_tracepoint_registers_ftype guess_tracepoint_registers)
+{
+  gdbarch->guess_tracepoint_registers = guess_tracepoint_registers;
+}
+
 const char *
 gdbarch_auto_charset (struct gdbarch *gdbarch)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..7ffbf1f 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1327,6 +1327,15 @@ typedef int (gdbarch_fast_tracepoint_valid_at_ftype) (struct gdbarch *gdbarch, C
 extern int gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, char **msg);
 extern void set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at);
 
+/* Guess register state based on tracepoint location.  Used for tracepoints
+   where no registers have been collected, but there's only one location,
+   allowing us to guess the PC value, and perhaps some other registers.
+   On entry, regcache has all registers marked as unavailable. */
+
+typedef void (gdbarch_guess_tracepoint_registers_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
+extern void set_gdbarch_guess_tracepoint_registers (struct gdbarch *gdbarch, gdbarch_guess_tracepoint_registers_ftype *guess_tracepoint_registers);
+
 /* Return the "auto" target charset. */
 
 typedef const char * (gdbarch_auto_charset_ftype) (void);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..61cb04a 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1028,6 +1028,12 @@ m:int:has_shared_address_space:void:::default_has_shared_address_space::0
 # True if a fast tracepoint can be set at an address.
 m:int:fast_tracepoint_valid_at:CORE_ADDR addr, char **msg:addr, msg::default_fast_tracepoint_valid_at::0
 
+# Guess register state based on tracepoint location.  Used for tracepoints
+# where no registers have been collected, but there's only one location,
+# allowing us to guess the PC value, and perhaps some other registers.
+# On entry, regcache has all registers marked as unavailable.
+m:void:guess_tracepoint_registers:struct regcache *regcache, CORE_ADDR addr:regcache, addr::default_guess_tracepoint_registers::0
+
 # Return the "auto" target charset.
 f:const char *:auto_charset:void::default_auto_charset:default_auto_charset::0
 # Return the "auto" target wide charset.
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index de42165..609b7e5 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -388,7 +388,8 @@ void
 tracefile_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int regn, pc_regno;
+  struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
+  int regn;
 
   /* We get here if no register data has been found.  Mark registers
      as unavailable.  */
@@ -397,48 +398,29 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 
   /* We can often usefully guess that the PC is going to be the same
      as the address of the tracepoint.  */
-  pc_regno = gdbarch_pc_regnum (gdbarch);
-
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (tp == NULL || tp->base.loc == NULL)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* But don't try to guess if tracepoint is multi-location...  */
+  if (tp->base.loc->next)
     {
-      struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-      gdb_byte *regs;
-
-      if (tp && tp->base.loc)
-	{
-	  /* But don't try to guess if tracepoint is multi-location...  */
-	  if (tp->base.loc->next)
-	    {
-	      warning (_("Tracepoint %d has multiple "
-			 "locations, cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-	  /* ... or does while-stepping.  */
-	  if (tp->step_count > 0)
-	    {
-	      warning (_("Tracepoint %d does while-stepping, "
-			 "cannot infer $pc"),
-		       tp->base.number);
-	      return;
-	    }
-
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
-	}
+      warning (_("Tracepoint %d has multiple "
+		 "locations, cannot infer $pc"),
+	       tp->base.number);
+      return;
+    }
+  /* ... or does while-stepping.  */
+  else if (tp->step_count > 0)
+    {
+      warning (_("Tracepoint %d does while-stepping, "
+		 "cannot infer $pc"),
+	       tp->base.number);
+      return;
     }
+
+  /* Guess what we can from the tracepoint location.  */
+  gdbarch_guess_tracepoint_registers (gdbarch, regcache,
+				      tp->base.loc->address);
 }
 
 /* This is the implementation of target_ops method to_has_all_memory.  */
-- 
2.7.1

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 16:11                         ` Marcin Kościelnicki
@ 2016-02-18 16:13                           ` Ulrich Weigand
  2016-02-18 16:22                             ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 16:13 UTC (permalink / raw)
  To: Marcin Kościelnicki
  Cc: lgustavo, arnez, gdb-patches, Marcin Kościelnicki

Marcin Kościelnicki wrote:

> 	* arch-utils.c (default_guess_tracepoint_registers): New function.
> 	* arch-utils.h (default_guess_tracepoint_registers): New prototype.
> 	* gdbarch.c: Regenerate.
> 	* gdbarch.h: Regenerate.
> 	* gdbarch.sh: Add guess_tracepoint_registers hook.
> 	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH] gdb: Add guess_tracepoint_registers hook to gdbarch.
  2016-02-18 16:13                           ` Ulrich Weigand
@ 2016-02-18 16:22                             ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 16:22 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: lgustavo, arnez, gdb-patches

On 18/02/16 17:12, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>
>> 	* arch-utils.c (default_guess_tracepoint_registers): New function.
>> 	* arch-utils.h (default_guess_tracepoint_registers): New prototype.
>> 	* gdbarch.c: Regenerate.
>> 	* gdbarch.h: Regenerate.
>> 	* gdbarch.sh: Add guess_tracepoint_registers hook.
>> 	* tracefile.c (tracefile_fetch_registers): Use the new gdbarch hook.
>
> This is OK.
>
> Thanks,
> Ulrich
>

Thanks, pushed.

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

* [PATCH] gdb/s390: Fill guess_tracepoint_registers hook.
  2016-02-18 16:03             ` Ulrich Weigand
@ 2016-02-18 16:36               ` Marcin Kościelnicki
  2016-02-18 16:48                 ` Ulrich Weigand
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 16:36 UTC (permalink / raw)
  To: uweigand; +Cc: arnez, gdb-patches, Marcin Kościelnicki

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_guess_tracepoint_registers): New function.
	(s390_gdbarch_init): Fill guess_tracepoint_registers hook.
---
This version fills PSWM too.  This causes two failures in tests when
combined with the later patches:
		      
- gdb.trace/mi-trace-frame-collected.exp: will have to be changed to expect
  $pswa and $cc to be available.
- gdb.trace/unavailable.exp: likewise.

An unfortunate side effect is that $cc is now considered available (which
unavailable.exp rightly complains about).  There isn't a way to mark
individual bitfields as unavailable, is there?

 gdb/ChangeLog         |  5 +++++
 gdb/s390-linux-tdep.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c8832c9..2b6050d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* s390-linux-tdep.c (s390_guess_tracepoint_registers): New function.
+	(s390_gdbarch_init): Fill guess_tracepoint_registers hook.
+
+2016-02-18  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* arch-utils.c (default_guess_tracepoint_registers): New function.
 	* arch-utils.h (default_guess_tracepoint_registers): New prototype.
 	* gdbarch.c: Regenerate.
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index e827684..57e25b4 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -167,6 +167,40 @@ s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
     regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
 }
 
+/* The "guess_tracepoint_registers" gdbarch method.  */
+
+static void
+s390_guess_tracepoint_registers (struct gdbarch *gdbarch,
+				 struct regcache *regcache,
+				 CORE_ADDR addr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int sz = register_size (gdbarch, S390_PSWA_REGNUM);
+  gdb_byte *reg = (gdb_byte *) alloca (sz);
+  ULONGEST pswm, pswa;
+
+  /* Set PSWA from the location and a default PSWM (the only part we're
+     unlikely to get right is the CC).  */
+  if (tdep->abi == ABI_LINUX_S390)
+    {
+      /* 31-bit PSWA needs high bit set (it's very unlikely the target
+	 was in 24-bit mode).  */
+      pswa = addr | 0x80000000UL;
+      pswm = 0x070d0000UL;
+    }
+  else
+    {
+      pswa = addr;
+      pswm = 0x0705000180000000ULL;
+    }
+
+  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pswa);
+  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
+
+  store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pswm);
+  regcache_raw_supply (regcache, S390_PSWM_REGNUM, reg);
+}
+
 
 /* DWARF Register Mapping.  */
 
@@ -7857,6 +7891,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					    s390_iterate_over_regset_sections);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
   set_gdbarch_write_pc (gdbarch, s390_write_pc);
+  set_gdbarch_guess_tracepoint_registers (gdbarch, s390_guess_tracepoint_registers);
   set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
   set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
-- 
2.7.1

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

* Re: [PATCH] gdb/s390: Fill guess_tracepoint_registers hook.
  2016-02-18 16:36               ` [PATCH] " Marcin Kościelnicki
@ 2016-02-18 16:48                 ` Ulrich Weigand
  2016-02-18 16:58                   ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-02-18 16:48 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: arnez, gdb-patches, Marcin Kościelnicki

Marcin Kościelnicki wrote:

> This version fills PSWM too.  This causes two failures in tests when
> combined with the later patches:
> 		      
> - gdb.trace/mi-trace-frame-collected.exp: will have to be changed to expect
>   $pswa and $cc to be available.
> - gdb.trace/unavailable.exp: likewise.
> 
> An unfortunate side effect is that $cc is now considered available (which
> unavailable.exp rightly complains about).  There isn't a way to mark
> individual bitfields as unavailable, is there?

That's bit unfortunate.  Right now there's no way to mark *parts* of
a register a unavailable (this is possible for the value subsystem,
but not for the plain regcache at this point).

It probably shouldn't matter much to show a defined $cc in those cases.

Patch is OK.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH] gdb/s390: Fill guess_tracepoint_registers hook.
  2016-02-18 16:48                 ` Ulrich Weigand
@ 2016-02-18 16:58                   ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 16:58 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: arnez, gdb-patches

On 18/02/16 17:48, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>
>> This version fills PSWM too.  This causes two failures in tests when
>> combined with the later patches:
>> 		
>> - gdb.trace/mi-trace-frame-collected.exp: will have to be changed to expect
>>    $pswa and $cc to be available.
>> - gdb.trace/unavailable.exp: likewise.
>>
>> An unfortunate side effect is that $cc is now considered available (which
>> unavailable.exp rightly complains about).  There isn't a way to mark
>> individual bitfields as unavailable, is there?
>
> That's bit unfortunate.  Right now there's no way to mark *parts* of
> a register a unavailable (this is possible for the value subsystem,
> but not for the plain regcache at this point).
>
> It probably shouldn't matter much to show a defined $cc in those cases.
>
> Patch is OK.
>
> Bye,
> Ulrich
>

Thanks, pushed.  I will update patch #5 shortly to fix the test issues. 
  FWIW patches #3 and #4 are currently ready for review, while #6-#8 
have some pending issues I'll have to fix (Antoine's comment about auxv 
+ making it work with the high GPRs patch + doc comments everywhere).

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

* Re: [PATCH] gdb.trace: Bump tspeed.exp timeout to 600 seconds.
  2016-01-29  9:53     ` [PATCH] " Marcin Kościelnicki
  2016-02-12 11:20       ` Yao Qi
@ 2016-02-18 18:54       ` Marcin Kościelnicki
  1 sibling, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-18 18:54 UTC (permalink / raw)
  To: arnez; +Cc: gdb-patches

On 29/01/16 10:53, Marcin Kościelnicki wrote:
> It seems the 180 seconds timeout is quite tight on my z13 machine,
> and causes failures when the machine is somewhat loaded.
>
> gdb/testsuite/ChangeLog:
>
> 	* gdb.trace/tspeed.exp: Bump the timeout to 600 seconds.
> ---

I've since learned of an earlier unpushed patch solving the same issue: 
https://sourceware.org/ml/gdb-patches/2015-08/msg00658.html .  Since it 
seems to be a smarter fix than mine, I'd like to abandon this patch.

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

* Re: [PATCH 6/8] gdbserver/s390: Add fast tracepoint support.
  2016-01-25 14:34   ` Antoine Tremblay
@ 2016-02-19 13:41     ` Marcin Kościelnicki
  2016-02-19 14:41       ` Antoine Tremblay
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-19 13:41 UTC (permalink / raw)
  To: Antoine Tremblay; +Cc: gdb-patches

Thanks for your suggestion, but I'm afraid I won't be doing it that way at all.  We're not quite out of the woods yet on multi-tdesc targets: see https://sourceware.org/bugzilla/show_bug.cgi?id=13808 .  This issue basically requires perfectly matched tdesc between gdbserver and IPA on all architectures, so a more generic mechanism is in order.  I think I will just stuff all possible tdescs for a target in an array and pass the tdesc index to IPA via a global variable.

25 sty 2016 3:34 PM Antoine Tremblay <antoine.tremblay@ericsson.com> napisał(a):
>
>
>
> On 01/24/2016 07:12 AM, Marcin Kościelnicki wrote: 
>
> > +void 
> > +initialize_low_tracepoint (void) 
> > +{ 
> > +  unsigned long hwcap = getauxval (AT_HWCAP); 
>
> You might consider also using proc if getauxval is not available ? 
>
> unsigned long hwcap = 0; 
>
> #ifdef HAVE_GETAUXVAL 
>    hwcap = getauxval (AT_HWCAP); 
> #else 
>    unsigned long data[2]; 
>    FILE *f = fopen ("/proc/self/auxv", "r"); 
>
>    if (f == NULL) 
>      return; 
>
>    while (fread (data, sizeof (data), 1, f) > 0) 
>      { 
>       if (data[0] == AT_HWCAP) 
>         { 
>           hwcap = data[1]; 
>           break; 
>         } 
>      } 
>
>    fclose (f); 
>
>
> Regards, 
> Antoine 
>

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

* Re: [PATCH 6/8] gdbserver/s390: Add fast tracepoint support.
  2016-02-19 13:41     ` Marcin Kościelnicki
@ 2016-02-19 14:41       ` Antoine Tremblay
  2016-03-04 10:40         ` [PATCH v2] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Antoine Tremblay @ 2016-02-19 14:41 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: Antoine Tremblay, gdb-patches


Marcin Kościelnicki writes:

> Thanks for your suggestion, but I'm afraid I won't be doing it that way at all.  We're not quite out of the woods yet on multi-tdesc targets: see https://sourceware.org/bugzilla/show_bug.cgi?id=13808 .  This issue basically requires perfectly matched tdesc between gdbserver and IPA on all architectures, so a more generic mechanism is in order.  I think I will just stuff all possible tdescs for a target in an array and pass the tdesc index to IPA via a global variable.
>

Seems like a good idea to me, I'm looking forward to it.

Thanks,
Antoine

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

* [PATCH] gdbserver/s390: Switch on tracepoint support.
  2016-02-07 14:04   ` Marcin Kościelnicki
@ 2016-02-22  7:38     ` Marcin Kościelnicki
  2016-03-04 10:39       ` [PATCH v3] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-22  7:38 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Also adds s390 support to gdb.trace testsuite.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (s390_supports_tracepoints): New function.
	(struct linux_target_ops): Fill supports_tracepoints hook.

gdb/testsuite/ChangeLog:

	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
---
Updated.  This version depends on
https://sourceware.org/ml/gdb-patches/2016-02/msg00627.html .

 gdb/gdbserver/ChangeLog                              |  5 +++++
 gdb/gdbserver/linux-s390-low.c                       | 10 +++++++++-
 gdb/testsuite/ChangeLog                              | 10 +++++-----
 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 16 +++++++++++++---
 gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
 5 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 326c769..6132bbf 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,10 @@
 2016-02-17  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* linux-s390-low.c (s390_supports_tracepoints): New function.
+	(struct linux_target_ops): Fill supports_tracepoints hook.
+
+2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* linux-s390-low.c (s390_supports_z_point_type): New function.
 	(struct linux_target_ops): Wire s390_supports_z_point_type in.
 
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 533e384..c85c331 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -690,6 +690,14 @@ s390_regs_info (void)
   return &regs_info;
 }
 
+/* The "supports_tracepoints" linux_target_ops method.  */
+
+static int
+s390_supports_tracepoints (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -716,7 +724,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
+  s390_supports_tracepoints,
   NULL, /* get_thread_area */
   NULL, /* install_fast_tracepoint_jump_pad */
   NULL, /* emit_ops */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8d695ec..27b2548 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-22  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
+	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
+
 2016-02-19  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* gdb.trace/ftrace.exp: Remove unnecessary target check.
@@ -312,11 +317,6 @@
 	(foreach_with_prefix): Likewise.
 	* lib/gdb.exp (foreach_with_prefix): New procedure.
 
-2016-01-25  Marcin Kościelnicki  <koriakin@0x04.net>
-
-	* gdb.trace/backtrace.exp: Bump stack collection fudge factor.
-	* gdb.trace/entry-values.exp: Bump stack collection fudge factor.
-
 2016-01-23  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* gdb.trace/unavailable-dwarf-piece.exp: Fix bitfield handling on big
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 0daaa25..1f0baaa 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -91,11 +91,21 @@ proc test_trace_frame_collected { data_source } {
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \
 	    "-trace-find frame-number 0"
 
+	set reg_pattern "\{number=\"$decimal\",value=\"$hex\"\}"
+
 	# Test MI command '-trace-frame-collected' dumps only
 	# collected registers.
-	mi_gdb_test "-trace-frame-collected" \
-	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
-	    "-trace-frame-collected (register)"
+	if { [istarget "s390*-*-*"] } {
+	    # Only PC is collected, but on s390 PC is a pseudo-register -
+	    # collecting it also collects the underlying PSWA register.
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[$reg_pattern,$reg_pattern,$reg_pattern,$reg_pattern\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	} else {
+	    mi_gdb_test "-trace-frame-collected" \
+		"\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[$reg_pattern\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+		"-trace-frame-collected (register)"
+	}
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index eceb182..a330024 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -48,6 +48,14 @@ x86_trace_dummy ()
        "    nop\n" \
        )
 
+#elif (defined __s390__)
+
+#define FAST_TRACEPOINT_LABEL(name) \
+  asm ("    .global " SYMBOL(name) "\n" \
+       SYMBOL(name) ":\n" \
+       "    mvc 0(8, %r15), 0(%r15)\n" \
+       )
+
 #else
 
 #error "unsupported architecture for trace tests"
-- 
2.7.1

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

* Re: [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-02-07 14:01   ` Marcin Kościelnicki
@ 2016-02-25 19:23     ` Marcin Kościelnicki
  2016-03-04 10:42       ` Marcin Kościelnicki
  2016-03-11  9:58     ` Andreas Arnez
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-25 19:23 UTC (permalink / raw)
  To: gdb-patches

Ping.

On 07/02/16 15:01, Marcin Kościelnicki wrote:
> gdb/ChangeLog:
>
> 	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
> 	(s390_ax_pseudo_register_push_stack): New function.
> 	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
> 	ax_pseudo_register_push_stack hooks.
> ---
> Added missing comments.
>
>   gdb/ChangeLog         |  7 +++++
>   gdb/s390-linux-tdep.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 91 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index d24cccd..6260040 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,12 @@
>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>
> +	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
> +	(s390_ax_pseudo_register_push_stack): New function.
> +	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
> +	ax_pseudo_register_push_stack hooks.
> +
> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
> +
>   	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
>   	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
>
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index 144365c..97bd564 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
>     return default_register_reggroup_p (gdbarch, regnum, group);
>   }
>
> +/* The "ax_pseudo_register_collect" gdbarch method.  */
> +
> +static int
> +s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
> +				 struct agent_expr *ax, int regnum)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  if (regnum == tdep->pc_regnum)
> +    {
> +      ax_reg_mask (ax, S390_PSWA_REGNUM);
> +    }
> +  else if (regnum == tdep->cc_regnum)
> +    {
> +      ax_reg_mask (ax, S390_PSWM_REGNUM);
> +    }
> +  else if (regnum_is_gpr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->gpr_full_regnum;
> +      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
> +      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
> +    }
> +  else if (regnum_is_vxr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->v0_full_regnum;
> +      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
> +      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
> +    }
> +  else
> +    {
> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
> +    }
> +  return 0;
> +}
> +
> +/* The "ax_pseudo_register_push_stack" gdbarch method.  */
> +
> +static int
> +s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
> +				    struct agent_expr *ax, int regnum)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  if (regnum == tdep->pc_regnum)
> +    {
> +      ax_reg (ax, S390_PSWA_REGNUM);
> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
> +	{
> +	  ax_zero_ext (ax, 31);
> +	}
> +    }
> +  else if (regnum == tdep->cc_regnum)
> +    {
> +      ax_reg (ax, S390_PSWM_REGNUM);
> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
> +	ax_const_l (ax, 12);
> +      else
> +	ax_const_l (ax, 44);
> +      ax_simple (ax, aop_rsh_unsigned);
> +      ax_zero_ext (ax, 2);
> +    }
> +  else if (regnum_is_gpr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->gpr_full_regnum;
> +      ax_reg (ax, S390_R0_REGNUM + regnum);
> +      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
> +      ax_const_l (ax, 32);
> +      ax_simple (ax, aop_lsh);
> +      ax_simple (ax, aop_bit_or);
> +    }
> +  else if (regnum_is_vxr_full (tdep, regnum))
> +    {
> +      /* Too large to stuff on the stack.  */
> +      return 1;
> +    }
> +  else
> +    {
> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
> +    }
> +  return 0;
> +}
> +
>
>   /* A helper for s390_software_single_step, decides if an instruction
>      is a partial-execution instruction that needs to be executed until
> @@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>     set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
>     set_tdesc_pseudo_register_reggroup_p (gdbarch,
>   					s390_pseudo_register_reggroup_p);
> +  set_gdbarch_ax_pseudo_register_collect (gdbarch,
> +					  s390_ax_pseudo_register_collect);
> +  set_gdbarch_ax_pseudo_register_push_stack
> +      (gdbarch, s390_ax_pseudo_register_push_stack);
>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>     set_gdbarch_register_name (gdbarch, s390_register_name);
>
>

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-02-07 14:02   ` Marcin Kościelnicki
@ 2016-02-25 19:23     ` Marcin Kościelnicki
  2016-03-04 10:42       ` Marcin Kościelnicki
  2016-03-11 11:20     ` Andreas Arnez
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-02-25 19:23 UTC (permalink / raw)
  To: gdb-patches

Ping.

On 07/02/16 15:02, Marcin Kościelnicki wrote:
> gdb/ChangeLog:
>
> 	* s390-linux-tdep.c (s390_gen_return_address): New function.
> 	(s390_gdbarch_init): Fill gen_return_address hook.
> ---
> Added missing comment.
>
>   gdb/ChangeLog         |  5 +++++
>   gdb/s390-linux-tdep.c | 13 +++++++++++++
>   2 files changed, 18 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 6260040..0cf8bfc 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,10 @@
>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>
> +	* s390-linux-tdep.c (s390_gen_return_address): New function.
> +	(s390_gdbarch_init): Fill gen_return_address hook.
> +
> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
> +
>   	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>   	(s390_ax_pseudo_register_push_stack): New function.
>   	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index 97bd564..0b91ed1 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -627,6 +627,18 @@ s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>     return 0;
>   }
>
> +/* The "gen_return_address" gdbarch method.  */
> +
> +static void
> +s390_gen_return_address (struct gdbarch *gdbarch,
> +			 struct agent_expr *ax, struct axs_value *value,
> +			 CORE_ADDR scope)
> +{
> +  value->type = register_type (gdbarch, S390_R14_REGNUM);
> +  value->kind = axs_lvalue_register;
> +  value->u.reg = S390_R14_REGNUM;
> +}
> +
>
>   /* A helper for s390_software_single_step, decides if an instruction
>      is a partial-execution instruction that needs to be executed until
> @@ -7970,6 +7982,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>   					  s390_ax_pseudo_register_collect);
>     set_gdbarch_ax_pseudo_register_push_stack
>         (gdbarch, s390_ax_pseudo_register_push_stack);
> +  set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>     set_gdbarch_register_name (gdbarch, s390_register_name);
>
>

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

* [PATCH v3] gdbserver/s390: Switch on tracepoint support.
  2016-02-22  7:38     ` [PATCH] " Marcin Kościelnicki
@ 2016-03-04 10:39       ` Marcin Kościelnicki
  2016-03-15 18:41         ` [PATCH v4] " Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-04 10:39 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Also adds s390 support to gdb.trace testsuite.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (s390_supports_tracepoints): New function.
	(struct linux_target_ops): Fill supports_tracepoints hook.

gdb/testsuite/ChangeLog:

	* gdb.trace/ftrace.exp: Set arg0exp for s390.
	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
	variable for GPR 0 instead of assuming it is register 0.
	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
	* lib/trace-support.exp: Add s390 registers.
---
Since I'm abandoning my main gdb.trace cleanup patch, here's a new version
that includes the necessary s390 test changes on top of current master.

 gdb/gdbserver/ChangeLog                              |  5 +++++
 gdb/gdbserver/linux-s390-low.c                       | 10 +++++++++-
 gdb/testsuite/ChangeLog                              |  9 +++++++++
 gdb/testsuite/gdb.trace/ftrace.exp                   |  5 +++++
 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 15 ++++++++++++++-
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp     | 18 +++++++++++++-----
 gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
 gdb/testsuite/lib/trace-support.exp                  |  4 ++++
 8 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 11e1c4f..489a044 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,8 @@
+2016-03-04  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* linux-s390-low.c (s390_supports_tracepoints): New function.
+	(struct linux_target_ops): Fill supports_tracepoints hook.
+
 2016-03-03  Yao Qi  <yao.qi@linaro.org>
 
 	* linux-low.c: Update comments to start_step_over.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 7304feb..2bcfa7a 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -745,6 +745,14 @@ s390_regs_info (void)
   return &regs_info;
 }
 
+/* The "supports_tracepoints" linux_target_ops method.  */
+
+static int
+s390_supports_tracepoints (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -771,7 +779,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
+  s390_supports_tracepoints,
   NULL, /* get_thread_area */
   NULL, /* install_fast_tracepoint_jump_pad */
   NULL, /* emit_ops */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 1811103..29a3fd0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2016-03-04  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.trace/ftrace.exp: Set arg0exp for s390.
+	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
+	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
+	variable for GPR 0 instead of assuming it is register 0.
+	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
+	* lib/trace-support.exp: Add s390 registers.
+
 2016-03-03  Doug Evans  <dje@google.com>
 
 	* gdb.base/skip.exp: Use with_test_prefix.
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index a1d4771..b3c1223 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -242,6 +242,11 @@ if [is_amd64_regs_target] {
     set arg0exp "*(int *) (\$ebp + 8)"
 } elseif { [istarget "aarch64*-*-*"] } {
     set arg0exp "\$x0"
+} elseif { [istarget "s390x-*-*"] } {
+    set arg0exp "\$r2"
+} elseif { [istarget "s390-*-*"] } {
+    # On targets with 64-bit GPRs, avoid the high part.
+    set arg0exp "(\$r2 & 0xffffffff)"
 } else {
     set arg0exp ""
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 0daaa25..a69c329 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -91,10 +91,23 @@ proc test_trace_frame_collected { data_source } {
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \
 	    "-trace-find frame-number 0"
 
+	set reg_pattern "\{number=\"$decimal\",value=\"$hex\"\}"
+
 	# Test MI command '-trace-frame-collected' dumps only
 	# collected registers.
+	if { [istarget "s390*-*-*"] } {
+	    # Only PC is collected, but on s390 PC is a pseudo-register -
+	    # collecting it also collects the underlying PSWA register.
+	    if { "$data_source" != "tfile" } {
+		set reg_pattern "$reg_pattern,$reg_pattern"
+	    } else {
+		# For tfile, PSWM and CC are also guessed.
+		set reg_pattern "$reg_pattern,$reg_pattern,$reg_pattern,$reg_pattern"
+	    }
+	}
+
 	mi_gdb_test "-trace-frame-collected" \
-	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[$reg_pattern\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
 	    "-trace-frame-collected (register)"
 
 	mi_gdb_test "-trace-find frame-number 1" \
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 82c6101..4ab67fe 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -130,28 +130,36 @@ proc test_trace_unavailable { data_source } {
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
 	    "-trace-find frame-number 1"
 
-	set pcnum 0
+	set pcnum -1
+	set gpr0num -1
 	if [is_amd64_regs_target] {
 	    set pcnum 16
+	    set gpr0num 0
 	} elseif [is_x86_like_target] {
 	    set pcnum 8
+	    set gpr0num 0
 	} elseif [is_aarch64_target] {
 	    set pcnum 32
+	    set gpr0num 0
+	} elseif { [istarget "s390*-*-*"] } {
+	    # Strictly speaking, this is PSWA, not PC.
+	    set pcnum 1
+	    set gpr0num 2
 	} else {
 	    # Other ports support tracepoint should define the number
 	    # of its own pc register.
 	}
 
-	if { $pcnum != 0 } {
+	if { $pcnum != -1 } {
 	    global hex
 	    # Test that register 0 and PC are displayed, and register
 	    # 0 is unavailable.
-	    mi_gdb_test "-data-list-register-values x 0 ${pcnum}" \
-		".*\\^done,register-values=\\\[\{number=\"0\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
+	    mi_gdb_test "-data-list-register-values x ${gpr0num} ${pcnum}" \
+		".*\\^done,register-values=\\\[\{number=\"${gpr0num}\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
 		"-data-list-register-values x"
 
 	    # Test that only available register PC is displayed.
-	    mi_gdb_test "-data-list-register-values --skip-unavailable x 0 ${pcnum}" \
+	    mi_gdb_test "-data-list-register-values --skip-unavailable x ${gpr0num} ${pcnum}" \
 		".*\\^done,register-values=\\\[\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
 		"-data-list-register-values --skip-unavailable x"
 	}
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index eceb182..a330024 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -48,6 +48,14 @@ x86_trace_dummy ()
        "    nop\n" \
        )
 
+#elif (defined __s390__)
+
+#define FAST_TRACEPOINT_LABEL(name) \
+  asm ("    .global " SYMBOL(name) "\n" \
+       SYMBOL(name) ":\n" \
+       "    mvc 0(8, %r15), 0(%r15)\n" \
+       )
+
 #else
 
 #error "unsupported architecture for trace tests"
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
index f593c43..878f9e2 100644
--- a/gdb/testsuite/lib/trace-support.exp
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -36,6 +36,10 @@ if [is_amd64_regs_target] {
     set fpreg "x29"
     set spreg "sp"
     set pcreg "pc"
+} elseif { [istarget "s390*-*-*"] } {
+    set fpreg "r11"
+    set spreg "r15"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
-- 
2.7.1

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

* [PATCH v2] gdbserver/s390: Add fast tracepoint support.
  2016-02-19 14:41       ` Antoine Tremblay
@ 2016-03-04 10:40         ` Marcin Kościelnicki
  2016-03-14 16:19           ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-04 10:40 UTC (permalink / raw)
  To: gdb-patches; +Cc: antoine.tremblay, Marcin Kościelnicki

Fast tracepoints will only work on 6-byte intructions, and assume at least
a z900 CPU.  s390 also has 4-byte jump instructions, which also work on
pre-z900, but their range is limitted to +-64kiB, which is not very useful
(and wouldn't work at all with current jump pad allocation).

There's a little problem with s390_relocate_instruction function: it
converts BRAS/BRASL instructions to LARL of the return address + JG
to the target address.  On 31-bit, this sets the high bit of the target
register to 0, while BRAS/BRASL would set it to 1.  While this is not
a problem when the result is only used to address memory, it could
possibly break something that expects to compare such addresses for
equality without first masking the bit off.  In particular, I'm not sure
whether leaving the return address high bit unset is ABI-compliant
(could confuse some unwinder?).  If that's a problem, it could be fixed
by handling it in the jump pad (since at that point we can just modify
the GPRs in the save area without having to worry about preserving
CCs and only having that one GPR to work with - I'm not sure if it's
even possible to set the high bit with such constraints).

gdb/gdbserver/ChangeLog:

	* Makefile.in: Add s390 IPA files.
	* configure.srv: Build IPA for s390.
	* linux-s390-ipa.c: New file.
	* linux-s390-low.c: New includes - inttypes.h and linux-s390-tdesc.h.
	(init_registers_s390_linux32): Move declaration to linux-s390-tdesc.h.
	(tdesc_s390_linux32): Ditto.
	(init_registers_s390_linux32v1): Ditto.
	(tdesc_s390_linux32v1): Ditto.
	(init_registers_s390_linux32v2): Ditto.
	(tdesc_s390_linux32v2): Ditto.
	(init_registers_s390_linux64): Ditto.
	(tdesc_s390_linux64): Ditto.
	(init_registers_s390_linux64v1): Ditto.
	(tdesc_s390_linux64v1): Ditto.
	(init_registers_s390_linux64v2): Ditto.
	(tdesc_s390_linux64v2): Ditto.
	(init_registers_s390_te_linux64): Ditto.
	(tdesc_s390_te_linux64): Ditto.
	(init_registers_s390_vx_linux64): Ditto.
	(tdesc_s390_vx_linux64): Ditto.
	(init_registers_s390_tevx_linux64): Ditto.
	(tdesc_s390_tevx_linux64): Ditto.
	(init_registers_s390x_linux64): Ditto.
	(tdesc_s390x_linux64): Ditto.
	(init_registers_s390x_linux64v1): Ditto.
	(tdesc_s390x_linux64v1): Ditto.
	(init_registers_s390x_linux64v2): Ditto.
	(tdesc_s390x_linux64v2): Ditto.
	(init_registers_s390x_te_linux64): Ditto.
	(tdesc_s390x_te_linux64): Ditto.
	(init_registers_s390x_vx_linux64): Ditto.
	(tdesc_s390x_vx_linux64): Ditto.
	(init_registers_s390x_tevx_linux64): Ditto.
	(tdesc_s390x_tevx_linux64): Ditto.
	(have_hwcap_s390_vx): New static variable.
	(s390_arch_setup): Fill have_hwcap_s390_vx.
	(s390_get_thread_area): New function.
	(s390_ft_entry_gpr_esa): New const.
	(s390_ft_entry_gpr_zarch): New const.
	(s390_ft_entry_misc): New const.
	(s390_ft_entry_fr): New const.
	(s390_ft_entry_vr): New const.
	(s390_ft_main_31): New const.
	(s390_ft_main_64): New const.
	(s390_ft_exit_fr): New const.
	(s390_ft_exit_vr): New const.
	(s390_ft_exit_misc): New const.
	(s390_ft_exit_gpr_esa): New const.
	(s390_ft_exit_gpr_zarch): New const.
	(append_insns): New function.
	(s390_relocate_instruction): New function.
	(s390_install_fast_tracepoint_jump_pad): New function.
	(s390_get_min_fast_tracepoint_insn_len): New function.
	(s390_get_ipa_tdesc_idx): New function.
	(struct linux_target_ops): Wire in the above functions.
	(initialize_low_arch) [!__s390x__]: Don't initialize s390x tdescs.
	* linux-s390-tdesc.h: New file.
---
Updated version - includes rebase on top of
ae91f6253926e4dadebcae90772f4f5a5bd06056 and some minor fixes.

 gdb/gdbserver/ChangeLog          |  60 +++
 gdb/gdbserver/Makefile.in        |  48 +++
 gdb/gdbserver/configure.srv      |  16 +
 gdb/gdbserver/linux-s390-ipa.c   | 394 ++++++++++++++++++++
 gdb/gdbserver/linux-s390-low.c   | 774 +++++++++++++++++++++++++++++++++++----
 gdb/gdbserver/linux-s390-tdesc.h | 102 ++++++
 6 files changed, 1331 insertions(+), 63 deletions(-)
 create mode 100644 gdb/gdbserver/linux-s390-ipa.c
 create mode 100644 gdb/gdbserver/linux-s390-tdesc.h

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 489a044..6ff94b1 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,65 @@
 2016-03-04  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* Makefile.in: Add s390 IPA files.
+	* configure.srv: Build IPA for s390.
+	* linux-s390-ipa.c: New file.
+	* linux-s390-low.c: New includes - inttypes.h and linux-s390-tdesc.h.
+	(init_registers_s390_linux32): Move declaration to linux-s390-tdesc.h.
+	(tdesc_s390_linux32): Ditto.
+	(init_registers_s390_linux32v1): Ditto.
+	(tdesc_s390_linux32v1): Ditto.
+	(init_registers_s390_linux32v2): Ditto.
+	(tdesc_s390_linux32v2): Ditto.
+	(init_registers_s390_linux64): Ditto.
+	(tdesc_s390_linux64): Ditto.
+	(init_registers_s390_linux64v1): Ditto.
+	(tdesc_s390_linux64v1): Ditto.
+	(init_registers_s390_linux64v2): Ditto.
+	(tdesc_s390_linux64v2): Ditto.
+	(init_registers_s390_te_linux64): Ditto.
+	(tdesc_s390_te_linux64): Ditto.
+	(init_registers_s390_vx_linux64): Ditto.
+	(tdesc_s390_vx_linux64): Ditto.
+	(init_registers_s390_tevx_linux64): Ditto.
+	(tdesc_s390_tevx_linux64): Ditto.
+	(init_registers_s390x_linux64): Ditto.
+	(tdesc_s390x_linux64): Ditto.
+	(init_registers_s390x_linux64v1): Ditto.
+	(tdesc_s390x_linux64v1): Ditto.
+	(init_registers_s390x_linux64v2): Ditto.
+	(tdesc_s390x_linux64v2): Ditto.
+	(init_registers_s390x_te_linux64): Ditto.
+	(tdesc_s390x_te_linux64): Ditto.
+	(init_registers_s390x_vx_linux64): Ditto.
+	(tdesc_s390x_vx_linux64): Ditto.
+	(init_registers_s390x_tevx_linux64): Ditto.
+	(tdesc_s390x_tevx_linux64): Ditto.
+	(have_hwcap_s390_vx): New static variable.
+	(s390_arch_setup): Fill have_hwcap_s390_vx.
+	(s390_get_thread_area): New function.
+	(s390_ft_entry_gpr_esa): New const.
+	(s390_ft_entry_gpr_zarch): New const.
+	(s390_ft_entry_misc): New const.
+	(s390_ft_entry_fr): New const.
+	(s390_ft_entry_vr): New const.
+	(s390_ft_main_31): New const.
+	(s390_ft_main_64): New const.
+	(s390_ft_exit_fr): New const.
+	(s390_ft_exit_vr): New const.
+	(s390_ft_exit_misc): New const.
+	(s390_ft_exit_gpr_esa): New const.
+	(s390_ft_exit_gpr_zarch): New const.
+	(append_insns): New function.
+	(s390_relocate_instruction): New function.
+	(s390_install_fast_tracepoint_jump_pad): New function.
+	(s390_get_min_fast_tracepoint_insn_len): New function.
+	(s390_get_ipa_tdesc_idx): New function.
+	(struct linux_target_ops): Wire in the above functions.
+	(initialize_low_arch) [!__s390x__]: Don't initialize s390x tdescs.
+	* linux-s390-tdesc.h: New file.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* linux-s390-low.c (s390_supports_tracepoints): New function.
 	(struct linux_target_ops): Fill supports_tracepoints hook.
 
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 257e9bf..48e843b 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -531,6 +531,54 @@ linux-aarch64-ipa.o: linux-aarch64-ipa.c
 aarch64-ipa.o: aarch64.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
+linux-s390-ipa.o: linux-s390-ipa.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux32-ipa.o: s390-linux32.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux32v1-ipa.o: s390-linux32v1.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux32v2-ipa.o: s390-linux32v2.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux64-ipa.o: s390-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux64v1-ipa.o: s390-linux64v1.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-linux64v2-ipa.o: s390-linux64v2.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-te-linux64-ipa.o: s390-te-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-vx-linux64-ipa.o: s390-vx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390-tevx-linux64-ipa.o: s390-tevx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-linux64-ipa.o: s390x-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-linux64v1-ipa.o: s390x-linux64v1.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-linux64v2-ipa.o: s390x-linux64v2.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-te-linux64-ipa.o: s390x-te-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-vx-linux64-ipa.o: s390x-vx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+s390x-tevx-linux64-ipa.o: s390x-tevx-linux64.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
 tdesc-ipa.o: tdesc.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index a89b1d1..ce02876 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -307,6 +307,22 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
+			ipa_obj="linux-s390-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux32-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux32v1-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux32v2-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux64v1-ipa.o"
+			ipa_obj="${ipa_obj} s390-linux64v2-ipa.o"
+			ipa_obj="${ipa_obj} s390-vx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390-te-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390-tevx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-linux64v1-ipa.o"
+			ipa_obj="${ipa_obj} s390x-linux64v2-ipa.o"
+			ipa_obj="${ipa_obj} s390x-vx-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-te-linux64-ipa.o"
+			ipa_obj="${ipa_obj} s390x-tevx-linux64-ipa.o"
 			;;
   sh*-*-linux*)		srv_regobj=reg-sh.o
 			srv_tgtobj="$srv_linux_obj linux-sh-low.o"
diff --git a/gdb/gdbserver/linux-s390-ipa.c b/gdb/gdbserver/linux-s390-ipa.c
new file mode 100644
index 0000000..d804188
--- /dev/null
+++ b/gdb/gdbserver/linux-s390-ipa.c
@@ -0,0 +1,394 @@
+/* GNU/Linux S/390 specific low level interface, for the in-process
+   agent library for GDB.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "server.h"
+#include "tracepoint.h"
+#include "linux-s390-tdesc.h"
+
+#define FT_FPR(x) (0x000 + (x) * 0x10)
+#define FT_VR(x) (0x000 + (x) * 0x10)
+#define FT_VR_L(x) (0x008 + (x) * 0x10)
+#define FT_GPR(x) (0x200 + (x) * 8)
+#define FT_GPR_U(x) (0x200 + (x) * 8)
+#define FT_GPR_L(x) (0x204 + (x) * 8)
+#define FT_GPR(x) (0x200 + (x) * 8)
+#define FT_ACR(x) (0x280 + (x) * 4)
+#define FT_PSWM 0x2c0
+#define FT_PSWM_U 0x2c0
+#define FT_PSWA 0x2c8
+#define FT_PSWA_L 0x2cc
+#define FT_FPC 0x2d0
+
+/* Mappings between registers collected by the jump pad and GDB's register
+   array layout used by regcache.
+
+   See linux-s390-low.c (s390_install_fast_tracepoint_jump_pad) for more
+   details.  */
+
+#ifndef __s390x__
+
+/* Used for s390-linux32, s390-linux32v1, s390-linux32v2.  */
+
+static const int s390_linux32_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit GPRs (mapped to lower halves of 64-bit slots).  */
+  FT_GPR_L (0), FT_GPR_L (1), FT_GPR_L (2), FT_GPR_L (3),
+  FT_GPR_L (4), FT_GPR_L (5), FT_GPR_L (6), FT_GPR_L (7),
+  FT_GPR_L (8), FT_GPR_L (9), FT_GPR_L (10), FT_GPR_L (11),
+  FT_GPR_L (12), FT_GPR_L (13), FT_GPR_L (14), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+};
+
+/* Used for s390-linux64, s390-linux64v1, s390-linux64v2, s390-vx-linux64.  */
+
+static const int s390_linux64_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit halves of 64-bit GPRs.  */
+  FT_GPR_U (0), FT_GPR_L (0),
+  FT_GPR_U (1), FT_GPR_L (1),
+  FT_GPR_U (2), FT_GPR_L (2),
+  FT_GPR_U (3), FT_GPR_L (3),
+  FT_GPR_U (4), FT_GPR_L (4),
+  FT_GPR_U (5), FT_GPR_L (5),
+  FT_GPR_U (6), FT_GPR_L (6),
+  FT_GPR_U (7), FT_GPR_L (7),
+  FT_GPR_U (8), FT_GPR_L (8),
+  FT_GPR_U (9), FT_GPR_L (9),
+  FT_GPR_U (10), FT_GPR_L (10),
+  FT_GPR_U (11), FT_GPR_L (11),
+  FT_GPR_U (12), FT_GPR_L (12),
+  FT_GPR_U (13), FT_GPR_L (13),
+  FT_GPR_U (14), FT_GPR_L (14),
+  FT_GPR_U (15), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+/* Used for s390-te-linux64, s390-tevx-linux64.  */
+
+static const int s390_te_linux64_ft_collect_regmap[] = {
+  /* 32-bit PSWA and PSWM.  */
+  FT_PSWM_U, FT_PSWA_L,
+  /* 32-bit halves of 64-bit GPRs.  */
+  FT_GPR_U (0), FT_GPR_L (0),
+  FT_GPR_U (1), FT_GPR_L (1),
+  FT_GPR_U (2), FT_GPR_L (2),
+  FT_GPR_U (3), FT_GPR_L (3),
+  FT_GPR_U (4), FT_GPR_L (4),
+  FT_GPR_U (5), FT_GPR_L (5),
+  FT_GPR_U (6), FT_GPR_L (6),
+  FT_GPR_U (7), FT_GPR_L (7),
+  FT_GPR_U (8), FT_GPR_L (8),
+  FT_GPR_U (9), FT_GPR_L (9),
+  FT_GPR_U (10), FT_GPR_L (10),
+  FT_GPR_U (11), FT_GPR_L (11),
+  FT_GPR_U (12), FT_GPR_L (12),
+  FT_GPR_U (13), FT_GPR_L (13),
+  FT_GPR_U (14), FT_GPR_L (14),
+  FT_GPR_U (15), FT_GPR_L (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* TDB */
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+#else /* __s390x__ */
+
+/* Used for s390x-linux64, s390x-linux64v1, s390x-linux64v2, s390x-vx-linux64.  */
+
+static const int s390x_ft_collect_regmap[] = {
+  /* 64-bit PSWA and PSWM.  */
+  FT_PSWM, FT_PSWA,
+  /* 64-bit GPRs.  */
+  FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
+  FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
+  FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
+  FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+/* Used for s390x-te-linux64, s390x-tevx-linux64.  */
+
+static const int s390x_te_ft_collect_regmap[] = {
+  /* 64-bit PSWA and PSWM.  */
+  FT_PSWM, FT_PSWA,
+  /* 64-bit GPRs.  */
+  FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
+  FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
+  FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
+  FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
+  /* ACRs */
+  FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
+  FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
+  FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
+  FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
+  /* FPRs (mapped to upper halves of 128-bit VR slots).  */
+  FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
+  FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
+  FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
+  FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
+  /* orig_r2, last_break, system_call */
+  -1, -1, -1,
+  /* TDB */
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  -1, -1, -1, -1,
+  /* Lower halves of 128-bit VRs. */
+  FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
+  FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
+  FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
+  FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
+  /* And the next 16 VRs.  */
+  FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
+  FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
+  FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
+  FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
+};
+
+#endif
+
+/* Initialized by get_ipa_tdesc according to the tdesc in use.  */
+
+static const int *s390_regmap;
+static int s390_regnum;
+
+/* Fill in REGCACHE with registers saved by the jump pad in BUF.  */
+
+void
+supply_fast_tracepoint_registers (struct regcache *regcache,
+				  const unsigned char *buf)
+{
+  int i;
+  for (i = 0; i < s390_regnum; i++)
+    if (s390_regmap[i] != -1)
+      supply_register (regcache, i, ((char *) buf) + s390_regmap[i]);
+}
+
+IP_AGENT_EXPORT_FUNC ULONGEST
+gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
+{
+  int offset;
+  if (regnum >= s390_regnum)
+    return 0;
+  offset = s390_regmap[regnum];
+  if (offset == -1)
+    return 0;
+
+  /* The regnums are variable, better to figure out size by FT offset.  */
+
+  /* 64-bit ones.  */
+  if (offset < FT_VR(16)
+#ifdef __s390x__
+      || (offset >= FT_GPR(0) && offset < FT_ACR(0))
+      || offset == FT_PSWM
+      || offset == FT_PSWA
+#endif
+     )
+    return *(uint64_t *) (raw_regs + offset);
+
+  if (offset >= FT_ACR(0 && offset < FT_PSWM)
+      || offset == FT_FPC
+#ifndef __s390x__
+      || (offset >= FT_GPR(0) && offset < FT_ACR(0))
+      || offset == FT_PSWM_U
+      || offset == FT_PSWA_L
+#endif
+     )
+    return *(uint32_t *) (raw_regs + offset);
+
+  /* This leaves 128-bit VX.  No way to return them.  */
+  return 0;
+}
+
+/* Return target_desc to use for IPA, given the tdesc index passed by
+   gdbserver.  For s390, it also sets s390_regmap and s390_regnum.  */
+
+const struct target_desc *
+get_ipa_tdesc (int idx)
+{
+#define SET_REGMAP(regmap, skip_last) \
+	do { \
+	  s390_regmap = regmap; \
+	  s390_regnum = (sizeof regmap / sizeof regmap[0]) - skip_last; \
+	} while(0)
+  switch (idx)
+    {
+#ifdef __s390x__
+    case S390_TDESC_64:
+      /* Subtract number of VX regs.  */
+      SET_REGMAP(s390x_ft_collect_regmap, 32);
+      return tdesc_s390x_linux64;
+    case S390_TDESC_64V1:
+      SET_REGMAP(s390x_ft_collect_regmap, 32);
+      return tdesc_s390x_linux64v1;
+    case S390_TDESC_64V2:
+      SET_REGMAP(s390x_ft_collect_regmap, 32);
+      return tdesc_s390x_linux64v2;
+    case S390_TDESC_TE:
+      SET_REGMAP(s390x_te_ft_collect_regmap, 32);
+      return tdesc_s390x_te_linux64;
+    case S390_TDESC_VX:
+      SET_REGMAP(s390x_ft_collect_regmap, 0);
+      return tdesc_s390x_vx_linux64;
+    case S390_TDESC_TEVX:
+      SET_REGMAP(s390x_te_ft_collect_regmap, 0);
+      return tdesc_s390x_tevx_linux64;
+#else
+    case S390_TDESC_32:
+      SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
+      return tdesc_s390_linux32;
+    case S390_TDESC_32V1:
+      SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
+      return tdesc_s390_linux32v1;
+    case S390_TDESC_32V2:
+      SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
+      return tdesc_s390_linux32v2;
+    case S390_TDESC_64:
+      SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
+      return tdesc_s390_linux64;
+    case S390_TDESC_64V1:
+      SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
+      return tdesc_s390_linux64v1;
+    case S390_TDESC_64V2:
+      SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
+      return tdesc_s390_linux64v2;
+    case S390_TDESC_TE:
+      SET_REGMAP(s390_te_linux64_ft_collect_regmap, 32);
+      return tdesc_s390_te_linux64;
+    case S390_TDESC_VX:
+      SET_REGMAP(s390_linux64_ft_collect_regmap, 0);
+      return tdesc_s390_vx_linux64;
+    case S390_TDESC_TEVX:
+      SET_REGMAP(s390_te_linux64_ft_collect_regmap, 0);
+      return tdesc_s390_tevx_linux64;
+#endif
+    default:
+      internal_error (__FILE__, __LINE__,
+		      "unknown ipa tdesc index: %d", idx);
+#ifdef __s390x__
+      return tdesc_s390x_linux64;
+#else
+      return tdesc_s390_linux32;
+#endif
+    }
+}
+
+void
+initialize_low_tracepoint (void)
+{
+#ifdef __s390x__
+  init_registers_s390x_linux64 ();
+  init_registers_s390x_linux64v1 ();
+  init_registers_s390x_linux64v2 ();
+  init_registers_s390x_te_linux64 ();
+  init_registers_s390x_vx_linux64 ();
+  init_registers_s390x_tevx_linux64 ();
+#else
+  init_registers_s390_linux32 ();
+  init_registers_s390_linux32v1 ();
+  init_registers_s390_linux32v2 ();
+  init_registers_s390_linux64 ();
+  init_registers_s390_linux64v1 ();
+  init_registers_s390_linux64v2 ();
+  init_registers_s390_te_linux64 ();
+  init_registers_s390_vx_linux64 ();
+  init_registers_s390_tevx_linux64 ();
+#endif
+}
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 2bcfa7a..146e4c9 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -27,6 +27,9 @@
 #include "nat/gdb_ptrace.h"
 #include <sys/uio.h>
 #include <elf.h>
+#include <inttypes.h>
+
+#include "linux-s390-tdesc.h"
 
 #ifndef HWCAP_S390_HIGH_GPRS
 #define HWCAP_S390_HIGH_GPRS 512
@@ -40,66 +43,6 @@
 #define HWCAP_S390_VX 2048
 #endif
 
-/* Defined in auto-generated file s390-linux32.c.  */
-void init_registers_s390_linux32 (void);
-extern const struct target_desc *tdesc_s390_linux32;
-
-/* Defined in auto-generated file s390-linux32v1.c.  */
-void init_registers_s390_linux32v1 (void);
-extern const struct target_desc *tdesc_s390_linux32v1;
-
-/* Defined in auto-generated file s390-linux32v2.c.  */
-void init_registers_s390_linux32v2 (void);
-extern const struct target_desc *tdesc_s390_linux32v2;
-
-/* Defined in auto-generated file s390-linux64.c.  */
-void init_registers_s390_linux64 (void);
-extern const struct target_desc *tdesc_s390_linux64;
-
-/* Defined in auto-generated file s390-linux64v1.c.  */
-void init_registers_s390_linux64v1 (void);
-extern const struct target_desc *tdesc_s390_linux64v1;
-
-/* Defined in auto-generated file s390-linux64v2.c.  */
-void init_registers_s390_linux64v2 (void);
-extern const struct target_desc *tdesc_s390_linux64v2;
-
-/* Defined in auto-generated file s390-te-linux64.c.  */
-void init_registers_s390_te_linux64 (void);
-extern const struct target_desc *tdesc_s390_te_linux64;
-
-/* Defined in auto-generated file s390-vx-linux64.c.  */
-void init_registers_s390_vx_linux64 (void);
-extern const struct target_desc *tdesc_s390_vx_linux64;
-
-/* Defined in auto-generated file s390-tevx-linux64.c.  */
-void init_registers_s390_tevx_linux64 (void);
-extern const struct target_desc *tdesc_s390_tevx_linux64;
-
-/* Defined in auto-generated file s390x-linux64.c.  */
-void init_registers_s390x_linux64 (void);
-extern const struct target_desc *tdesc_s390x_linux64;
-
-/* Defined in auto-generated file s390x-linux64v1.c.  */
-void init_registers_s390x_linux64v1 (void);
-extern const struct target_desc *tdesc_s390x_linux64v1;
-
-/* Defined in auto-generated file s390x-linux64v2.c.  */
-void init_registers_s390x_linux64v2 (void);
-extern const struct target_desc *tdesc_s390x_linux64v2;
-
-/* Defined in auto-generated file s390x-te-linux64.c.  */
-void init_registers_s390x_te_linux64 (void);
-extern const struct target_desc *tdesc_s390x_te_linux64;
-
-/* Defined in auto-generated file s390x-vx-linux64.c.  */
-void init_registers_s390x_vx_linux64 (void);
-extern const struct target_desc *tdesc_s390x_vx_linux64;
-
-/* Defined in auto-generated file s390x-tevx-linux64.c.  */
-void init_registers_s390x_tevx_linux64 (void);
-extern const struct target_desc *tdesc_s390x_tevx_linux64;
-
 #define s390_num_regs 52
 
 static int s390_regmap[] = {
@@ -539,6 +482,7 @@ s390_check_regset (int pid, int regset, int regsize)
 /* For a 31-bit inferior, whether the kernel supports using the full
    64-bit GPRs.  */
 static int have_hwcap_s390_high_gprs = 0;
+static int have_hwcap_s390_vx = 0;
 
 static void
 s390_arch_setup (void)
@@ -621,6 +565,8 @@ s390_arch_setup (void)
 	else
 	  tdesc = tdesc_s390_linux64;
       }
+
+    have_hwcap_s390_vx = have_regset_vxrs;
   }
 
   /* Update target_regsets according to available register sets.  */
@@ -753,6 +699,704 @@ s390_supports_tracepoints (void)
   return 1;
 }
 
+/* Implementation of linux_target_ops method "get_thread_area".  */
+
+static int
+s390_get_thread_area (int lwpid, CORE_ADDR *addrp)
+{
+  CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, (long) 0);
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  if (register_size (regcache->tdesc, 0) == 4)
+    res &= 0xffffffff;
+#endif
+  *addrp = res;
+  return 0;
+}
+
+
+/* Fast tracepoint support.
+
+   The register save area on stack is identical for all targets:
+
+   0x000+i*0x10: VR0-VR31
+   0x200+i*8: GR0-GR15
+   0x280+i*4: AR0-AR15
+   0x2c0: PSWM [64-bit]
+   0x2c8: PSWA [64-bit]
+   0x2d0: FPC
+
+   If we're on 31-bit linux, we just don't store the high parts of the GPRs.
+   Likewise, if there's no VX support, we just store the FRs into the slots
+   of low VR halves.  The agent code is responsible for rearranging that
+   into regcache.  */
+
+/* Code sequence saving GPRs for 31-bit target with no high GPRs.  There's
+   one trick used at the very beginning: since there's no way to allocate
+   stack space without destroying CC (lay instruction can do it, but it's
+   only supported on later CPUs), we take 4 different execution paths for
+   every possible value of CC, allocate stack space, save %r0, stuff the
+   CC value in %r0 (shifted to match its position in PSWM high word),
+   then branch to common path.  */
+
+static const unsigned char s390_ft_entry_gpr_esa[] = {
+  0xa7, 0x14, 0x00, 0x1e,		/* jo .Lcc3 */
+  0xa7, 0x24, 0x00, 0x14,		/* jh .Lcc2 */
+  0xa7, 0x44, 0x00, 0x0a,		/* jl .Lcc1 */
+  /* CC = 0 */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x00, 0x00,		/* lhi %r0, 0 */
+  0xa7, 0xf4, 0x00, 0x18,		/* j .Lccdone */
+  /* .Lcc1: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x10, 0x00,		/* lhi %r0, 0x1000 */
+  0xa7, 0xf4, 0x00, 0x10,		/* j .Lccdone */
+  /* .Lcc2: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x20, 0x00,		/* lhi %r0, 0x2000 */
+  0xa7, 0xf4, 0x00, 0x08,		/* j .Lccdone */
+  /* .Lcc3: */
+  0xa7, 0xfa, 0xfd, 0x00,		/* ahi %r15, -0x300 */
+  0x50, 0x00, 0xf2, 0x04,		/* st %r0, 0x204(%r15) */
+  0xa7, 0x08, 0x30, 0x00,		/* lhi %r0, 0x3000 */
+  /* .Lccdone: */
+  0x50, 0x10, 0xf2, 0x0c,		/* st %r1, 0x20c(%r15) */
+  0x50, 0x20, 0xf2, 0x14,		/* st %r2, 0x214(%r15) */
+  0x50, 0x30, 0xf2, 0x1c,		/* st %r3, 0x21c(%r15) */
+  0x50, 0x40, 0xf2, 0x24,		/* st %r4, 0x224(%r15) */
+  0x50, 0x50, 0xf2, 0x2c,		/* st %r5, 0x22c(%r15) */
+  0x50, 0x60, 0xf2, 0x34,		/* st %r6, 0x234(%r15) */
+  0x50, 0x70, 0xf2, 0x3c,		/* st %r7, 0x23c(%r15) */
+  0x50, 0x80, 0xf2, 0x44,		/* st %r8, 0x244(%r15) */
+  0x50, 0x90, 0xf2, 0x4c,		/* st %r9, 0x24c(%r15) */
+  0x50, 0xa0, 0xf2, 0x54,		/* st %r10, 0x254(%r15) */
+  0x50, 0xb0, 0xf2, 0x5c,		/* st %r11, 0x25c(%r15) */
+  0x50, 0xc0, 0xf2, 0x64,		/* st %r12, 0x264(%r15) */
+  0x50, 0xd0, 0xf2, 0x6c,		/* st %r13, 0x26c(%r15) */
+  0x50, 0xe0, 0xf2, 0x74,		/* st %r14, 0x274(%r15) */
+  /* Compute original value of %r15 and store it.  We use ahi instead
+     of la to preserve the whole value, and not just the low 31 bits.
+     This is not particularly important here, but essential in the
+     zarch case where someone might be using the high word of %r15
+     as an extra register.  */
+  0x18, 0x1f,				/* lr %r1, %r15 */
+  0xa7, 0x1a, 0x03, 0x00,		/* ahi %r1, 0x300 */
+  0x50, 0x10, 0xf2, 0x7c,		/* st %r1, 0x27c(%r15) */
+};
+
+/* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
+   target.  Same as above, except this time we can use load/store multiple,
+   since the 64-bit regs are tightly packed.  */
+
+static const unsigned char s390_ft_entry_gpr_zarch[] = {
+  0xa7, 0x14, 0x00, 0x21,		/* jo .Lcc3 */
+  0xa7, 0x24, 0x00, 0x16,		/* jh .Lcc2 */
+  0xa7, 0x44, 0x00, 0x0b,		/* jl .Lcc1 */
+  /* CC = 0 */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x00, 0x00,		/* lhi %r0, 0 */
+  0xa7, 0xf4, 0x00, 0x1b,		/* j .Lccdone */
+  /* .Lcc1: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x10, 0x00,		/* lhi %r0, 0x1000 */
+  0xa7, 0xf4, 0x00, 0x12,		/* j .Lccdone */
+  /* .Lcc2: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x20, 0x00,		/* lhi %r0, 0x2000 */
+  0xa7, 0xf4, 0x00, 0x09,		/* j .Lccdone */
+  /* .Lcc3: */
+  0xa7, 0xfb, 0xfd, 0x00,		/* aghi %r15, -0x300 */
+  0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24,	/* stmg %r0, %r14, 0x200(%r15) */
+  0xa7, 0x08, 0x30, 0x00,		/* lhi %r0, 0x3000 */
+  /* .Lccdone: */
+  0xb9, 0x04, 0x00, 0x1f,		/* lgr %r1, %r15 */
+  0xa7, 0x1b, 0x03, 0x00,		/* aghi %r1, 0x300 */
+  0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24,	/* stg %r1, 0x278(%r15) */
+};
+
+/* Code sequence saving ARs, PSWM and FPC.  PSWM has to be assembled from
+   current PSWM (read by epsw) and CC from entry (in %r0).  */
+
+static const unsigned char s390_ft_entry_misc[] = {
+  0x9b, 0x0f, 0xf2, 0x80,		/* stam %a0, %a15, 0x20(%%r15) */
+  0xb9, 0x8d, 0x00, 0x23,		/* epsw %r2, %r3 */
+  0xa7, 0x18, 0xcf, 0xff,		/* lhi %r1, ~0x3000 */
+  0x14, 0x21,				/* nr %r2, %r1 */
+  0x16, 0x20,				/* or %r2, %r0 */
+  0x50, 0x20, 0xf2, 0xc0,		/* st %r2, 0x2c0(%r15) */
+  0x50, 0x30, 0xf2, 0xc4,		/* st %r3, 0x2c4(%r15) */
+  0xb2, 0x9c, 0xf2, 0xd0,		/* stfpc 0x2d0(%r15) */
+};
+
+/* Code sequence saving FRs, used if VX not supported.  */
+
+static const unsigned char s390_ft_entry_fr[] = {
+  0x60, 0x00, 0xf0, 0x00,		/* std %f0, 0x000(%r15) */
+  0x60, 0x10, 0xf0, 0x10,		/* std %f1, 0x010(%r15) */
+  0x60, 0x20, 0xf0, 0x20,		/* std %f2, 0x020(%r15) */
+  0x60, 0x30, 0xf0, 0x30,		/* std %f3, 0x030(%r15) */
+  0x60, 0x40, 0xf0, 0x40,		/* std %f4, 0x040(%r15) */
+  0x60, 0x50, 0xf0, 0x50,		/* std %f5, 0x050(%r15) */
+  0x60, 0x60, 0xf0, 0x60,		/* std %f6, 0x060(%r15) */
+  0x60, 0x70, 0xf0, 0x70,		/* std %f7, 0x070(%r15) */
+  0x60, 0x80, 0xf0, 0x80,		/* std %f8, 0x080(%r15) */
+  0x60, 0x90, 0xf0, 0x90,		/* std %f9, 0x090(%r15) */
+  0x60, 0xa0, 0xf0, 0xa0,		/* std %f10, 0x0a0(%r15) */
+  0x60, 0xb0, 0xf0, 0xb0,		/* std %f11, 0x0b0(%r15) */
+  0x60, 0xc0, 0xf0, 0xc0,		/* std %f12, 0x0c0(%r15) */
+  0x60, 0xd0, 0xf0, 0xd0,		/* std %f13, 0x0d0(%r15) */
+  0x60, 0xe0, 0xf0, 0xe0,		/* std %f14, 0x0e0(%r15) */
+  0x60, 0xf0, 0xf0, 0xf0,		/* std %f15, 0x0f0(%r15) */
+};
+
+/* Code sequence saving VRs, used if VX not supported.  */
+
+static const unsigned char s390_ft_entry_vr[] = {
+  0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e,	/* vstm %v0, %v15, 0x000(%r15) */
+  0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e,	/* vstm %v16, %v31, 0x100(%r15) */
+};
+
+/* Code sequence doing the collection call for 31-bit target.  %r1 contains
+   the address of the literal pool.  */
+
+static const unsigned char s390_ft_main_31[] = {
+  /* Load the literals into registers.  */
+  0x58, 0x50, 0x10, 0x00,		/* l %r5, 0x0(%r1) */
+  0x58, 0x20, 0x10, 0x04,		/* l %r2, 0x4(%r1) */
+  0x58, 0x40, 0x10, 0x08,		/* l %r4, 0x8(%r1) */
+  0x58, 0x60, 0x10, 0x0c,		/* l %r6, 0xc(%r1) */
+  /* Save original PSWA (tracepoint address | 0x80000000).  */
+  0x50, 0x50, 0xf2, 0xcc,		/* st %r5, 0x2cc(%r15) */
+  /* Construct a collecting_t object at %r15+0x2e0.  */
+  0x50, 0x20, 0xf2, 0xe0,		/* st %r2, 0x2e0(%r15) */
+  0x9b, 0x00, 0xf2, 0xe4,		/* stam %a0, %a0, 0x2e4(%r15) */
+  /* Move its address to %r0.  */
+  0x41, 0x00, 0xf2, 0xe0,		/* la %r0, 0x2e0(%r15) */
+  /* Take the lock.  */
+  /* .Lloop:  */
+  0xa7, 0x18, 0x00, 0x00,		/* lhi %r1, 0 */
+  0xba, 0x10, 0x60, 0x00,		/* cs %r1, %r0, 0(%r6) */
+  0xa7, 0x74, 0xff, 0xfc,		/* jne .Lloop */
+  /* Address of the register save block to %r3.  */
+  0x18, 0x3f,				/* lr %r3, %r15 */
+  /* Make a stack frame, so that we can call the collector.  */
+  0xa7, 0xfa, 0xff, 0xa0,		/* ahi %r15, -0x60 */
+  /* Call it.  */
+  0x0d, 0xe4,				/* basr %r14, %r4 */
+  /* And get rid of the stack frame again.  */
+  0x41, 0xf0, 0xf0, 0x60,		/* la %r15, 0x60(%r15) */
+  /* Leave the lock.  */
+  0x07, 0xf0, 				/* br %r0 */
+  0xa7, 0x18, 0x00, 0x00,		/* lhi %r1, 0 */
+  0x50, 0x10, 0x60, 0x00,		/* st %t1, 0(%r6) */
+};
+
+/* Code sequence doing the collection call for 64-bit target.  %r1 contains
+   the address of the literal pool.  */
+
+static const unsigned char s390_ft_main_64[] = {
+  /* Load the literals into registers.  */
+  0xe3, 0x50, 0x10, 0x00, 0x00, 0x04,	/* lg %r5, 0x00(%r1) */
+  0xe3, 0x20, 0x10, 0x08, 0x00, 0x04,	/* lg %r2, 0x08(%r1) */
+  0xe3, 0x40, 0x10, 0x10, 0x00, 0x04,	/* lg %r4, 0x10(%r1) */
+  0xe3, 0x60, 0x10, 0x18, 0x00, 0x04,	/* lg %r6, 0x18(%r1) */
+  /* Save original PSWA (tracepoint address).  */
+  0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24,	/* stg %r5, 0x2c8(%r15) */
+  /* Construct a collecting_t object at %r15+0x2e0.  */
+  0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24,	/* stg %r2, 0x2e0(%r15) */
+  0x9b, 0x01, 0xf2, 0xe8,		/* stam %a0, %a1, 0x2e8(%r15) */
+  /* Move its address to %r0.  */
+  0x41, 0x00, 0xf2, 0xe0,		/* la %r0, 0x2e0(%r15) */
+  /* Take the lock.  */
+  /* .Lloop:  */
+  0xa7, 0x19, 0x00, 0x00,		/* lghi %r1, 0 */
+  0xeb, 0x10, 0x60, 0x00, 0x00, 0x30,	/* csg %r1, %r0, 0(%r6) */
+  0xa7, 0x74, 0xff, 0xfb,		/* jne .Lloop */
+  /* Address of the register save block to %r3.  */
+  0xb9, 0x04, 0x00, 0x3f,		/* lgr %r3, %r15 */
+  /* Make a stack frame, so that we can call the collector.  */
+  0xa7, 0xfb, 0xff, 0x60,		/* aghi %r15, -0xa0 */
+  /* Call it.  */
+  0x0d, 0xe4,				/* basr %r14, %r4 */
+  /* And get rid of the stack frame again.  */
+  0x41, 0xf0, 0xf0, 0xa0,		/* la %r15, 0xa0(%r15) */
+  /* Leave the lock.  */
+  0x07, 0xf0,				/* br %r0 */
+  0xa7, 0x19, 0x00, 0x00,		/* lghi %r1, 0 */
+  0xe3, 0x10, 0x60, 0x00, 0x00, 0x24,	/* stg %t1, 0(%r6) */
+};
+
+/* Code sequence restoring FRs, for targets with no VX support.  */
+
+static const unsigned char s390_ft_exit_fr[] = {
+  0x68, 0x00, 0xf0, 0x00,		/* ld %f0, 0x000(%r15) */
+  0x68, 0x10, 0xf0, 0x10,		/* ld %f1, 0x010(%r15) */
+  0x68, 0x20, 0xf0, 0x20,		/* ld %f2, 0x020(%r15) */
+  0x68, 0x30, 0xf0, 0x30,		/* ld %f3, 0x030(%r15) */
+  0x68, 0x40, 0xf0, 0x40,		/* ld %f4, 0x040(%r15) */
+  0x68, 0x50, 0xf0, 0x50,		/* ld %f5, 0x050(%r15) */
+  0x68, 0x60, 0xf0, 0x60,		/* ld %f6, 0x060(%r15) */
+  0x68, 0x70, 0xf0, 0x70,		/* ld %f7, 0x070(%r15) */
+  0x68, 0x80, 0xf0, 0x80,		/* ld %f8, 0x080(%r15) */
+  0x68, 0x90, 0xf0, 0x90,		/* ld %f9, 0x090(%r15) */
+  0x68, 0xa0, 0xf0, 0xa0,		/* ld %f10, 0x0a0(%r15) */
+  0x68, 0xb0, 0xf0, 0xb0,		/* ld %f11, 0x0b0(%r15) */
+  0x68, 0xc0, 0xf0, 0xc0,		/* ld %f12, 0x0c0(%r15) */
+  0x68, 0xd0, 0xf0, 0xd0,		/* ld %f13, 0x0d0(%r15) */
+  0x68, 0xe0, 0xf0, 0xe0,		/* ld %f14, 0x0e0(%r15) */
+  0x68, 0xf0, 0xf0, 0xf0,		/* ld %f15, 0x0f0(%r15) */
+};
+
+/* Code sequence restoring VRs.  */
+
+static const unsigned char s390_ft_exit_vr[] = {
+  0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36,	/* vlm %v0, %v15, 0x000(%r15) */
+  0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36,	/* vlm %v16, %v31, 0x100(%r15) */
+};
+
+/* Code sequence restoring misc registers.  As for PSWM, only CC should be
+   modified by C code, so we use the alr instruction to restore it by
+   manufacturing an operand that'll result in the original flags.  */
+
+static const unsigned char s390_ft_exit_misc[] = {
+  0xb2, 0x9d, 0xf2, 0xd0,		/* lfpc 0x2d0(%r15) */
+  0x58, 0x00, 0xf2, 0xc0,		/* l %r0, 0x2c0(%r15) */
+  /* Extract CC to high 2 bits of %r0.  */
+  0x88, 0x00, 0x00, 0x0c,		/* srl %r0, 12 */
+  0x89, 0x00, 0x00, 0x1e,		/* sll %r0, 30 */
+  /* Add %r0 to itself.  Result will be nonzero iff CC bit 0 is set, and
+     will have carry iff CC bit 1 is set - resulting in the same flags
+     as the original.  */
+  0x1e, 0x00,				/* alr %r0, %r0 */
+  0x9a, 0x0f, 0xf2, 0x80,		/* lam %a0, %a15, 0x280(%r15) */
+};
+
+/* Code sequence restoring GPRs, for 31-bit targets with no high GPRs.  */
+
+static const unsigned char s390_ft_exit_gpr_esa[] = {
+  0x58, 0x00, 0xf2, 0x04,		/* l %r0, 0x204(%r15) */
+  0x58, 0x10, 0xf2, 0x0c,		/* l %r1, 0x20c(%r15) */
+  0x58, 0x20, 0xf2, 0x14,		/* l %r2, 0x214(%r15) */
+  0x58, 0x30, 0xf2, 0x1c,		/* l %r3, 0x21c(%r15) */
+  0x58, 0x40, 0xf2, 0x24,		/* l %r4, 0x224(%r15) */
+  0x58, 0x50, 0xf2, 0x2c,		/* l %r5, 0x22c(%r15) */
+  0x58, 0x60, 0xf2, 0x34,		/* l %r6, 0x234(%r15) */
+  0x58, 0x70, 0xf2, 0x3c,		/* l %r7, 0x23c(%r15) */
+  0x58, 0x80, 0xf2, 0x44,		/* l %r8, 0x244(%r15) */
+  0x58, 0x90, 0xf2, 0x4c,		/* l %r9, 0x24c(%r15) */
+  0x58, 0xa0, 0xf2, 0x54,		/* l %r10, 0x254(%r15) */
+  0x58, 0xb0, 0xf2, 0x5c,		/* l %r11, 0x25c(%r15) */
+  0x58, 0xc0, 0xf2, 0x64,		/* l %r12, 0x264(%r15) */
+  0x58, 0xd0, 0xf2, 0x6c,		/* l %r13, 0x26c(%r15) */
+  0x58, 0xe0, 0xf2, 0x74,		/* l %r14, 0x274(%r15) */
+  0x58, 0xf0, 0xf2, 0x7c,		/* l %r15, 0x27c(%r15) */
+};
+
+/* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
+   with high GPRs.  */
+
+static const unsigned char s390_ft_exit_gpr_zarch[] = {
+  0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04,	/* lmg %r0, %r15, 0x200(%r15) */
+};
+
+/* Writes instructions to target, updating the to pointer.  */
+
+static void
+append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
+{
+  write_inferior_memory (*to, buf, len);
+  *to += len;
+}
+
+/* Relocates an instruction from oldloc to *to, updating to.  */
+
+static int
+s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
+{
+  gdb_byte buf[6];
+  int ilen;
+  int op2;
+  /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup.  */
+  int mode = 0;
+  int is_bras = 0;
+  read_inferior_memory (oldloc, buf, sizeof buf);
+  if (buf[0] < 0x40)
+    ilen = 2;
+  else if (buf[0] < 0xc0)
+    ilen = 4;
+  else
+    ilen = 6;
+  switch (buf[0])
+    {
+    case 0x05: /* BALR */
+    case 0x0c: /* BASSM */
+    case 0x0d: /* BASR */
+    case 0x45: /* BAL */
+    case 0x4d: /* BAS */
+      /* These save a return address and mess around with registers.
+	 We can't relocate them.  */
+      return 1;
+    case 0x84: /* BRXH */
+    case 0x85: /* BRXLE */
+      mode = 1;
+      break;
+    case 0xa7:
+      op2 = buf[1] & 0xf;
+      /* BRC, BRAS, BRCT, BRCTG */
+      if (op2 >= 4 && op2 <= 7)
+	mode = 1;
+      /* BRAS */
+      if (op2 == 5)
+	is_bras = 1;
+      break;
+    case 0xc0:
+      op2 = buf[1] & 0xf;
+      /* LARL, BRCL, BRASL */
+      if (op2 == 0 || op2 == 4 || op2 == 5)
+	mode = 2;
+      /* BRASL */
+      if (op2 == 5)
+	is_bras = 1;
+      break;
+    case 0xc4:
+    case 0xc6:
+      /* PC-relative addressing instructions.  */
+      mode = 2;
+      break;
+    case 0xc5: /* BPRP */
+    case 0xc7: /* BPP */
+      /* Branch prediction - just skip it.  */
+      return 0;
+    case 0xcc:
+      op2 = buf[1] & 0xf;
+      /* BRCTH */
+      if (op2 == 6)
+	mode = 2;
+      break;
+    case 0xec:
+      op2 = buf[5];
+      switch (op2)
+	{
+	case 0x44: /* BRXHG */
+	case 0x45: /* BRXLG */
+	case 0x64: /* CGRJ */
+	case 0x65: /* CLGRJ */
+	case 0x76: /* CRJ */
+	case 0x77: /* CLRJ */
+	  mode = 1;
+	  break;
+	}
+      break;
+    }
+
+  if (mode != 0)
+    {
+      /* We'll have to relocate an instruction with a PC-relative field.
+	 First, compute the target.  */
+      int64_t loffset = 0;
+      CORE_ADDR target;
+      if (mode == 1)
+	{
+	  int16_t soffset = 0;
+	  memcpy (&soffset, buf+2, 2);
+	  loffset = soffset;
+	}
+      else if (mode == 2)
+	{
+	  int32_t soffset = 0;
+	  memcpy (&soffset, buf+2, 4);
+	  loffset = soffset;
+	}
+      target = oldloc + loffset * 2;
+      if (!is_64)
+	target &= 0x7fffffff;
+
+      if (is_bras)
+	{
+	  /* BRAS or BRASL was used.  We cannot just relocate those, since
+	     they save the return address in a register.  We can, however,
+	     replace them with a LARL+JG sequence.  */
+
+	  /* Make the LARL.  */
+	  int32_t soffset;
+	  buf[0] = 0xc0;
+	  buf[1] &= 0xf0;
+	  loffset = oldloc + ilen - *to;
+	  loffset >>= 1;
+	  soffset = loffset;
+	  if (soffset != loffset && is_64)
+	    return 1;
+	  memcpy (buf+2, &soffset, 4);
+	  append_insns (to, 6, buf);
+
+	  /* XXX: this is not fully correct.  In 31-bit mode, LARL will write
+	     an address with the top bit 0, while BRAS/BRASL will write it
+	     with top bit 1.  It should not matter much, since linux compilers
+	     use BR and not BSM to return from functions, but it could confuse
+	     some poor stack unwinder.  */
+
+	  /* We'll now be writing a JG.  */
+	  mode = 2;
+	  buf[0] = 0xc0;
+	  buf[1] = 0xf4;
+	  ilen = 6;
+	}
+
+      /* Compute the new offset and write it to the buffer.  */
+      loffset = target - *to;
+      loffset >>= 1;
+
+      if (mode == 1)
+	{
+	  int16_t soffset = loffset;
+	  if (soffset != loffset)
+	    return 1;
+	  memcpy (buf+2, &soffset, 2);
+	}
+      else if (mode == 2)
+	{
+	  int32_t soffset = loffset;
+	  if (soffset != loffset && is_64)
+	    return 1;
+	  memcpy (buf+2, &soffset, 4);
+	}
+    }
+  append_insns (to, ilen, buf);
+  return 0;
+}
+
+/* Implementation of linux_target_ops method
+   "install_fast_tracepoint_jump_pad".  */
+
+static int
+s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
+				       CORE_ADDR tpaddr,
+				       CORE_ADDR collector,
+				       CORE_ADDR lockaddr,
+				       ULONGEST orig_size,
+				       CORE_ADDR *jump_entry,
+				       CORE_ADDR *trampoline,
+				       ULONGEST *trampoline_size,
+				       unsigned char *jjump_pad_insn,
+				       ULONGEST *jjump_pad_insn_size,
+				       CORE_ADDR *adjusted_insn_addr,
+				       CORE_ADDR *adjusted_insn_addr_end,
+				       char *err)
+{
+  int i;
+  int64_t loffset;
+  int32_t offset;
+  unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 };	/* jg ... */
+  CORE_ADDR buildaddr = *jump_entry;
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  int is_64 = register_size (regcache->tdesc, 0) == 8;
+  int is_zarch = is_64 || have_hwcap_s390_high_gprs;
+  int has_vx = have_hwcap_s390_vx;
+#else
+  int is_64 = 0, is_zarch = 0, has_vx = 0;
+#endif
+  CORE_ADDR literals[4] = {
+    tpaddr,
+    tpoint,
+    collector,
+    lockaddr,
+  };
+
+  /* First, store the GPRs.  */
+  if (!is_zarch)
+    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa, s390_ft_entry_gpr_esa);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch, s390_ft_entry_gpr_zarch);
+
+  /* Second, misc registers (ARs, PSWM, FPC).  PSWA will be stored below.  */
+  append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
+
+  /* Third, FRs or VRs.  */
+  if (!has_vx)
+    append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
+
+  /* Now, the main part of code - store PSWA, take lock, call collector,
+     leave lock.  First, we'll need to fetch 4 literals.  */
+  if (!is_64) {
+    unsigned char buf[] = {
+      0x07, 0x07,		/* nopr %r7 */
+      0xa7, 0x15, 0x00, 0x0a,	/* bras %r1, .Lend */
+      0, 0, 0, 0,		/* tpaddr */
+      0, 0, 0, 0,		/* tpoint */
+      0, 0, 0, 0,		/* collector */
+      0, 0, 0, 0,		/* lockaddr */
+      /* .Lend: */
+    };
+    /* Find the proper start place in buf, so that literals will be
+       aligned. */
+    int bufpos = (buildaddr + 2) & 3;
+    /* First literal will be saved as the PSWA, make sure it has the high bit
+       set.  */
+    literals[0] |= 0x80000000;
+    /* Stuff the literals into the buffer. */
+    for (i = 0; i < 4; i++) {
+      uint32_t lit = literals[i];
+      memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
+    }
+    append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
+    append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
+  } else {
+    unsigned char buf[] = {
+      0x07, 0x07,		/* nopr %r7 */
+      0x07, 0x07,		/* nopr %r7 */
+      0x07, 0x07,		/* nopr %r7 */
+      0xa7, 0x15, 0x00, 0x12,	/* bras %r1, .Lend */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* tpaddr */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* tpoint */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* collector */
+      0, 0, 0, 0, 0, 0, 0, 0,	/* lockaddr */
+      /* .Lend: */
+    };
+    /* Find the proper start place in buf, so that literals will be
+       aligned. */
+    int bufpos = (buildaddr + 2) & 7;
+    /* Stuff the literals into the buffer. */
+    for (i = 0; i < 4; i++) {
+      uint64_t lit = literals[i];
+      memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
+    }
+    append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
+    append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
+  }
+
+  /* Restore FRs or VRs.  */
+  if (!has_vx)
+    append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
+
+  /* Restore misc registers.  */
+  append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
+
+  /* Restore the GPRs.  */
+  if (!is_zarch)
+    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa, s390_ft_exit_gpr_esa);
+  else
+    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch, s390_ft_exit_gpr_zarch);
+
+  /* Now, adjust the original instruction to execute in the jump
+     pad.  */
+  *adjusted_insn_addr = buildaddr;
+  if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
+    {
+      sprintf (err, "E.Could not relocate instruction for tracepoint.");
+      return 1;
+    }
+  *adjusted_insn_addr_end = buildaddr;
+
+  /* Finally, write a jump back to the program.  */
+
+  loffset = (tpaddr + orig_size) - buildaddr;
+  loffset >>= 1;
+  offset = loffset;
+  if (is_64 && offset != loffset)
+    {
+      sprintf (err,
+	       "E.Jump back from jump pad too far from tracepoint "
+	       "(offset 0x%" PRIx64 " > int33).", loffset);
+      return 1;
+    }
+  memcpy (jbuf + 2, &offset, 4);
+  append_insns (&buildaddr, sizeof jbuf, jbuf);
+
+  /* The jump pad is now built.  Wire in a jump to our jump pad.  This
+     is always done last (by our caller actually), so that we can
+     install fast tracepoints with threads running.  This relies on
+     the agent's atomic write support.  */
+  loffset = *jump_entry - tpaddr;
+  loffset >>= 1;
+  offset = loffset;
+  if (is_64 && offset != loffset)
+    {
+      sprintf (err,
+	       "E.Jump back from jump pad too far from tracepoint "
+	       "(offset 0x%" PRIx64 " > int33).", loffset);
+      return 1;
+    }
+  memcpy (jbuf + 2, &offset, 4);
+  memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
+  *jjump_pad_insn_size = sizeof jbuf;
+
+  /* Return the end address of our pad.  */
+  *jump_entry = buildaddr;
+
+  return 0;
+}
+
+/* Implementation of linux_target_ops method
+   "get_min_fast_tracepoint_insn_len".  */
+
+static int
+s390_get_min_fast_tracepoint_insn_len (void)
+{
+  /* We only support using 6-byte jumps to reach the tracepoint code.
+     If the tracepoint buffer were allocated sufficiently close (64kiB)
+     to the executable code, and the traced instruction itself was close
+     enough to the beginning, we could use 4-byte jumps, but this doesn't
+     seem to be worth the effort.  */
+  return 6;
+}
+
+/* Implementation of linux_target_ops method "get_ipa_tdesc_idx".  */
+
+static int
+s390_get_ipa_tdesc_idx (void)
+{
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  const struct target_desc *tdesc = regcache->tdesc;
+
+#ifdef __s390x__
+  if (tdesc == tdesc_s390x_linux64)
+    return S390_TDESC_64;
+  if (tdesc == tdesc_s390x_linux64v1)
+    return S390_TDESC_64V1;
+  if (tdesc == tdesc_s390x_linux64v2)
+    return S390_TDESC_64V2;
+  if (tdesc == tdesc_s390x_te_linux64)
+    return S390_TDESC_TE;
+  if (tdesc == tdesc_s390x_vx_linux64)
+    return S390_TDESC_VX;
+  if (tdesc == tdesc_s390x_tevx_linux64)
+    return S390_TDESC_TEVX;
+#endif
+
+  if (tdesc == tdesc_s390_linux32)
+    return S390_TDESC_32;
+  if (tdesc == tdesc_s390_linux32v1)
+    return S390_TDESC_32V1;
+  if (tdesc == tdesc_s390_linux32v2)
+    return S390_TDESC_32V2;
+  if (tdesc == tdesc_s390_linux64)
+    return S390_TDESC_64;
+  if (tdesc == tdesc_s390_linux64v1)
+    return S390_TDESC_64V1;
+  if (tdesc == tdesc_s390_linux64v2)
+    return S390_TDESC_64V2;
+  if (tdesc == tdesc_s390_te_linux64)
+    return S390_TDESC_TE;
+  if (tdesc == tdesc_s390_vx_linux64)
+    return S390_TDESC_VX;
+  if (tdesc == tdesc_s390_tevx_linux64)
+    return S390_TDESC_TEVX;
+
+  return 0;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -780,13 +1424,15 @@ struct linux_target_ops the_low_target = {
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
   s390_supports_tracepoints,
-  NULL, /* get_thread_area */
-  NULL, /* install_fast_tracepoint_jump_pad */
+  s390_get_thread_area,
+  s390_install_fast_tracepoint_jump_pad,
   NULL, /* emit_ops */
-  NULL, /* get_min_fast_tracepoint_insn_len */
+  s390_get_min_fast_tracepoint_insn_len,
   NULL, /* supports_range_stepping */
   NULL, /* breakpoint_kind_from_current_state */
   s390_supports_hardware_single_step,
+  NULL, /* get_syscall_trapinfo */
+  s390_get_ipa_tdesc_idx,
 };
 
 void
@@ -803,12 +1449,14 @@ initialize_low_arch (void)
   init_registers_s390_te_linux64 ();
   init_registers_s390_vx_linux64 ();
   init_registers_s390_tevx_linux64 ();
+#ifdef __s390x__
   init_registers_s390x_linux64 ();
   init_registers_s390x_linux64v1 ();
   init_registers_s390x_linux64v2 ();
   init_registers_s390x_te_linux64 ();
   init_registers_s390x_vx_linux64 ();
   init_registers_s390x_tevx_linux64 ();
+#endif
 
   initialize_regsets_info (&s390_regsets_info);
   initialize_regsets_info (&s390_regsets_info_3264);
diff --git a/gdb/gdbserver/linux-s390-tdesc.h b/gdb/gdbserver/linux-s390-tdesc.h
new file mode 100644
index 0000000..501cc88
--- /dev/null
+++ b/gdb/gdbserver/linux-s390-tdesc.h
@@ -0,0 +1,102 @@
+/* Low level support for s390, shared between gdbserver and IPA.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+/* Note: since IPA obviously knows what ABI it's running on (s390 vs s390x),
+   it's sufficient to pass only the register set here.  This, together with
+   the ABI known at IPA compile time, maps to a tdesc.  */
+
+enum s390_linux_tdesc {
+  S390_TDESC_32,
+  S390_TDESC_32V1,
+  S390_TDESC_32V2,
+  S390_TDESC_64,
+  S390_TDESC_64V1,
+  S390_TDESC_64V2,
+  S390_TDESC_TE,
+  S390_TDESC_VX,
+  S390_TDESC_TEVX,
+};
+
+#ifdef __s390x__
+
+/* Defined in auto-generated file s390x-linux64.c.  */
+void init_registers_s390x_linux64 (void);
+extern const struct target_desc *tdesc_s390x_linux64;
+
+/* Defined in auto-generated file s390x-linux64v1.c.  */
+void init_registers_s390x_linux64v1 (void);
+extern const struct target_desc *tdesc_s390x_linux64v1;
+
+/* Defined in auto-generated file s390x-linux64v2.c.  */
+void init_registers_s390x_linux64v2 (void);
+extern const struct target_desc *tdesc_s390x_linux64v2;
+
+/* Defined in auto-generated file s390x-te-linux64.c.  */
+void init_registers_s390x_te_linux64 (void);
+extern const struct target_desc *tdesc_s390x_te_linux64;
+
+/* Defined in auto-generated file s390x-vx-linux64.c.  */
+void init_registers_s390x_vx_linux64 (void);
+extern const struct target_desc *tdesc_s390x_vx_linux64;
+
+/* Defined in auto-generated file s390x-tevx-linux64.c.  */
+void init_registers_s390x_tevx_linux64 (void);
+extern const struct target_desc *tdesc_s390x_tevx_linux64;
+
+#endif
+
+#if !defined __s390x__ || !defined IN_PROCESS_AGENT
+
+/* Defined in auto-generated file s390-linux32.c.  */
+void init_registers_s390_linux32 (void);
+extern const struct target_desc *tdesc_s390_linux32;
+
+/* Defined in auto-generated file s390-linux32v1.c.  */
+void init_registers_s390_linux32v1 (void);
+extern const struct target_desc *tdesc_s390_linux32v1;
+
+/* Defined in auto-generated file s390-linux32v2.c.  */
+void init_registers_s390_linux32v2 (void);
+extern const struct target_desc *tdesc_s390_linux32v2;
+
+/* Defined in auto-generated file s390-linux64.c.  */
+void init_registers_s390_linux64 (void);
+extern const struct target_desc *tdesc_s390_linux64;
+
+/* Defined in auto-generated file s390-linux64v1.c.  */
+void init_registers_s390_linux64v1 (void);
+extern const struct target_desc *tdesc_s390_linux64v1;
+
+/* Defined in auto-generated file s390-linux64v2.c.  */
+void init_registers_s390_linux64v2 (void);
+extern const struct target_desc *tdesc_s390_linux64v2;
+
+/* Defined in auto-generated file s390-te-linux64.c.  */
+void init_registers_s390_te_linux64 (void);
+extern const struct target_desc *tdesc_s390_te_linux64;
+
+/* Defined in auto-generated file s390-vx-linux64.c.  */
+void init_registers_s390_vx_linux64 (void);
+extern const struct target_desc *tdesc_s390_vx_linux64;
+
+/* Defined in auto-generated file s390-tevx-linux64.c.  */
+void init_registers_s390_tevx_linux64 (void);
+extern const struct target_desc *tdesc_s390_tevx_linux64;
+
+#endif
-- 
2.7.1

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

* [PATCH v2] gdbserver/s390: Add support for compiled agent expressions.
  2016-01-24 12:12 ` [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions Marcin Kościelnicki
@ 2016-03-04 10:41   ` Marcin Kościelnicki
  2016-03-14 16:19     ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-04 10:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

These sequences assume a z900+ CPU, like the rest of fast tracepoint
support.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (add_insns): New function.
	(s390_emit_prologue): New function.
	(s390_emit_epilogue): New function.
	(s390_emit_add): New function.
	(s390_emit_sub): New function.
	(s390_emit_mul): New function.
	(s390_emit_lsh): New function.
	(s390_emit_rsh_signed): New function.
	(s390_emit_rsh_unsigned): New function.
	(s390_emit_ext): New function.
	(s390_emit_log_not): New function.
	(s390_emit_bit_and): New function.
	(s390_emit_bit_or): New function.
	(s390_emit_bit_xor): New function.
	(s390_emit_bit_not): New function.
	(s390_emit_equal): New function.
	(s390_emit_less_signed): New function.
	(s390_emit_less_unsigned): New function.
	(s390_emit_ref): New function.
	(s390_emit_if_goto): New function.
	(s390_emit_goto): New function.
	(s390_write_goto_address): New function.
	(s390_emit_litpool): New function.
	(s390_emit_const): New function.
	(s390_emit_call): New function.
	(s390_emit_reg): New function.
	(s390_emit_pop): New function.
	(s390_emit_stack_flush): New function.
	(s390_emit_zero_ext): New function.
	(s390_emit_swap): New function.
	(s390_emit_stack_adjust): New function.
	(s390_emit_set_r2): New function.
	(s390_emit_int_call_1): New function.
	(s390_emit_void_call_2): New function.
	(s390_emit_eq_goto): New function.
	(s390_emit_ne_goto): New function.
	(s390_emit_lt_goto): New function.
	(s390_emit_le_goto): New function.
	(s390_emit_gt_goto): New function.
	(s390_emit_ge_goto): New function.
	(s390x_emit_prologue): New function.
	(s390x_emit_epilogue): New function.
	(s390x_emit_add): New function.
	(s390x_emit_sub): New function.
	(s390x_emit_mul): New function.
	(s390x_emit_lsh): New function.
	(s390x_emit_rsh_signed): New function.
	(s390x_emit_rsh_unsigned): New function.
	(s390x_emit_ext): New function.
	(s390x_emit_log_not): New function.
	(s390x_emit_bit_and): New function.
	(s390x_emit_bit_or): New function.
	(s390x_emit_bit_xor): New function.
	(s390x_emit_bit_not): New function.
	(s390x_emit_equal): New function.
	(s390x_emit_less_signed): New function.
	(s390x_emit_less_unsigned): New function.
	(s390x_emit_ref): New function.
	(s390x_emit_if_goto): New function.
	(s390x_emit_const): New function.
	(s390x_emit_call): New function.
	(s390x_emit_reg): New function.
	(s390x_emit_pop): New function.
	(s390x_emit_stack_flush): New function.
	(s390x_emit_zero_ext): New function.
	(s390x_emit_swap): New function.
	(s390x_emit_stack_adjust): New function.
	(s390x_emit_int_call_1): New function.
	(s390x_emit_void_call_2): New function.
	(s390x_emit_eq_goto): New function.
	(s390x_emit_ne_goto): New function.
	(s390x_emit_lt_goto): New function.
	(s390x_emit_le_goto): New function.
	(s390x_emit_gt_goto): New function.
	(s390x_emit_ge_goto): New function.
	(s390_emit_ops): New function.
	(struct linux_target_ops): Fill in emit_ops hook.
---
Updated version: deduplicated s390_emit_goto with s390x_emit_goto,
documentation comments, indent fixes.

 gdb/gdbserver/ChangeLog        |   80 +++
 gdb/gdbserver/linux-s390-low.c | 1346 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 1425 insertions(+), 1 deletion(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 6ff94b1..df010ab 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,85 @@
 2016-03-04  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* linux-s390-low.c (add_insns): New function.
+	(s390_emit_prologue): New function.
+	(s390_emit_epilogue): New function.
+	(s390_emit_add): New function.
+	(s390_emit_sub): New function.
+	(s390_emit_mul): New function.
+	(s390_emit_lsh): New function.
+	(s390_emit_rsh_signed): New function.
+	(s390_emit_rsh_unsigned): New function.
+	(s390_emit_ext): New function.
+	(s390_emit_log_not): New function.
+	(s390_emit_bit_and): New function.
+	(s390_emit_bit_or): New function.
+	(s390_emit_bit_xor): New function.
+	(s390_emit_bit_not): New function.
+	(s390_emit_equal): New function.
+	(s390_emit_less_signed): New function.
+	(s390_emit_less_unsigned): New function.
+	(s390_emit_ref): New function.
+	(s390_emit_if_goto): New function.
+	(s390_emit_goto): New function.
+	(s390_write_goto_address): New function.
+	(s390_emit_litpool): New function.
+	(s390_emit_const): New function.
+	(s390_emit_call): New function.
+	(s390_emit_reg): New function.
+	(s390_emit_pop): New function.
+	(s390_emit_stack_flush): New function.
+	(s390_emit_zero_ext): New function.
+	(s390_emit_swap): New function.
+	(s390_emit_stack_adjust): New function.
+	(s390_emit_set_r2): New function.
+	(s390_emit_int_call_1): New function.
+	(s390_emit_void_call_2): New function.
+	(s390_emit_eq_goto): New function.
+	(s390_emit_ne_goto): New function.
+	(s390_emit_lt_goto): New function.
+	(s390_emit_le_goto): New function.
+	(s390_emit_gt_goto): New function.
+	(s390_emit_ge_goto): New function.
+	(s390x_emit_prologue): New function.
+	(s390x_emit_epilogue): New function.
+	(s390x_emit_add): New function.
+	(s390x_emit_sub): New function.
+	(s390x_emit_mul): New function.
+	(s390x_emit_lsh): New function.
+	(s390x_emit_rsh_signed): New function.
+	(s390x_emit_rsh_unsigned): New function.
+	(s390x_emit_ext): New function.
+	(s390x_emit_log_not): New function.
+	(s390x_emit_bit_and): New function.
+	(s390x_emit_bit_or): New function.
+	(s390x_emit_bit_xor): New function.
+	(s390x_emit_bit_not): New function.
+	(s390x_emit_equal): New function.
+	(s390x_emit_less_signed): New function.
+	(s390x_emit_less_unsigned): New function.
+	(s390x_emit_ref): New function.
+	(s390x_emit_if_goto): New function.
+	(s390x_emit_const): New function.
+	(s390x_emit_call): New function.
+	(s390x_emit_reg): New function.
+	(s390x_emit_pop): New function.
+	(s390x_emit_stack_flush): New function.
+	(s390x_emit_zero_ext): New function.
+	(s390x_emit_swap): New function.
+	(s390x_emit_stack_adjust): New function.
+	(s390x_emit_int_call_1): New function.
+	(s390x_emit_void_call_2): New function.
+	(s390x_emit_eq_goto): New function.
+	(s390x_emit_ne_goto): New function.
+	(s390x_emit_lt_goto): New function.
+	(s390x_emit_le_goto): New function.
+	(s390x_emit_gt_goto): New function.
+	(s390x_emit_ge_goto): New function.
+	(s390_emit_ops): New function.
+	(struct linux_target_ops): Fill in emit_ops hook.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* Makefile.in: Add s390 IPA files.
 	* configure.srv: Build IPA for s390.
 	* linux-s390-ipa.c: New file.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 146e4c9..f0d76f0 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -22,6 +22,8 @@
 #include "server.h"
 #include "linux-low.h"
 #include "elf/common.h"
+#include "ax.h"
+#include "tracepoint.h"
 
 #include <asm/ptrace.h>
 #include "nat/gdb_ptrace.h"
@@ -1397,6 +1399,1348 @@ s390_get_ipa_tdesc_idx (void)
   return 0;
 }
 
+/* Appends given buffer to current_insn_ptr in the target.  */
+
+static void
+add_insns (const unsigned char *start, int len)
+{
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  if (debug_threads)
+    debug_printf ("Adding %d bytes of insn at %s\n",
+		  len, paddress (buildaddr));
+
+  append_insns (&buildaddr, len, start);
+  current_insn_ptr = buildaddr;
+}
+
+/* Register usage in emit:
+
+   - %r0, %r1: temp
+   - %r2: top of stack (high word for 31-bit)
+   - %r3: low word of top of stack (for 31-bit)
+   - %r4, %r5: temp
+   - %r6, %r7, %r8: don't use
+   - %r9: saved arg1
+   - %r10: saved arg2
+   - %r11: frame pointer
+   - %r12: saved top of stack for void_call_2 (high word for 31-bit)
+   - %r13: low word of saved top of stack (for 31-bit)
+   - %r14: return address for calls
+   - %r15: stack pointer
+
+  */
+
+/* The "emit_prologue" emit_ops method for s390.  */
+
+static void
+s390_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x9f, 0xf0, 0x24,		/* stm %r9, %r15, 0x24(%r15) */
+    0x18, 0x92,				/* lr %r9, %r2 */
+    0x18, 0xa3,				/* lr %r10, %r3 */
+    0x18, 0xbf,				/* lr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_epilogue" emit_ops method for s390.  */
+
+static void
+s390_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x23, 0xa0, 0x00,		/* stm %r2, %r3, 0(%r10) */
+    0xa7, 0x28, 0x00, 0x00,		/* lhi %r2, 0 */
+    0x98, 0x9f, 0xb0, 0x24,		/* lm %r9, %r15, 0x24(%r11) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_add" emit_ops method for s390.  */
+
+static void
+s390_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0x5e, 0x30, 0xf0, 0x04,		/* al %r3, 4(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98,	/* al %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_sub" emit_ops method for s390.  */
+
+static void
+s390_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x1f, 0x53,			/* slr %r5, %r3 */
+    0xb9, 0x99, 0x00, 0x42,	/* slbr %r4, %r2 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+    0x18, 0x35,			/* lr %r3, %r5 */
+    0x18, 0x24,			/* lr %r2, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_mul" emit_ops method for s390.  */
+
+static void
+s390_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+/* The "emit_lsh" emit_ops method for s390.  */
+
+static void
+s390_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8d, 0x20, 0x40, 0x00,	/* sldl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_signed" emit_ops method for s390.  */
+
+static void
+s390_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8e, 0x20, 0x40, 0x00,	/* srda %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_unsigned" emit_ops method for s390.  */
+
+static void
+s390_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8c, 0x20, 0x40, 0x00,	/* srdl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ext" emit_ops method for s390.  */
+
+static void
+s390_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8e, 0x20, 0x00, 64-arg,	/* srda %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_log_not" emit_ops method for s390.  */
+
+static void
+s390_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,			/* or %r2, %r3 */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0x74, 0x00, 0x04,	/* jne .Lskip */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lskip: */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_and" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0x54, 0x20, 0xf0, 0x00,	/* n %r2, 0(%r15) */
+    0x54, 0x30, 0xf0, 0x04,	/* n %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_or" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0x56, 0x20, 0xf0, 0x00,	/* o %r2, 0(%r15) */
+    0x56, 0x30, 0xf0, 0x04,	/* o %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_xor" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,	/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,	/* x %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_not" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x48, 0xff, 0xff,	/* lhi %r4, -1 */
+    0x17, 0x24,			/* xr %r2, %r4 */
+    0x17, 0x34,			/* xr %r3, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_equal" emit_ops method for s390.  */
+
+static void
+s390_emit_equal (void)
+{
+  s390_emit_bit_xor ();
+  s390_emit_log_not ();
+}
+
+/* The "emit_less_signed" emit_ops method for s390.  */
+
+static void
+s390_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,	/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_less_unsigned" emit_ops method for s390.  */
+
+static void
+s390_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x55, 0x20, 0xf0, 0x00,	/* cl %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ref" emit_ops method for s390.  */
+
+static void
+s390_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x43, 0x30, 0x30, 0x00,	/* ic %r3, 0(%r3) */
+  };
+  static const unsigned char buf2[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x48, 0x30, 0x30, 0x00,	/* lh %r3, 0(%r3) */
+  };
+  static const unsigned char buf4[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x58, 0x30, 0x30, 0x00,	/* l %r3, 0(%r3) */
+  };
+  static const unsigned char buf8[] = {
+    0x98, 0x23, 0x30, 0x00,	/* lm %r2, %r3, 0(%r3) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* The "emit_if_goto" emit_ops method for s390.  */
+
+static void
+s390_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x00,		/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_goto" emit_ops method for s390 and s390x.  */
+
+static void
+s390_emit_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 2;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "write_goto_address" emit_ops method for s390 and s390x.  */
+
+static void
+s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  long diff = ((long) (to - (from - 2))) / 2;
+  int sdiff = diff;
+  unsigned char buf[sizeof sdiff];
+
+  /* We're only doing 4-byte sizes at the moment.  */
+  if (size != sizeof sdiff || sdiff != diff)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  memcpy (buf, &sdiff, sizeof sdiff);
+  write_inferior_memory (from, buf, sizeof sdiff);
+}
+
+/* Preparation for emitting a literal pool of given size.  Loads the address
+   of the pool into %r1, and jumps over it.  Called should emit the pool data
+   immediately afterwards.  Used for both s390 and s390x.  */
+
+static void
+s390_emit_litpool (int size)
+{
+  static const unsigned char nop[] = {
+    0x07, 0x07,
+  };
+  unsigned char buf[] = {
+    0xa7, 0x15, 0x00, (size + 4) / 2,	/* bras %r1, .Lend+size */
+    /* .Lend: */
+  };
+  if (size == 4)
+    {
+      /* buf needs to start at even halfword for litpool to be aligned */
+      if (current_insn_ptr & 2)
+	add_insns (nop, sizeof nop);
+    }
+  else
+    {
+      while ((current_insn_ptr & 6) != 4)
+	add_insns (nop, sizeof nop);
+    }
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_const" emit_ops method for s390.  */
+
+static void
+s390_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x38, num >> 8, num,	/* lhi %r3, <num> */
+    0x17, 0x22,			/* xr %r2, %r2 */
+  };
+  static const unsigned char buf_l[] = {
+    0x98, 0x23, 0x10, 0x00,	/* lm %r2, %r3, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= 0)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_call" emit_ops method for s390.  */
+
+static void
+s390_emit_call (CORE_ADDR fn)
+{
+  unsigned int n = fn;
+  static const unsigned char buf[] = {
+    0x58, 0x10, 0x10, 0x00,	/* l %r1, 0(%r1) */
+    0xa7, 0xfa, 0xff, 0xa0,	/* ahi %r15, -0x60 */
+    0x0d, 0xe1,			/* basr %r14, %r1 */
+    0xa7, 0xfa, 0x00, 0x60,	/* ahi %r15, 0x60 */
+  };
+  s390_emit_litpool (4);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_reg" emit_ops method for s390.  */
+
+static void
+s390_emit_reg (int reg)
+{
+  unsigned char bufpre[] = {
+    0x18, 0x29,			/* lr %r2, %r9 */
+    0xa7, 0x38, reg >> 8, reg,	/* lhi %r3, <reg> */
+  };
+  add_insns (bufpre, sizeof bufpre);
+  s390_emit_call (get_raw_reg_func_addr ());
+}
+
+/* The "emit_pop" emit_ops method for s390.  */
+
+static void
+s390_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_flush" emit_ops method for s390.  */
+
+static void
+s390_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfa, 0xff, 0xf8,	/* ahi %r15, -8 */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_zero_ext" emit_ops method for s390.  */
+
+static void
+s390_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8c, 0x20, 0x00, 64-arg,	/* srdl %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_swap" emit_ops method for s390.  */
+
+static void
+s390_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+    0x18, 0x24,			/* lr %r2, %r4 */
+    0x18, 0x35,			/* lr %r3, %r5 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_adjust" emit_ops method for s390.  */
+
+static void
+s390_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfa, n * 8 >> 8, n * 8,	/* ahi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* Sets %r2 to a 32-bit constant.  */
+
+static void
+s390_emit_set_r2 (int arg1)
+{
+  unsigned char buf_s[] = {
+    0xa7, 0x28, arg1 >> 8, arg1,	/* lhi %r2, <arg1> */
+  };
+  static const unsigned char buf_l[] = {
+    0x58, 0x20, 0x10, 0x00,	/* l %r2, 0(%r1) */
+  };
+  if (arg1 < 0x8000 && arg1 >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (4);
+    add_insns ((unsigned char *) &arg1, sizeof arg1);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_int_call_1" emit_ops method for s390.  */
+
+static void
+s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `LONGEST(*fn)(int)'.  */
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+}
+
+/* The "emit_void_call_2" emit_ops method for s390.  */
+
+static void
+s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+  static const unsigned char buf[] = {
+    0x18, 0xc2,			/* lr %r12, %r2 */
+    0x18, 0xd3,			/* lr %r13, %r3 */
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x18, 0x32,			/* lr %r3, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0x18, 0x2c,			/* lr %r2, %r12 */
+    0x18, 0x3d,			/* lr %r3, %r13 */
+  };
+  add_insns (buf, sizeof buf);
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+/* The "emit_eq_goto" emit_ops method for s390.  */
+
+void
+s390_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ne_goto" emit_ops method for s390.  */
+
+void
+s390_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_lt_goto" emit_ops method for s390.  */
+
+void
+s390_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x08,		/* jh .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_le_goto" emit_ops method for s390.  */
+
+void
+s390_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xa4, 0x00, 0x08,		/* jhe .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_gt_goto" emit_ops method for s390.  */
+
+void
+s390_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x44, 0x00, 0x08,		/* jl .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ge_goto" emit_ops method for s390.  */
+
+void
+s390_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xc4, 0x00, 0x08,		/* jle .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ops" structure for s390.  Named _impl to avoid name
+   collision with s390_emit_ops function.  */
+
+struct emit_ops s390_emit_ops_impl =
+  {
+    s390_emit_prologue,
+    s390_emit_epilogue,
+    s390_emit_add,
+    s390_emit_sub,
+    s390_emit_mul,
+    s390_emit_lsh,
+    s390_emit_rsh_signed,
+    s390_emit_rsh_unsigned,
+    s390_emit_ext,
+    s390_emit_log_not,
+    s390_emit_bit_and,
+    s390_emit_bit_or,
+    s390_emit_bit_xor,
+    s390_emit_bit_not,
+    s390_emit_equal,
+    s390_emit_less_signed,
+    s390_emit_less_unsigned,
+    s390_emit_ref,
+    s390_emit_if_goto,
+    s390_emit_goto,
+    s390_write_goto_address,
+    s390_emit_const,
+    s390_emit_call,
+    s390_emit_reg,
+    s390_emit_pop,
+    s390_emit_stack_flush,
+    s390_emit_zero_ext,
+    s390_emit_swap,
+    s390_emit_stack_adjust,
+    s390_emit_int_call_1,
+    s390_emit_void_call_2,
+    s390_emit_eq_goto,
+    s390_emit_ne_goto,
+    s390_emit_lt_goto,
+    s390_emit_le_goto,
+    s390_emit_gt_goto,
+    s390_emit_ge_goto
+  };
+
+#ifdef __s390x__
+
+/* The "emit_prologue" emit_ops method for s390x.  */
+
+static void
+s390x_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24,	/* stmg %r9, %r15, 0x48(%r15) */
+    0xb9, 0x04, 0x00, 0x92,		/* lgr %r9, %r2 */
+    0xb9, 0x04, 0x00, 0xa3,		/* lgr %r10, %r3 */
+    0xb9, 0x04, 0x00, 0xbf,		/* lgr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_epilogue" emit_ops method for s390x.  */
+
+static void
+s390x_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r10) */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04,	/* lmg %r9, %r15, 0x48(%r15) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_add" emit_ops method for s390x.  */
+
+static void
+s390x_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a,	/* alg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_sub" emit_ops method for s390x.  */
+
+static void
+s390x_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xb9, 0x0b, 0x00, 0x32,		/* slgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_mul" emit_ops method for s390x.  */
+
+static void
+s390x_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+/* The "emit_lsh" emit_ops method for s390x.  */
+
+static void
+s390x_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d,	/* sllg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_signed" emit_ops method for s390x.  */
+
+static void
+s390x_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a,	/* srag %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_unsigned" emit_ops method for s390x.  */
+
+static void
+s390x_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c,	/* srlg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ext" emit_ops method for s390x.  */
+
+static void
+s390x_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0a,	/* srag %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_log_not" emit_ops method for s390x.  */
+
+static void
+s390x_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x00, 0x00, 0x22,		/* lpgr %r2, %r2 */
+    0xa7, 0x2b, 0xff, 0xff,		/* aghi %r2, -1 */
+    0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c,	/* srlg %r2, %r2, 63 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_and" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80,	/* ng %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_or" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81,	/* og %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_xor" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82,	/* xg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_not" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x39, 0xff, 0xff,	/* lghi %r3, -1 */
+    0xb9, 0x82, 0x00, 0x23,	/* xgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_equal" emit_ops method for s390x.  */
+
+static void
+s390x_emit_equal (void)
+{
+  s390x_emit_bit_xor ();
+  s390x_emit_log_not ();
+}
+
+/* The "emit_less_signed" emit_ops method for s390x.  */
+
+static void
+s390x_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_less_unsigned" emit_ops method for s390x.  */
+
+static void
+s390x_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21,	/* clg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ref" emit_ops method for s390x.  */
+
+static void
+s390x_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x90,	/* llgc %r2, 0(%r2) */
+  };
+  static const unsigned char buf2[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x91	/* llgh %r2, 0(%r2) */
+  };
+  static const unsigned char buf4[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x16,	/* llgf %r2, 0(%r2) */
+  };
+  static const unsigned char buf8[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r2) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* The "emit_if_goto" emit_ops method for s390x.  */
+
+static void
+s390x_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x02, 0x00, 0x22,		/* ltgr %r2, %r2 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 16;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_const" emit_ops method for s390x.  */
+
+static void
+s390x_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x29, num >> 8, num,		/* lghi %r2, <num> */
+  };
+  static const unsigned char buf_l[] = {
+    0xe3, 0x20, 0x10, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_call" emit_ops method for s390x.  */
+
+static void
+s390x_emit_call (CORE_ADDR fn)
+{
+  unsigned long n = fn;
+  static const unsigned char buf[] = {
+    0xe3, 0x10, 0x10, 0x00, 0x00, 0x04,	/* lg %r1, 0(%r1) */
+    0xa7, 0xfb, 0xff, 0x60,		/* aghi %r15, -0xa0 */
+    0x0d, 0xe1,				/* basr %r14, %r1 */
+    0xa7, 0xfb, 0x00, 0xa0,		/* aghi %r15, 0xa0 */
+  };
+  s390_emit_litpool (8);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_reg" emit_ops method for s390x.  */
+
+static void
+s390x_emit_reg (int reg)
+{
+  unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x29,		/* lgr %r2, %r9 */
+    0xa7, 0x39, reg >> 8, reg,		/* lghi %r3, <reg> */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_call (get_raw_reg_func_addr ());
+}
+
+/* The "emit_pop" emit_ops method for s390x.  */
+
+static void
+s390x_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_flush" emit_ops method for s390x.  */
+
+static void
+s390x_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfb, 0xff, 0xf8,		/* aghi %r15, -8 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_zero_ext" emit_ops method for s390x.  */
+
+static void
+s390x_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0c,	/* srlg %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_swap" emit_ops method for s390x.  */
+
+static void
+s390x_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_adjust" emit_ops method for s390x.  */
+
+static void
+s390x_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfb, n * 8 >> 8, n * 8,	/* aghi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_int_call_1" emit_ops method for s390x.  */
+
+static void
+s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `LONGEST(*fn)(int)'.  */
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+}
+
+/* The "emit_void_call_2" emit_ops method for s390x.  */
+
+static void
+s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+  static const unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x32,		/* lgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0xc2,		/* lgr %r12, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0xb9, 0x04, 0x00, 0x2c,		/* lgr %r2, %r12 */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+/* The "emit_eq_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ne_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_lt_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x24, 0x00, 0x00, 0x00, 0x00,	/* jgh <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_le_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00,	/* jghe <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_gt_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x44, 0x00, 0x00, 0x00, 0x00,	/* jgl <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ge_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00,	/* jgle <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ops" structure for s390x.  */
+
+struct emit_ops s390x_emit_ops =
+  {
+    s390x_emit_prologue,
+    s390x_emit_epilogue,
+    s390x_emit_add,
+    s390x_emit_sub,
+    s390x_emit_mul,
+    s390x_emit_lsh,
+    s390x_emit_rsh_signed,
+    s390x_emit_rsh_unsigned,
+    s390x_emit_ext,
+    s390x_emit_log_not,
+    s390x_emit_bit_and,
+    s390x_emit_bit_or,
+    s390x_emit_bit_xor,
+    s390x_emit_bit_not,
+    s390x_emit_equal,
+    s390x_emit_less_signed,
+    s390x_emit_less_unsigned,
+    s390x_emit_ref,
+    s390x_emit_if_goto,
+    s390_emit_goto,
+    s390_write_goto_address,
+    s390x_emit_const,
+    s390x_emit_call,
+    s390x_emit_reg,
+    s390x_emit_pop,
+    s390x_emit_stack_flush,
+    s390x_emit_zero_ext,
+    s390x_emit_swap,
+    s390x_emit_stack_adjust,
+    s390x_emit_int_call_1,
+    s390x_emit_void_call_2,
+    s390x_emit_eq_goto,
+    s390x_emit_ne_goto,
+    s390x_emit_lt_goto,
+    s390x_emit_le_goto,
+    s390x_emit_gt_goto,
+    s390x_emit_ge_goto
+  };
+#endif
+
+/* The "emit_ops" linux_target_ops method.  */
+
+static struct emit_ops *
+s390_emit_ops (void)
+{
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  if (register_size (regcache->tdesc, 0) == 8)
+    return &s390x_emit_ops;
+  else
+#endif
+    return &s390_emit_ops_impl;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -1426,7 +2770,7 @@ struct linux_target_ops the_low_target = {
   s390_supports_tracepoints,
   s390_get_thread_area,
   s390_install_fast_tracepoint_jump_pad,
-  NULL, /* emit_ops */
+  s390_emit_ops,
   s390_get_min_fast_tracepoint_insn_len,
   NULL, /* supports_range_stepping */
   NULL, /* breakpoint_kind_from_current_state */
-- 
2.7.1

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

* Re: [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-02-25 19:23     ` Marcin Kościelnicki
@ 2016-03-04 10:42       ` Marcin Kościelnicki
  2016-03-11  2:20         ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-04 10:42 UTC (permalink / raw)
  To: gdb-patches

Ping.

On 25/02/16 20:23, Marcin Kościelnicki wrote:
> Ping.
>
> On 07/02/16 15:01, Marcin Kościelnicki wrote:
>> gdb/ChangeLog:
>>
>>     * s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>>     (s390_ax_pseudo_register_push_stack): New function.
>>     (s390_gdbarch_init): Fill ax_pseudo_register_collect and
>>     ax_pseudo_register_push_stack hooks.
>> ---
>> Added missing comments.
>>
>>   gdb/ChangeLog         |  7 +++++
>>   gdb/s390-linux-tdep.c | 84
>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 91 insertions(+)
>>
>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>> index d24cccd..6260040 100644
>> --- a/gdb/ChangeLog
>> +++ b/gdb/ChangeLog
>> @@ -1,5 +1,12 @@
>>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>>
>> +    * s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>> +    (s390_ax_pseudo_register_push_stack): New function.
>> +    (s390_gdbarch_init): Fill ax_pseudo_register_collect and
>> +    ax_pseudo_register_push_stack hooks.
>> +
>> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>> +
>>       * s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
>>       (s390_gdbarch_init): Fill supply_pseudo_pc hook.
>>
>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>> index 144365c..97bd564 100644
>> --- a/gdb/s390-linux-tdep.c
>> +++ b/gdb/s390-linux-tdep.c
>> @@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch
>> *gdbarch, int regnum,
>>     return default_register_reggroup_p (gdbarch, regnum, group);
>>   }
>>
>> +/* The "ax_pseudo_register_collect" gdbarch method.  */
>> +
>> +static int
>> +s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
>> +                 struct agent_expr *ax, int regnum)
>> +{
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>> +  if (regnum == tdep->pc_regnum)
>> +    {
>> +      ax_reg_mask (ax, S390_PSWA_REGNUM);
>> +    }
>> +  else if (regnum == tdep->cc_regnum)
>> +    {
>> +      ax_reg_mask (ax, S390_PSWM_REGNUM);
>> +    }
>> +  else if (regnum_is_gpr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->gpr_full_regnum;
>> +      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
>> +      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
>> +    }
>> +  else if (regnum_is_vxr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->v0_full_regnum;
>> +      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
>> +      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
>> +    }
>> +  else
>> +    {
>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>> +    }
>> +  return 0;
>> +}
>> +
>> +/* The "ax_pseudo_register_push_stack" gdbarch method.  */
>> +
>> +static int
>> +s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>> +                    struct agent_expr *ax, int regnum)
>> +{
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>> +  if (regnum == tdep->pc_regnum)
>> +    {
>> +      ax_reg (ax, S390_PSWA_REGNUM);
>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>> +    {
>> +      ax_zero_ext (ax, 31);
>> +    }
>> +    }
>> +  else if (regnum == tdep->cc_regnum)
>> +    {
>> +      ax_reg (ax, S390_PSWM_REGNUM);
>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>> +    ax_const_l (ax, 12);
>> +      else
>> +    ax_const_l (ax, 44);
>> +      ax_simple (ax, aop_rsh_unsigned);
>> +      ax_zero_ext (ax, 2);
>> +    }
>> +  else if (regnum_is_gpr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->gpr_full_regnum;
>> +      ax_reg (ax, S390_R0_REGNUM + regnum);
>> +      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
>> +      ax_const_l (ax, 32);
>> +      ax_simple (ax, aop_lsh);
>> +      ax_simple (ax, aop_bit_or);
>> +    }
>> +  else if (regnum_is_vxr_full (tdep, regnum))
>> +    {
>> +      /* Too large to stuff on the stack.  */
>> +      return 1;
>> +    }
>> +  else
>> +    {
>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>> +    }
>> +  return 0;
>> +}
>> +
>>
>>   /* A helper for s390_software_single_step, decides if an instruction
>>      is a partial-execution instruction that needs to be executed until
>> @@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info,
>> struct gdbarch_list *arches)
>>     set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
>>     set_tdesc_pseudo_register_reggroup_p (gdbarch,
>>                       s390_pseudo_register_reggroup_p);
>> +  set_gdbarch_ax_pseudo_register_collect (gdbarch,
>> +                      s390_ax_pseudo_register_collect);
>> +  set_gdbarch_ax_pseudo_register_push_stack
>> +      (gdbarch, s390_ax_pseudo_register_push_stack);
>>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>>     set_gdbarch_register_name (gdbarch, s390_register_name);
>>
>>
>

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-02-25 19:23     ` Marcin Kościelnicki
@ 2016-03-04 10:42       ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-04 10:42 UTC (permalink / raw)
  To: gdb-patches

Ping.

On 25/02/16 20:23, Marcin Kościelnicki wrote:
> Ping.
>
> On 07/02/16 15:02, Marcin Kościelnicki wrote:
>> gdb/ChangeLog:
>>
>>     * s390-linux-tdep.c (s390_gen_return_address): New function.
>>     (s390_gdbarch_init): Fill gen_return_address hook.
>> ---
>> Added missing comment.
>>
>>   gdb/ChangeLog         |  5 +++++
>>   gdb/s390-linux-tdep.c | 13 +++++++++++++
>>   2 files changed, 18 insertions(+)
>>
>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>> index 6260040..0cf8bfc 100644
>> --- a/gdb/ChangeLog
>> +++ b/gdb/ChangeLog
>> @@ -1,5 +1,10 @@
>>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>>
>> +    * s390-linux-tdep.c (s390_gen_return_address): New function.
>> +    (s390_gdbarch_init): Fill gen_return_address hook.
>> +
>> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>> +
>>       * s390-linux-tdep.c (s390_ax_pseudo_register_collect): New
>> function.
>>       (s390_ax_pseudo_register_push_stack): New function.
>>       (s390_gdbarch_init): Fill ax_pseudo_register_collect and
>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>> index 97bd564..0b91ed1 100644
>> --- a/gdb/s390-linux-tdep.c
>> +++ b/gdb/s390-linux-tdep.c
>> @@ -627,6 +627,18 @@ s390_ax_pseudo_register_push_stack (struct
>> gdbarch *gdbarch,
>>     return 0;
>>   }
>>
>> +/* The "gen_return_address" gdbarch method.  */
>> +
>> +static void
>> +s390_gen_return_address (struct gdbarch *gdbarch,
>> +             struct agent_expr *ax, struct axs_value *value,
>> +             CORE_ADDR scope)
>> +{
>> +  value->type = register_type (gdbarch, S390_R14_REGNUM);
>> +  value->kind = axs_lvalue_register;
>> +  value->u.reg = S390_R14_REGNUM;
>> +}
>> +
>>
>>   /* A helper for s390_software_single_step, decides if an instruction
>>      is a partial-execution instruction that needs to be executed until
>> @@ -7970,6 +7982,7 @@ s390_gdbarch_init (struct gdbarch_info info,
>> struct gdbarch_list *arches)
>>                         s390_ax_pseudo_register_collect);
>>     set_gdbarch_ax_pseudo_register_push_stack
>>         (gdbarch, s390_ax_pseudo_register_push_stack);
>> +  set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
>>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>>     set_gdbarch_register_name (gdbarch, s390_register_name);
>>
>>
>

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

* Re: [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-03-04 10:42       ` Marcin Kościelnicki
@ 2016-03-11  2:20         ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-11  2:20 UTC (permalink / raw)
  To: gdb-patches

Ping.

On 04/03/16 11:42, Marcin Kościelnicki wrote:
> Ping.
>
> On 25/02/16 20:23, Marcin Kościelnicki wrote:
>> Ping.
>>
>> On 07/02/16 15:01, Marcin Kościelnicki wrote:
>>> gdb/ChangeLog:
>>>
>>>     * s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>>>     (s390_ax_pseudo_register_push_stack): New function.
>>>     (s390_gdbarch_init): Fill ax_pseudo_register_collect and
>>>     ax_pseudo_register_push_stack hooks.
>>> ---
>>> Added missing comments.
>>>
>>>   gdb/ChangeLog         |  7 +++++
>>>   gdb/s390-linux-tdep.c | 84
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>   2 files changed, 91 insertions(+)
>>>
>>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>>> index d24cccd..6260040 100644
>>> --- a/gdb/ChangeLog
>>> +++ b/gdb/ChangeLog
>>> @@ -1,5 +1,12 @@
>>>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>>>
>>> +    * s390-linux-tdep.c (s390_ax_pseudo_register_collect): New
>>> function.
>>> +    (s390_ax_pseudo_register_push_stack): New function.
>>> +    (s390_gdbarch_init): Fill ax_pseudo_register_collect and
>>> +    ax_pseudo_register_push_stack hooks.
>>> +
>>> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>>> +
>>>       * s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
>>>       (s390_gdbarch_init): Fill supply_pseudo_pc hook.
>>>
>>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>>> index 144365c..97bd564 100644
>>> --- a/gdb/s390-linux-tdep.c
>>> +++ b/gdb/s390-linux-tdep.c
>>> @@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch
>>> *gdbarch, int regnum,
>>>     return default_register_reggroup_p (gdbarch, regnum, group);
>>>   }
>>>
>>> +/* The "ax_pseudo_register_collect" gdbarch method.  */
>>> +
>>> +static int
>>> +s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
>>> +                 struct agent_expr *ax, int regnum)
>>> +{
>>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>>> +  if (regnum == tdep->pc_regnum)
>>> +    {
>>> +      ax_reg_mask (ax, S390_PSWA_REGNUM);
>>> +    }
>>> +  else if (regnum == tdep->cc_regnum)
>>> +    {
>>> +      ax_reg_mask (ax, S390_PSWM_REGNUM);
>>> +    }
>>> +  else if (regnum_is_gpr_full (tdep, regnum))
>>> +    {
>>> +      regnum -= tdep->gpr_full_regnum;
>>> +      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
>>> +      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
>>> +    }
>>> +  else if (regnum_is_vxr_full (tdep, regnum))
>>> +    {
>>> +      regnum -= tdep->v0_full_regnum;
>>> +      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
>>> +      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
>>> +    }
>>> +  else
>>> +    {
>>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>>> +    }
>>> +  return 0;
>>> +}
>>> +
>>> +/* The "ax_pseudo_register_push_stack" gdbarch method.  */
>>> +
>>> +static int
>>> +s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>>> +                    struct agent_expr *ax, int regnum)
>>> +{
>>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>>> +  if (regnum == tdep->pc_regnum)
>>> +    {
>>> +      ax_reg (ax, S390_PSWA_REGNUM);
>>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>>> +    {
>>> +      ax_zero_ext (ax, 31);
>>> +    }
>>> +    }
>>> +  else if (regnum == tdep->cc_regnum)
>>> +    {
>>> +      ax_reg (ax, S390_PSWM_REGNUM);
>>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>>> +    ax_const_l (ax, 12);
>>> +      else
>>> +    ax_const_l (ax, 44);
>>> +      ax_simple (ax, aop_rsh_unsigned);
>>> +      ax_zero_ext (ax, 2);
>>> +    }
>>> +  else if (regnum_is_gpr_full (tdep, regnum))
>>> +    {
>>> +      regnum -= tdep->gpr_full_regnum;
>>> +      ax_reg (ax, S390_R0_REGNUM + regnum);
>>> +      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
>>> +      ax_const_l (ax, 32);
>>> +      ax_simple (ax, aop_lsh);
>>> +      ax_simple (ax, aop_bit_or);
>>> +    }
>>> +  else if (regnum_is_vxr_full (tdep, regnum))
>>> +    {
>>> +      /* Too large to stuff on the stack.  */
>>> +      return 1;
>>> +    }
>>> +  else
>>> +    {
>>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>>> +    }
>>> +  return 0;
>>> +}
>>> +
>>>
>>>   /* A helper for s390_software_single_step, decides if an instruction
>>>      is a partial-execution instruction that needs to be executed until
>>> @@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info,
>>> struct gdbarch_list *arches)
>>>     set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
>>>     set_tdesc_pseudo_register_reggroup_p (gdbarch,
>>>                       s390_pseudo_register_reggroup_p);
>>> +  set_gdbarch_ax_pseudo_register_collect (gdbarch,
>>> +                      s390_ax_pseudo_register_collect);
>>> +  set_gdbarch_ax_pseudo_register_push_stack
>>> +      (gdbarch, s390_ax_pseudo_register_push_stack);
>>>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>>>     set_gdbarch_register_name (gdbarch, s390_register_name);
>>>
>>>
>>
>

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

* Re: [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-02-07 14:01   ` Marcin Kościelnicki
  2016-02-25 19:23     ` Marcin Kościelnicki
@ 2016-03-11  9:58     ` Andreas Arnez
  2016-03-11 10:04       ` Marcin Kościelnicki
  1 sibling, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-03-11  9:58 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Feb 07 2016, Marcin Kościelnicki wrote:

> gdb/ChangeLog:
>
> 	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
> 	(s390_ax_pseudo_register_push_stack): New function.
> 	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
> 	ax_pseudo_register_push_stack hooks.
> ---
> Added missing comments.
>
>  gdb/ChangeLog         |  7 +++++
>  gdb/s390-linux-tdep.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index d24cccd..6260040 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,12 @@
>  2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>  
> +	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
> +	(s390_ax_pseudo_register_push_stack): New function.
> +	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
> +	ax_pseudo_register_push_stack hooks.
> +
> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
> +
>  	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
>  	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
>  
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index 144365c..97bd564 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
>    return default_register_reggroup_p (gdbarch, regnum, group);
>  }
>  
> +/* The "ax_pseudo_register_collect" gdbarch method.  */
> +
> +static int
> +s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
> +				 struct agent_expr *ax, int regnum)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  if (regnum == tdep->pc_regnum)
> +    {
> +      ax_reg_mask (ax, S390_PSWA_REGNUM);
> +    }
> +  else if (regnum == tdep->cc_regnum)
> +    {
> +      ax_reg_mask (ax, S390_PSWM_REGNUM);
> +    }
> +  else if (regnum_is_gpr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->gpr_full_regnum;
> +      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
> +      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
> +    }
> +  else if (regnum_is_vxr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->v0_full_regnum;
> +      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
> +      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
> +    }
> +  else
> +    {
> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
> +    }
> +  return 0;
> +}
> +
> +/* The "ax_pseudo_register_push_stack" gdbarch method.  */
> +
> +static int
> +s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
> +				    struct agent_expr *ax, int regnum)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  if (regnum == tdep->pc_regnum)
> +    {
> +      ax_reg (ax, S390_PSWA_REGNUM);
> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
> +	{
> +	  ax_zero_ext (ax, 31);
> +	}
> +    }
> +  else if (regnum == tdep->cc_regnum)
> +    {
> +      ax_reg (ax, S390_PSWM_REGNUM);
> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
> +	ax_const_l (ax, 12);
> +      else
> +	ax_const_l (ax, 44);
> +      ax_simple (ax, aop_rsh_unsigned);
> +      ax_zero_ext (ax, 2);
> +    }
> +  else if (regnum_is_gpr_full (tdep, regnum))
> +    {
> +      regnum -= tdep->gpr_full_regnum;
> +      ax_reg (ax, S390_R0_REGNUM + regnum);
> +      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
> +      ax_const_l (ax, 32);
> +      ax_simple (ax, aop_lsh);
> +      ax_simple (ax, aop_bit_or);
> +    }
> +  else if (regnum_is_vxr_full (tdep, regnum))
> +    {
> +      /* Too large to stuff on the stack.  */
> +      return 1;
> +    }
> +  else
> +    {
> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
> +    }
> +  return 0;
> +}
> +
>  
>  /* A helper for s390_software_single_step, decides if an instruction
>     is a partial-execution instruction that needs to be executed until
> @@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
>    set_tdesc_pseudo_register_reggroup_p (gdbarch,
>  					s390_pseudo_register_reggroup_p);
> +  set_gdbarch_ax_pseudo_register_collect (gdbarch,
> +					  s390_ax_pseudo_register_collect);
> +  set_gdbarch_ax_pseudo_register_push_stack
> +      (gdbarch, s390_ax_pseudo_register_push_stack);
>    tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>    set_gdbarch_register_name (gdbarch, s390_register_name);

Thanks, this is OK.

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

* Re: [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks.
  2016-03-11  9:58     ` Andreas Arnez
@ 2016-03-11 10:04       ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-11 10:04 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 11/03/16 10:58, Andreas Arnez wrote:
> On Sun, Feb 07 2016, Marcin Kościelnicki wrote:
>
>> gdb/ChangeLog:
>>
>> 	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>> 	(s390_ax_pseudo_register_push_stack): New function.
>> 	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
>> 	ax_pseudo_register_push_stack hooks.
>> ---
>> Added missing comments.
>>
>>   gdb/ChangeLog         |  7 +++++
>>   gdb/s390-linux-tdep.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 91 insertions(+)
>>
>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>> index d24cccd..6260040 100644
>> --- a/gdb/ChangeLog
>> +++ b/gdb/ChangeLog
>> @@ -1,5 +1,12 @@
>>   2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>>
>> +	* s390-linux-tdep.c (s390_ax_pseudo_register_collect): New function.
>> +	(s390_ax_pseudo_register_push_stack): New function.
>> +	(s390_gdbarch_init): Fill ax_pseudo_register_collect and
>> +	ax_pseudo_register_push_stack hooks.
>> +
>> +2016-02-07  Marcin Kościelnicki  <koriakin@0x04.net>
>> +
>>   	* s390-linux-tdep.c (s390_supply_pseudo_pc): New function.
>>   	(s390_gdbarch_init): Fill supply_pseudo_pc hook.
>>
>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>> index 144365c..97bd564 100644
>> --- a/gdb/s390-linux-tdep.c
>> +++ b/gdb/s390-linux-tdep.c
>> @@ -547,6 +547,86 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
>>     return default_register_reggroup_p (gdbarch, regnum, group);
>>   }
>>
>> +/* The "ax_pseudo_register_collect" gdbarch method.  */
>> +
>> +static int
>> +s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
>> +				 struct agent_expr *ax, int regnum)
>> +{
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>> +  if (regnum == tdep->pc_regnum)
>> +    {
>> +      ax_reg_mask (ax, S390_PSWA_REGNUM);
>> +    }
>> +  else if (regnum == tdep->cc_regnum)
>> +    {
>> +      ax_reg_mask (ax, S390_PSWM_REGNUM);
>> +    }
>> +  else if (regnum_is_gpr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->gpr_full_regnum;
>> +      ax_reg_mask (ax, S390_R0_REGNUM + regnum);
>> +      ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
>> +    }
>> +  else if (regnum_is_vxr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->v0_full_regnum;
>> +      ax_reg_mask (ax, S390_F0_REGNUM + regnum);
>> +      ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
>> +    }
>> +  else
>> +    {
>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>> +    }
>> +  return 0;
>> +}
>> +
>> +/* The "ax_pseudo_register_push_stack" gdbarch method.  */
>> +
>> +static int
>> +s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>> +				    struct agent_expr *ax, int regnum)
>> +{
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>> +  if (regnum == tdep->pc_regnum)
>> +    {
>> +      ax_reg (ax, S390_PSWA_REGNUM);
>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>> +	{
>> +	  ax_zero_ext (ax, 31);
>> +	}
>> +    }
>> +  else if (regnum == tdep->cc_regnum)
>> +    {
>> +      ax_reg (ax, S390_PSWM_REGNUM);
>> +      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
>> +	ax_const_l (ax, 12);
>> +      else
>> +	ax_const_l (ax, 44);
>> +      ax_simple (ax, aop_rsh_unsigned);
>> +      ax_zero_ext (ax, 2);
>> +    }
>> +  else if (regnum_is_gpr_full (tdep, regnum))
>> +    {
>> +      regnum -= tdep->gpr_full_regnum;
>> +      ax_reg (ax, S390_R0_REGNUM + regnum);
>> +      ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
>> +      ax_const_l (ax, 32);
>> +      ax_simple (ax, aop_lsh);
>> +      ax_simple (ax, aop_bit_or);
>> +    }
>> +  else if (regnum_is_vxr_full (tdep, regnum))
>> +    {
>> +      /* Too large to stuff on the stack.  */
>> +      return 1;
>> +    }
>> +  else
>> +    {
>> +      internal_error (__FILE__, __LINE__, _("invalid regnum"));
>> +    }
>> +  return 0;
>> +}
>> +
>>
>>   /* A helper for s390_software_single_step, decides if an instruction
>>      is a partial-execution instruction that needs to be executed until
>> @@ -7886,6 +7966,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>     set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
>>     set_tdesc_pseudo_register_reggroup_p (gdbarch,
>>   					s390_pseudo_register_reggroup_p);
>> +  set_gdbarch_ax_pseudo_register_collect (gdbarch,
>> +					  s390_ax_pseudo_register_collect);
>> +  set_gdbarch_ax_pseudo_register_push_stack
>> +      (gdbarch, s390_ax_pseudo_register_push_stack);
>>     tdesc_use_registers (gdbarch, tdesc, tdesc_data);
>>     set_gdbarch_register_name (gdbarch, s390_register_name);
>
> Thanks, this is OK.
>

Thanks, pushed.  How about the remaining 4 patches?

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-02-07 14:02   ` Marcin Kościelnicki
  2016-02-25 19:23     ` Marcin Kościelnicki
@ 2016-03-11 11:20     ` Andreas Arnez
  2016-03-11 11:35       ` Marcin Kościelnicki
  1 sibling, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-03-11 11:20 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Feb 07 2016, Marcin Kościelnicki wrote:

> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index 97bd564..0b91ed1 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -627,6 +627,18 @@ s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>    return 0;
>  }
>  
> +/* The "gen_return_address" gdbarch method.  */
> +
> +static void
> +s390_gen_return_address (struct gdbarch *gdbarch,
> +			 struct agent_expr *ax, struct axs_value *value,
> +			 CORE_ADDR scope)
> +{
> +  value->type = register_type (gdbarch, S390_R14_REGNUM);
> +  value->kind = axs_lvalue_register;
> +  value->u.reg = S390_R14_REGNUM;
> +}

Under which circumstances is this supposed to work?  And how reliable
does it need to be?  The ABI only guarantees that r14 holds the return
address at function entry.  Anywhere else it likely doesn't.

--
Andreas

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 11:20     ` Andreas Arnez
@ 2016-03-11 11:35       ` Marcin Kościelnicki
  2016-03-11 12:18         ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-11 11:35 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 11/03/16 12:20, Andreas Arnez wrote:
> On Sun, Feb 07 2016, Marcin Kościelnicki wrote:
>
>> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
>> index 97bd564..0b91ed1 100644
>> --- a/gdb/s390-linux-tdep.c
>> +++ b/gdb/s390-linux-tdep.c
>> @@ -627,6 +627,18 @@ s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
>>     return 0;
>>   }
>>
>> +/* The "gen_return_address" gdbarch method.  */
>> +
>> +static void
>> +s390_gen_return_address (struct gdbarch *gdbarch,
>> +			 struct agent_expr *ax, struct axs_value *value,
>> +			 CORE_ADDR scope)
>> +{
>> +  value->type = register_type (gdbarch, S390_R14_REGNUM);
>> +  value->kind = axs_lvalue_register;
>> +  value->u.reg = S390_R14_REGNUM;
>> +}
>
> Under which circumstances is this supposed to work?  And how reliable
> does it need to be?  The ABI only guarantees that r14 holds the return
> address at function entry.  Anywhere else it likely doesn't.
>
> --
> Andreas
>

Quoting gdbarch.sh:

# Generate bytecodes to collect the return address in a frame.
# Since the bytecodes run on the target, possibly with GDB not even
# connected, the full unwinding machinery is not available, and
# typically this function will issue bytecodes for one or more likely
# places that the return address may be found.
m:void:gen_return_address:struct agent_expr *ax, struct axs_value 
*value, CORE_ADDR scope:ax, value, scope::default_gen_return_address::0

ie. it's supposed to collect some value that will likely help the 
unwinder - if it collects the wrong thing, the unwinder (knowing the 
right place for sure) will simply consider the previous frame PC to be 
unavailable.

We could also try to collect 14*<wordsize>(%r11), hoping that's the save 
slot for %r14, but the interface unfortunately doesn't support 
collecting multiple values (no matter what the comment above says).

Unfortunately, this interface is just not very well-designed - both x86 
and aarch64 just take a shot in the dark like this patch.  A better way 
would be to reuse the existing unwinders and remove this hook 
altogether, or (for while-stepping, where we can't predict the PC) 
actually allow multiple values and aim at a few likely locations.  But 
IMO that's not in scope for this patchset.

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 11:35       ` Marcin Kościelnicki
@ 2016-03-11 12:18         ` Andreas Arnez
  2016-03-11 12:26           ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-03-11 12:18 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Fri, Mar 11 2016, Marcin Kościelnicki wrote:

> We could also try to collect 14*<wordsize>(%r11), hoping that's the
> save slot for %r14, but the interface unfortunately doesn't support
> collecting multiple values (no matter what the comment above says).

Nah, that doesn't help either, since most functions don't use r11 as a
frame pointer.  There is just no way to locate the return address unless
we have call frame information or perform code analysis.

> Unfortunately, this interface is just not very well-designed - both
> x86 and aarch64 just take a shot in the dark like this patch.  A
> better way would be to reuse the existing unwinders and remove this
> hook altogether, or (for while-stepping, where we can't predict the
> PC) actually allow multiple values and aim at a few likely locations.
> But IMO that's not in scope for this patchset.

The point I was trying to make is that r14 is fairly *unlikely* to
contain the return address, unless we're near function entry.  If we
just called a function, then r14 contains an address within our own
function.  Otherwise r14 can also contain something else entirely.

Is there a way to admit that we don't know the return address?  What if
we always return garbage?  E.g., maybe it's better to always return 0?

-- 
Andreas

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 12:18         ` Andreas Arnez
@ 2016-03-11 12:26           ` Marcin Kościelnicki
  2016-03-11 15:31             ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-11 12:26 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 11/03/16 13:18, Andreas Arnez wrote:
> On Fri, Mar 11 2016, Marcin Kościelnicki wrote:
>
>> We could also try to collect 14*<wordsize>(%r11), hoping that's the
>> save slot for %r14, but the interface unfortunately doesn't support
>> collecting multiple values (no matter what the comment above says).
>
> Nah, that doesn't help either, since most functions don't use r11 as a
> frame pointer.  There is just no way to locate the return address unless
> we have call frame information or perform code analysis.
>
>> Unfortunately, this interface is just not very well-designed - both
>> x86 and aarch64 just take a shot in the dark like this patch.  A
>> better way would be to reuse the existing unwinders and remove this
>> hook altogether, or (for while-stepping, where we can't predict the
>> PC) actually allow multiple values and aim at a few likely locations.
>> But IMO that's not in scope for this patchset.
>
> The point I was trying to make is that r14 is fairly *unlikely* to
> contain the return address, unless we're near function entry.  If we
> just called a function, then r14 contains an address within our own
> function.  Otherwise r14 can also contain something else entirely.

Well, it works for leaf functions... not much, but not totally useless 
either.
>
> Is there a way to admit that we don't know the return address?  What if
> we always return garbage?  E.g., maybe it's better to always return 0?
>
We can always error() in there (and KFAIL the testcase in gdb.trace that 
exercises it).  However, returning garbage here doesn't result in 
garbage backtrace - this only collects data, if the unwinder actually 
doing the work later determines it should look for the return address on 
the stack, it'll just ignore our collected $r14 and consider the return 
address unavailable (unless another collect rule happened to match it).

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 12:26           ` Marcin Kościelnicki
@ 2016-03-11 15:31             ` Andreas Arnez
  2016-03-11 15:44               ` Pedro Alves
  2016-03-13  9:53               ` Marcin Kościelnicki
  0 siblings, 2 replies; 89+ messages in thread
From: Andreas Arnez @ 2016-03-11 15:31 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Fri, Mar 11 2016, Marcin Kościelnicki wrote:

> We can always error() in there (and KFAIL the testcase in gdb.trace
> that exercises it).  However, returning garbage here doesn't result in
> garbage backtrace - this only collects data, if the unwinder actually
> doing the work later determines it should look for the return address
> on the stack, it'll just ignore our collected $r14 and consider the
> return address unavailable (unless another collect rule happened to
> match it).

Well, from that test case it appears that `$_ret' is generally not
expected to work very reliably.  Since r14 usually does work near
function entry, this may be sufficient for now.

So I'm OK with the patch.  Please add a small comment stating that this
is a best-can-do approach that usually works near function entry and may
yield wrong results otherwise.

-- 
Andreas

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 15:31             ` Andreas Arnez
@ 2016-03-11 15:44               ` Pedro Alves
  2016-03-11 16:45                 ` Andreas Arnez
  2016-03-13  9:53               ` Marcin Kościelnicki
  1 sibling, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-03-11 15:44 UTC (permalink / raw)
  To: Andreas Arnez, Marcin Kościelnicki; +Cc: gdb-patches

On 03/11/2016 03:31 PM, Andreas Arnez wrote:
> So I'm OK with the patch.  Please add a small comment stating that this
> is a best-can-do approach that usually works near function entry and may
> yield wrong results otherwise.

I think that should be put in the manual, even.  Users will also trip on
this, not just our tests.

Thanks,
Pedro Alves

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 15:44               ` Pedro Alves
@ 2016-03-11 16:45                 ` Andreas Arnez
  2016-03-11 17:02                   ` Pedro Alves
  2016-03-11 18:07                   ` Eli Zaretskii
  0 siblings, 2 replies; 89+ messages in thread
From: Andreas Arnez @ 2016-03-11 16:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Eli Zaretskii, Marcin Kościelnicki, gdb-patches

On Fri, Mar 11 2016, Pedro Alves wrote:

> On 03/11/2016 03:31 PM, Andreas Arnez wrote:
>> So I'm OK with the patch.  Please add a small comment stating that this
>> is a best-can-do approach that usually works near function entry and may
>> yield wrong results otherwise.
>
> I think that should be put in the manual, even.  Users will also trip on
> this, not just our tests.

Right, I thought about this as well.  How about this?

-- >8 --
Subject: [PATCH] Document possible unreliability of `$_ret'

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4ec0ec1..a14fe19 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -12863,7 +12863,9 @@ Collect all local variables.
 
 @item $_ret
 Collect the return address.  This is helpful if you want to see more
-of a backtrace.
+of a backtrace.  Note that the return address can not always be
+determined reliably, and a wrong address may be collected instead.
+The reliability is usually higher for tracepoints at function entry.
 
 @item $_probe_argc
 Collects the number of arguments from the static probe at which the

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 16:45                 ` Andreas Arnez
@ 2016-03-11 17:02                   ` Pedro Alves
  2016-03-11 18:17                     ` Eli Zaretskii
  2016-03-11 18:07                   ` Eli Zaretskii
  1 sibling, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-03-11 17:02 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: Eli Zaretskii, Marcin Kościelnicki, gdb-patches

On 03/11/2016 04:45 PM, Andreas Arnez wrote:
> On Fri, Mar 11 2016, Pedro Alves wrote:
> 
>> On 03/11/2016 03:31 PM, Andreas Arnez wrote:
>>> So I'm OK with the patch.  Please add a small comment stating that this
>>> is a best-can-do approach that usually works near function entry and may
>>> yield wrong results otherwise.
>>
>> I think that should be put in the manual, even.  Users will also trip on
>> this, not just our tests.
> 
> Right, I thought about this as well.  How about this?
> 
> -- >8 --
> Subject: [PATCH] Document possible unreliability of `$_ret'
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 4ec0ec1..a14fe19 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -12863,7 +12863,9 @@ Collect all local variables.
>   
>   @item $_ret
>   Collect the return address.  This is helpful if you want to see more
> -of a backtrace.
> +of a backtrace.  Note that the return address can not always be
> +determined reliably, and a wrong address may be collected instead.
> +The reliability is usually higher for tracepoints at function entry.

Hmm, this reads a bit as if the backtrace will be incorrect/bogus
later on, which is not true.

How about a merge of your suggestion with Marcin's previous reply,
and some extras on top:

@item $_ret
Collect the set of memory addresses and/or registers necessary to compute
the frame's return address.  This is helpful if you want to see 
more of a backtrace.

@emph{Note:} The necessary set can not always be reliability determined up
front, and the wrong address / registers may end up collected instead.
The reliability is usually higher for tracepoints at function entry.
When this happens, backtracing will stop because the return address
is found unavailable (unless another collect rule happened to match it).

Thanks,
Pedro Alves

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 16:45                 ` Andreas Arnez
  2016-03-11 17:02                   ` Pedro Alves
@ 2016-03-11 18:07                   ` Eli Zaretskii
  1 sibling, 0 replies; 89+ messages in thread
From: Eli Zaretskii @ 2016-03-11 18:07 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: palves, koriakin, gdb-patches

> From: Andreas Arnez <arnez@linux.vnet.ibm.com>
> Cc: Eli Zaretskii <eliz@gnu.org>
> Cc: Marcin Kościelnicki <koriakin@0x04.net>,        gdb-patches@sourceware.org
> Date: Fri, 11 Mar 2016 17:45:16 +0100
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 4ec0ec1..a14fe19 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -12863,7 +12863,9 @@ Collect all local variables.
>  
>  @item $_ret
>  Collect the return address.  This is helpful if you want to see more
> -of a backtrace.
> +of a backtrace.  Note that the return address can not always be
> +determined reliably, and a wrong address may be collected instead.
> +The reliability is usually higher for tracepoints at function entry.

LGTM, thanks.

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 17:02                   ` Pedro Alves
@ 2016-03-11 18:17                     ` Eli Zaretskii
  2016-03-11 18:37                       ` Pedro Alves
  0 siblings, 1 reply; 89+ messages in thread
From: Eli Zaretskii @ 2016-03-11 18:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: arnez, koriakin, gdb-patches

> Cc: Eli Zaretskii <eliz@gnu.org>,
>         Marcin Kościelnicki
>  <koriakin@0x04.net>,
>         gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 11 Mar 2016 17:02:19 +0000
> 
> >   @item $_ret
> >   Collect the return address.  This is helpful if you want to see more
> > -of a backtrace.
> > +of a backtrace.  Note that the return address can not always be
> > +determined reliably, and a wrong address may be collected instead.
> > +The reliability is usually higher for tracepoints at function entry.
> 
> Hmm, this reads a bit as if the backtrace will be incorrect/bogus
> later on, which is not true.
> 
> How about a merge of your suggestion with Marcin's previous reply,
> and some extras on top:
> 
> @item $_ret
> Collect the set of memory addresses and/or registers necessary to compute
> the frame's return address.  This is helpful if you want to see 
> more of a backtrace.
> 
> @emph{Note:} The necessary set can not always be reliability determined up
> front, and the wrong address / registers may end up collected instead.
> The reliability is usually higher for tracepoints at function entry.
> When this happens, backtracing will stop because the return address
> is found unavailable (unless another collect rule happened to match it).

Maybe it's me, but I don't see the significant difference between
these two versions.  (And there's a typo in the second one:
"reliability" should be "reliably".)

Thanks.

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 18:17                     ` Eli Zaretskii
@ 2016-03-11 18:37                       ` Pedro Alves
  2016-03-11 19:34                         ` Eli Zaretskii
  0 siblings, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-03-11 18:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arnez, koriakin, gdb-patches

On 03/11/2016 06:16 PM, Eli Zaretskii wrote:
>> Cc: Eli Zaretskii <eliz@gnu.org>,
>>          Marcin Kościelnicki
>>   <koriakin@0x04.net>,
>>          gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Fri, 11 Mar 2016 17:02:19 +0000
>>
>>>    @item $_ret
>>>    Collect the return address.  This is helpful if you want to see more
>>> -of a backtrace.
>>> +of a backtrace.  Note that the return address can not always be
>>> +determined reliably, and a wrong address may be collected instead.
>>> +The reliability is usually higher for tracepoints at function entry.
>>
>> Hmm, this reads a bit as if the backtrace will be incorrect/bogus
>> later on, which is not true.
>>
>> How about a merge of your suggestion with Marcin's previous reply,
>> and some extras on top:
>>
>> @item $_ret
>> Collect the set of memory addresses and/or registers necessary to compute
>> the frame's return address.  This is helpful if you want to see
>> more of a backtrace.
>>
>> @emph{Note:} The necessary set can not always be reliability determined up
>> front, and the wrong address / registers may end up collected instead.
>> The reliability is usually higher for tracepoints at function entry.
>> When this happens, backtracing will stop because the return address
>> is found unavailable (unless another collect rule happened to match it).
>
> Maybe it's me, but I don't see the significant difference between
> these two versions.

I think the original version can be misinterpreted as if the
backtrace will show the wrong caller when the wrong address
is collected.  This version clarifies that it won't.

> (And there's a typo in the second one:
> "reliability" should be "reliably".)

Whoops.

Thanks,
Pedro Alves

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 18:37                       ` Pedro Alves
@ 2016-03-11 19:34                         ` Eli Zaretskii
  2016-03-15 11:11                           ` Pedro Alves
  0 siblings, 1 reply; 89+ messages in thread
From: Eli Zaretskii @ 2016-03-11 19:34 UTC (permalink / raw)
  To: Pedro Alves; +Cc: arnez, koriakin, gdb-patches

> Cc: arnez@linux.vnet.ibm.com, koriakin@0x04.net, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 11 Mar 2016 18:37:22 +0000
> 
> On 03/11/2016 06:16 PM, Eli Zaretskii wrote:
> >> Cc: Eli Zaretskii <eliz@gnu.org>,
> >>          Marcin Kościelnicki
> >>   <koriakin@0x04.net>,
> >>          gdb-patches@sourceware.org
> >> From: Pedro Alves <palves@redhat.com>
> >> Date: Fri, 11 Mar 2016 17:02:19 +0000
> >>
> >>>    @item $_ret
> >>>    Collect the return address.  This is helpful if you want to see more
> >>> -of a backtrace.
> >>> +of a backtrace.  Note that the return address can not always be
> >>> +determined reliably, and a wrong address may be collected instead.
> >>> +The reliability is usually higher for tracepoints at function entry.
> >>
> >> Hmm, this reads a bit as if the backtrace will be incorrect/bogus
> >> later on, which is not true.
> >>
> >> How about a merge of your suggestion with Marcin's previous reply,
> >> and some extras on top:
> >>
> >> @item $_ret
> >> Collect the set of memory addresses and/or registers necessary to compute
> >> the frame's return address.  This is helpful if you want to see
> >> more of a backtrace.
> >>
> >> @emph{Note:} The necessary set can not always be reliability determined up
> >> front, and the wrong address / registers may end up collected instead.
> >> The reliability is usually higher for tracepoints at function entry.
> >> When this happens, backtracing will stop because the return address
> >> is found unavailable (unless another collect rule happened to match it).
> >
> > Maybe it's me, but I don't see the significant difference between
> > these two versions.
> 
> I think the original version can be misinterpreted as if the
> backtrace will show the wrong caller when the wrong address
> is collected.  This version clarifies that it won't.

My reading is the other way around: the original version only talks
about the return address, while the modified one talks about a set of
addresses.

Anyway, if you are happier with your proposal, I won't object.

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 15:31             ` Andreas Arnez
  2016-03-11 15:44               ` Pedro Alves
@ 2016-03-13  9:53               ` Marcin Kościelnicki
  2016-03-14 10:07                 ` Andreas Arnez
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-13  9:53 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 11/03/16 16:31, Andreas Arnez wrote:
> On Fri, Mar 11 2016, Marcin Kościelnicki wrote:
>
>> We can always error() in there (and KFAIL the testcase in gdb.trace
>> that exercises it).  However, returning garbage here doesn't result in
>> garbage backtrace - this only collects data, if the unwinder actually
>> doing the work later determines it should look for the return address
>> on the stack, it'll just ignore our collected $r14 and consider the
>> return address unavailable (unless another collect rule happened to
>> match it).
>
> Well, from that test case it appears that `$_ret' is generally not
> expected to work very reliably.  Since r14 usually does work near
> function entry, this may be sufficient for now.
>
> So I'm OK with the patch.  Please add a small comment stating that this
> is a best-can-do approach that usually works near function entry and may
> yield wrong results otherwise.
>

Thanks, pushed with this comment:

/* The "gen_return_address" gdbarch method.  Since this is supposed to be
    just a best-effort method, and we don't really have the means to run
    the full unwinder here, just collect the link register.  */

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-13  9:53               ` Marcin Kościelnicki
@ 2016-03-14 10:07                 ` Andreas Arnez
  0 siblings, 0 replies; 89+ messages in thread
From: Andreas Arnez @ 2016-03-14 10:07 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Sun, Mar 13 2016, Marcin Kościelnicki wrote:

> On 11/03/16 16:31, Andreas Arnez wrote:
>> On Fri, Mar 11 2016, Marcin Kościelnicki wrote:
>>
>>> We can always error() in there (and KFAIL the testcase in gdb.trace
>>> that exercises it).  However, returning garbage here doesn't result in
>>> garbage backtrace - this only collects data, if the unwinder actually
>>> doing the work later determines it should look for the return address
>>> on the stack, it'll just ignore our collected $r14 and consider the
>>> return address unavailable (unless another collect rule happened to
>>> match it).
>>
>> Well, from that test case it appears that `$_ret' is generally not
>> expected to work very reliably.  Since r14 usually does work near
>> function entry, this may be sufficient for now.
>>
>> So I'm OK with the patch.  Please add a small comment stating that this
>> is a best-can-do approach that usually works near function entry and may
>> yield wrong results otherwise.
>>
>
> Thanks, pushed with this comment:
>
> /* The "gen_return_address" gdbarch method.  Since this is supposed to be
>    just a best-effort method, and we don't really have the means to run
>    the full unwinder here, just collect the link register.  */

Very good, thanks.

-- 
Andreas Arnez

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

* Re: [PATCH v2] gdbserver/s390: Add fast tracepoint support.
  2016-03-04 10:40         ` [PATCH v2] " Marcin Kościelnicki
@ 2016-03-14 16:19           ` Andreas Arnez
  2016-03-14 16:25             ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-03-14 16:19 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches, antoine.tremblay

On Fri, Mar 04 2016, Marcin Kościelnicki wrote:

> Fast tracepoints will only work on 6-byte intructions, and assume at least
> a z900 CPU.  s390 also has 4-byte jump instructions, which also work on
> pre-z900, but their range is limitted to +-64kiB, which is not very useful
> (and wouldn't work at all with current jump pad allocation).
>
> There's a little problem with s390_relocate_instruction function: it
> converts BRAS/BRASL instructions to LARL of the return address + JG
> to the target address.  On 31-bit, this sets the high bit of the target
> register to 0, while BRAS/BRASL would set it to 1.  While this is not
> a problem when the result is only used to address memory, it could
> possibly break something that expects to compare such addresses for
> equality without first masking the bit off.  In particular, I'm not sure
> whether leaving the return address high bit unset is ABI-compliant
> (could confuse some unwinder?).  If that's a problem, it could be fixed
> by handling it in the jump pad (since at that point we can just modify
> the GPRs in the save area without having to worry about preserving
> CCs and only having that one GPR to work with - I'm not sure if it's
> even possible to set the high bit with such constraints).
>
> gdb/gdbserver/ChangeLog:
>
> 	* Makefile.in: Add s390 IPA files.
> 	* configure.srv: Build IPA for s390.
> 	* linux-s390-ipa.c: New file.
> 	* linux-s390-low.c: New includes - inttypes.h and linux-s390-tdesc.h.
> 	(init_registers_s390_linux32): Move declaration to linux-s390-tdesc.h.
> 	(tdesc_s390_linux32): Ditto.
> 	(init_registers_s390_linux32v1): Ditto.
> 	(tdesc_s390_linux32v1): Ditto.
> 	(init_registers_s390_linux32v2): Ditto.
> 	(tdesc_s390_linux32v2): Ditto.
> 	(init_registers_s390_linux64): Ditto.
> 	(tdesc_s390_linux64): Ditto.
> 	(init_registers_s390_linux64v1): Ditto.
> 	(tdesc_s390_linux64v1): Ditto.
> 	(init_registers_s390_linux64v2): Ditto.
> 	(tdesc_s390_linux64v2): Ditto.
> 	(init_registers_s390_te_linux64): Ditto.
> 	(tdesc_s390_te_linux64): Ditto.
> 	(init_registers_s390_vx_linux64): Ditto.
> 	(tdesc_s390_vx_linux64): Ditto.
> 	(init_registers_s390_tevx_linux64): Ditto.
> 	(tdesc_s390_tevx_linux64): Ditto.
> 	(init_registers_s390x_linux64): Ditto.
> 	(tdesc_s390x_linux64): Ditto.
> 	(init_registers_s390x_linux64v1): Ditto.
> 	(tdesc_s390x_linux64v1): Ditto.
> 	(init_registers_s390x_linux64v2): Ditto.
> 	(tdesc_s390x_linux64v2): Ditto.
> 	(init_registers_s390x_te_linux64): Ditto.
> 	(tdesc_s390x_te_linux64): Ditto.
> 	(init_registers_s390x_vx_linux64): Ditto.
> 	(tdesc_s390x_vx_linux64): Ditto.
> 	(init_registers_s390x_tevx_linux64): Ditto.
> 	(tdesc_s390x_tevx_linux64): Ditto.
> 	(have_hwcap_s390_vx): New static variable.
> 	(s390_arch_setup): Fill have_hwcap_s390_vx.
> 	(s390_get_thread_area): New function.
> 	(s390_ft_entry_gpr_esa): New const.
> 	(s390_ft_entry_gpr_zarch): New const.
> 	(s390_ft_entry_misc): New const.
> 	(s390_ft_entry_fr): New const.
> 	(s390_ft_entry_vr): New const.
> 	(s390_ft_main_31): New const.
> 	(s390_ft_main_64): New const.
> 	(s390_ft_exit_fr): New const.
> 	(s390_ft_exit_vr): New const.
> 	(s390_ft_exit_misc): New const.
> 	(s390_ft_exit_gpr_esa): New const.
> 	(s390_ft_exit_gpr_zarch): New const.
> 	(append_insns): New function.
> 	(s390_relocate_instruction): New function.
> 	(s390_install_fast_tracepoint_jump_pad): New function.
> 	(s390_get_min_fast_tracepoint_insn_len): New function.
> 	(s390_get_ipa_tdesc_idx): New function.
> 	(struct linux_target_ops): Wire in the above functions.
> 	(initialize_low_arch) [!__s390x__]: Don't initialize s390x tdescs.
> 	* linux-s390-tdesc.h: New file.

This is OK, apart from some minor nits (see below).  Note that we
usually say "likewise" instead of "ditto".

> +static int
> +s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
> +{

[...]

> +
> +	  /* XXX: this is not fully correct.  In 31-bit mode, LARL will write
> +	     an address with the top bit 0, while BRAS/BRASL will write it
> +	     with top bit 1.  It should not matter much, since linux compilers
> +	     use BR and not BSM to return from functions, but it could confuse
> +	     some poor stack unwinder.  */

We'll probably keep the logic like that anyway unless it's found to
cause real problems, so better replace the "XXX:" by a mere "Note:".
Also, "linux" should be "GNU/Linux".

> +
> +	  /* We'll now be writing a JG.  */
> +	  mode = 2;
> +	  buf[0] = 0xc0;
> +	  buf[1] = 0xf4;
> +	  ilen = 6;
> +	}
> +
> +      /* Compute the new offset and write it to the buffer.  */
> +      loffset = target - *to;
> +      loffset >>= 1;
> +
> +      if (mode == 1)
> +	{
> +	  int16_t soffset = loffset;
> +	  if (soffset != loffset)
> +	    return 1;
> +	  memcpy (buf+2, &soffset, 2);

"buf+2" -> "buf + 2".

> +	}
> +      else if (mode == 2)
> +	{
> +	  int32_t soffset = loffset;
> +	  if (soffset != loffset && is_64)
> +	    return 1;
> +	  memcpy (buf+2, &soffset, 4);

Same here.

[...]

> +static int
> +s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
> +				       CORE_ADDR tpaddr,
> +				       CORE_ADDR collector,
> +				       CORE_ADDR lockaddr,
> +				       ULONGEST orig_size,
> +				       CORE_ADDR *jump_entry,
> +				       CORE_ADDR *trampoline,
> +				       ULONGEST *trampoline_size,
> +				       unsigned char *jjump_pad_insn,
> +				       ULONGEST *jjump_pad_insn_size,
> +				       CORE_ADDR *adjusted_insn_addr,
> +				       CORE_ADDR *adjusted_insn_addr_end,
> +				       char *err)
> +{
> +  int i;
> +  int64_t loffset;
> +  int32_t offset;
> +  unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 };	/* jg ... */
> +  CORE_ADDR buildaddr = *jump_entry;
> +#ifdef __s390x__
> +  struct regcache *regcache = get_thread_regcache (current_thread, 0);
> +  int is_64 = register_size (regcache->tdesc, 0) == 8;
> +  int is_zarch = is_64 || have_hwcap_s390_high_gprs;
> +  int has_vx = have_hwcap_s390_vx;
> +#else
> +  int is_64 = 0, is_zarch = 0, has_vx = 0;
> +#endif
> +  CORE_ADDR literals[4] = {
> +    tpaddr,
> +    tpoint,
> +    collector,
> +    lockaddr,
> +  };
> +
> +  /* First, store the GPRs.  */
> +  if (!is_zarch)
> +    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa, s390_ft_entry_gpr_esa);
> +  else
> +    append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch, s390_ft_entry_gpr_zarch);

Lines too long.  Also, non-reversed logic might be a bit clearer here
and in further such conditionals below.

[...]

> +
> +  /* Restore the GPRs.  */
> +  if (!is_zarch)
> +    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa, s390_ft_exit_gpr_esa);
> +  else
> +    append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch, s390_ft_exit_gpr_zarch);

Lines too long.

Otherwise the patch looks good to me.

Thanks,
Andreas

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

* Re: [PATCH v2] gdbserver/s390: Add support for compiled agent expressions.
  2016-03-04 10:41   ` [PATCH v2] " Marcin Kościelnicki
@ 2016-03-14 16:19     ` Andreas Arnez
  0 siblings, 0 replies; 89+ messages in thread
From: Andreas Arnez @ 2016-03-14 16:19 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches

On Fri, Mar 04 2016, Marcin Kościelnicki wrote:

> These sequences assume a z900+ CPU, like the rest of fast tracepoint
> support.
>
> gdb/gdbserver/ChangeLog:
>
> 	* linux-s390-low.c (add_insns): New function.
> 	(s390_emit_prologue): New function.
> 	(s390_emit_epilogue): New function.
> 	(s390_emit_add): New function.
> 	(s390_emit_sub): New function.
> 	(s390_emit_mul): New function.
> 	(s390_emit_lsh): New function.
> 	(s390_emit_rsh_signed): New function.
> 	(s390_emit_rsh_unsigned): New function.
> 	(s390_emit_ext): New function.
> 	(s390_emit_log_not): New function.
> 	(s390_emit_bit_and): New function.
> 	(s390_emit_bit_or): New function.
> 	(s390_emit_bit_xor): New function.
> 	(s390_emit_bit_not): New function.
> 	(s390_emit_equal): New function.
> 	(s390_emit_less_signed): New function.
> 	(s390_emit_less_unsigned): New function.
> 	(s390_emit_ref): New function.
> 	(s390_emit_if_goto): New function.
> 	(s390_emit_goto): New function.
> 	(s390_write_goto_address): New function.
> 	(s390_emit_litpool): New function.
> 	(s390_emit_const): New function.
> 	(s390_emit_call): New function.
> 	(s390_emit_reg): New function.
> 	(s390_emit_pop): New function.
> 	(s390_emit_stack_flush): New function.
> 	(s390_emit_zero_ext): New function.
> 	(s390_emit_swap): New function.
> 	(s390_emit_stack_adjust): New function.
> 	(s390_emit_set_r2): New function.
> 	(s390_emit_int_call_1): New function.
> 	(s390_emit_void_call_2): New function.
> 	(s390_emit_eq_goto): New function.
> 	(s390_emit_ne_goto): New function.
> 	(s390_emit_lt_goto): New function.
> 	(s390_emit_le_goto): New function.
> 	(s390_emit_gt_goto): New function.
> 	(s390_emit_ge_goto): New function.
> 	(s390x_emit_prologue): New function.
> 	(s390x_emit_epilogue): New function.
> 	(s390x_emit_add): New function.
> 	(s390x_emit_sub): New function.
> 	(s390x_emit_mul): New function.
> 	(s390x_emit_lsh): New function.
> 	(s390x_emit_rsh_signed): New function.
> 	(s390x_emit_rsh_unsigned): New function.
> 	(s390x_emit_ext): New function.
> 	(s390x_emit_log_not): New function.
> 	(s390x_emit_bit_and): New function.
> 	(s390x_emit_bit_or): New function.
> 	(s390x_emit_bit_xor): New function.
> 	(s390x_emit_bit_not): New function.
> 	(s390x_emit_equal): New function.
> 	(s390x_emit_less_signed): New function.
> 	(s390x_emit_less_unsigned): New function.
> 	(s390x_emit_ref): New function.
> 	(s390x_emit_if_goto): New function.
> 	(s390x_emit_const): New function.
> 	(s390x_emit_call): New function.
> 	(s390x_emit_reg): New function.
> 	(s390x_emit_pop): New function.
> 	(s390x_emit_stack_flush): New function.
> 	(s390x_emit_zero_ext): New function.
> 	(s390x_emit_swap): New function.
> 	(s390x_emit_stack_adjust): New function.
> 	(s390x_emit_int_call_1): New function.
> 	(s390x_emit_void_call_2): New function.
> 	(s390x_emit_eq_goto): New function.
> 	(s390x_emit_ne_goto): New function.
> 	(s390x_emit_lt_goto): New function.
> 	(s390x_emit_le_goto): New function.
> 	(s390x_emit_gt_goto): New function.
> 	(s390x_emit_ge_goto): New function.
> 	(s390_emit_ops): New function.
> 	(struct linux_target_ops): Fill in emit_ops hook.
> ---
> Updated version: deduplicated s390_emit_goto with s390x_emit_goto,
> documentation comments, indent fixes.

This is OK.

One minor nit:

> +static void
> +s390_emit_ext (int arg)
> +{
> +  unsigned char buf[] = {
> +    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
> +    0x8e, 0x20, 0x00, 64-arg,	/* srda %r2, <64-arg> */

The "-" operator should be separated with spaces from its operands.  The
same applies to s390_emit_zero_ext, s390x_emit_ext, and
s390x_emit_zero_ext.

Thanks,
Andreas

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

* Re: [PATCH v2] gdbserver/s390: Add fast tracepoint support.
  2016-03-14 16:19           ` Andreas Arnez
@ 2016-03-14 16:25             ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-14 16:25 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches, antoine.tremblay


>
> Otherwise the patch looks good to me.

Thanks for the review, I'll fix these problems and push once patch #5 is 
OKd.
>
> Thanks,
> Andreas
>

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-11 19:34                         ` Eli Zaretskii
@ 2016-03-15 11:11                           ` Pedro Alves
  2016-03-15 11:23                             ` Andreas Arnez
  0 siblings, 1 reply; 89+ messages in thread
From: Pedro Alves @ 2016-03-15 11:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arnez, koriakin, gdb-patches

On 03/11/2016 07:33 PM, Eli Zaretskii wrote:
>> Cc: arnez@linux.vnet.ibm.com, koriakin@0x04.net, gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Fri, 11 Mar 2016 18:37:22 +0000
>>
>> On 03/11/2016 06:16 PM, Eli Zaretskii wrote:
>>>> Cc: Eli Zaretskii <eliz@gnu.org>,
>>>>           Marcin Kościelnicki
>>>>    <koriakin@0x04.net>,
>>>>           gdb-patches@sourceware.org
>>>> From: Pedro Alves <palves@redhat.com>
>>>> Date: Fri, 11 Mar 2016 17:02:19 +0000
>>>>
>>>>>     @item $_ret
>>>>>     Collect the return address.  This is helpful if you want to see more
>>>>> -of a backtrace.
>>>>> +of a backtrace.  Note that the return address can not always be
>>>>> +determined reliably, and a wrong address may be collected instead.
>>>>> +The reliability is usually higher for tracepoints at function entry.
>>>>
>>>> Hmm, this reads a bit as if the backtrace will be incorrect/bogus
>>>> later on, which is not true.
>>>>
>>>> How about a merge of your suggestion with Marcin's previous reply,
>>>> and some extras on top:
>>>>
>>>> @item $_ret
>>>> Collect the set of memory addresses and/or registers necessary to compute
>>>> the frame's return address.  This is helpful if you want to see
>>>> more of a backtrace.
>>>>
>>>> @emph{Note:} The necessary set can not always be reliability determined up
>>>> front, and the wrong address / registers may end up collected instead.
>>>> The reliability is usually higher for tracepoints at function entry.
>>>> When this happens, backtracing will stop because the return address
>>>> is found unavailable (unless another collect rule happened to match it).
>>>
>>> Maybe it's me, but I don't see the significant difference between
>>> these two versions.
>>
>> I think the original version can be misinterpreted as if the
>> backtrace will show the wrong caller when the wrong address
>> is collected.  This version clarifies that it won't.
> 
> My reading is the other way around: the original version only talks
> about the return address, while the modified one talks about a set of
> addresses.

I see what you mean.  I reverted part of the change, and made
the note say the simpler "location" instead now.

> Anyway, if you are happier with your proposal, I won't object.

Below's what I pushed.

Thanks!

From 45fa2529db961adff41c52c3a560808cb135beb2 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 15 Mar 2016 11:08:52 +0000
Subject: [PATCH] Document possible unreliability of '$_ret'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

gdb/doc/ChangeLog:
2016-03-15  Pedro Alves  <palves@redhat.com>
	    Andreas Arnez  <arnez@linux.vnet.ibm.com>
	    Marcin Kościelnicki  <koriakin@0x04.net>

	* gdb.texinfo (Tracepoint Actions): Document possible
	unreliability of '$_ret'.
---
 gdb/doc/ChangeLog   | 7 +++++++
 gdb/doc/gdb.texinfo | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 3d49085..0606d9d 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,10 @@
+2016-03-15  Pedro Alves  <palves@redhat.com>
+	    Andreas Arnez  <arnez@linux.vnet.ibm.com>
+	    Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.texinfo (Tracepoint Actions): Document possible
+	unreliability of '$_ret'.
+
 2016-03-11  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* gdb.texinfo (Symbols): Document new 'maint info line-table'
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index bf7df35..5f88335 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -12878,6 +12878,13 @@ Collect all local variables.
 Collect the return address.  This is helpful if you want to see more
 of a backtrace.
 
+@emph{Note:} The return address location can not always be reliability
+determined up front, and the wrong address / registers may end up
+collected instead.  On some architectures the reliability is higher
+for tracepoints at function entry, while on others it's the opposite.
+When this happens, backtracing will stop because the return address is
+found unavailable (unless another collect rule happened to match it).
+
 @item $_probe_argc
 Collects the number of arguments from the static probe at which the
 tracepoint is located.
-- 
2.5.0


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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-15 11:11                           ` Pedro Alves
@ 2016-03-15 11:23                             ` Andreas Arnez
  2016-03-15 11:30                               ` Pedro Alves
  0 siblings, 1 reply; 89+ messages in thread
From: Andreas Arnez @ 2016-03-15 11:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Eli Zaretskii, koriakin, gdb-patches

On Tue, Mar 15 2016, Pedro Alves wrote:

> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index bf7df35..5f88335 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -12878,6 +12878,13 @@ Collect all local variables.
>  Collect the return address.  This is helpful if you want to see more
>  of a backtrace.
>
> +@emph{Note:} The return address location can not always be reliability
                                                              ^^^^^^^^^^^
Should be "reliably" ;-)

> +determined up front, and the wrong address / registers may end up
> +collected instead.  On some architectures the reliability is higher
> +for tracepoints at function entry, while on others it's the opposite.
> +When this happens, backtracing will stop because the return address is
> +found unavailable (unless another collect rule happened to match it).
> +
>  @item $_probe_argc
>  Collects the number of arguments from the static probe at which the
>  tracepoint is located.

--
Andreas

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

* Re: [PATCH 4/8] gdb/s390: Fill gen_return_address hook.
  2016-03-15 11:23                             ` Andreas Arnez
@ 2016-03-15 11:30                               ` Pedro Alves
  0 siblings, 0 replies; 89+ messages in thread
From: Pedro Alves @ 2016-03-15 11:30 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: Eli Zaretskii, koriakin, gdb-patches

On 03/15/2016 11:23 AM, Andreas Arnez wrote:
> On Tue, Mar 15 2016, Pedro Alves wrote:
> 
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index bf7df35..5f88335 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -12878,6 +12878,13 @@ Collect all local variables.
>>   Collect the return address.  This is helpful if you want to see more
>>   of a backtrace.
>>
>> +@emph{Note:} The return address location can not always be reliability
>                                                                ^^^^^^^^^^^
> Should be "reliably" ;-)

Bah.  I knew I'd forget something...  Thanks for double checking.

Fixed with the patch below.

From 2a60e18f8fe3bf9512671e02b39acacb484bb8c6 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 15 Mar 2016 11:29:03 +0000
Subject: [PATCH] Fix typo in previous gdb/doc/ commit

Should be s/reliability/reliably/.

gdb/doc/ChangeLog:
2016-03-15  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (Tracepoint Actions): Fix typo.
---
 gdb/doc/ChangeLog   | 4 ++++
 gdb/doc/gdb.texinfo | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 0606d9d..a48d1c4 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,4 +1,8 @@
 2016-03-15  Pedro Alves  <palves@redhat.com>
+
+	* gdb.texinfo (Tracepoint Actions): Fix typo.
+
+2016-03-15  Pedro Alves  <palves@redhat.com>
 	    Andreas Arnez  <arnez@linux.vnet.ibm.com>
 	    Marcin Kościelnicki  <koriakin@0x04.net>
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5f88335..71657b0 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -12878,7 +12878,7 @@ Collect all local variables.
 Collect the return address.  This is helpful if you want to see more
 of a backtrace.
 
-@emph{Note:} The return address location can not always be reliability
+@emph{Note:} The return address location can not always be reliably
 determined up front, and the wrong address / registers may end up
 collected instead.  On some architectures the reliability is higher
 for tracepoints at function entry, while on others it's the opposite.
-- 
2.5.0


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

* [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-04 10:39       ` [PATCH v3] " Marcin Kościelnicki
@ 2016-03-15 18:41         ` Marcin Kościelnicki
  2016-03-22  9:16           ` Marcin Kościelnicki
  2016-03-23 15:25           ` Andreas Arnez
  0 siblings, 2 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-15 18:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Marcin Kościelnicki

Also adds s390 support to gdb.trace testsuite.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (s390_supports_tracepoints): New function.
	(struct linux_target_ops): Fill supports_tracepoints hook.

gdb/testsuite/ChangeLog:

	* gdb.trace/ftrace.exp: Set arg0exp for s390.
	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
	variable for GPR 0 instead of assuming it is register 0.
	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
	* lib/trace-support.exp: Add s390 registers.
---
This fixes a minor conflict with the powerpc regular tracepoint support
pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
powerpc branch).

 gdb/gdbserver/ChangeLog                              |  5 +++++
 gdb/gdbserver/linux-s390-low.c                       | 10 +++++++++-
 gdb/testsuite/ChangeLog                              |  9 +++++++++
 gdb/testsuite/gdb.trace/ftrace.exp                   |  5 +++++
 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 15 ++++++++++++++-
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp     | 19 ++++++++++++++-----
 gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
 gdb/testsuite/lib/trace-support.exp                  |  4 ++++
 8 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index dda87b0..29a2e4d 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,8 @@
+2016-03-15  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* linux-s390-low.c (s390_supports_tracepoints): New function.
+	(struct linux_target_ops): Fill supports_tracepoints hook.
+
 2016-03-09  Marcin Kościelnicki  <koriakin@0x04.net>
 
 	* linux-ppc-low.c (ppc_supports_tracepoints): New function.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 7304feb..2bcfa7a 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -745,6 +745,14 @@ s390_regs_info (void)
   return &regs_info;
 }
 
+/* The "supports_tracepoints" linux_target_ops method.  */
+
+static int
+s390_supports_tracepoints (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -771,7 +779,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
+  s390_supports_tracepoints,
   NULL, /* get_thread_area */
   NULL, /* install_fast_tracepoint_jump_pad */
   NULL, /* emit_ops */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index eec8604..9c0fb1b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2016-03-15  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* gdb.trace/ftrace.exp: Set arg0exp for s390.
+	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
+	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
+	variable for GPR 0 instead of assuming it is register 0.
+	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
+	* lib/trace-support.exp: Add s390 registers.
+
 2016-03-14  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* gdb.base/default.exp: Add $_as_string to the list of expected
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index 349f4e2..4736f0f 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -244,6 +244,11 @@ if [is_amd64_regs_target] {
     set arg0exp "\$x0"
 } elseif [istarget "powerpc*-*-*"] {
     set arg0exp "\$r3"
+} elseif { [istarget "s390x-*-*"] } {
+    set arg0exp "\$r2"
+} elseif { [istarget "s390-*-*"] } {
+    # On targets with 64-bit GPRs, avoid the high part.
+    set arg0exp "(\$r2 & 0xffffffff)"
 } else {
     set arg0exp ""
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 0daaa25..a69c329 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -91,10 +91,23 @@ proc test_trace_frame_collected { data_source } {
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \
 	    "-trace-find frame-number 0"
 
+	set reg_pattern "\{number=\"$decimal\",value=\"$hex\"\}"
+
 	# Test MI command '-trace-frame-collected' dumps only
 	# collected registers.
+	if { [istarget "s390*-*-*"] } {
+	    # Only PC is collected, but on s390 PC is a pseudo-register -
+	    # collecting it also collects the underlying PSWA register.
+	    if { "$data_source" != "tfile" } {
+		set reg_pattern "$reg_pattern,$reg_pattern"
+	    } else {
+		# For tfile, PSWM and CC are also guessed.
+		set reg_pattern "$reg_pattern,$reg_pattern,$reg_pattern,$reg_pattern"
+	    }
+	}
+
 	mi_gdb_test "-trace-frame-collected" \
-	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
+	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[$reg_pattern\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
 	    "-trace-frame-collected (register)"
 
 	mi_gdb_test "-trace-find frame-number 1" \
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 4228c97..a49cd17 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -130,30 +130,39 @@ proc test_trace_unavailable { data_source } {
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
 	    "-trace-find frame-number 1"
 
-	set pcnum 0
+	set pcnum -1
+	set gpr0num -1
 	if [is_amd64_regs_target] {
 	    set pcnum 16
+	    set gpr0num 0
 	} elseif [is_x86_like_target] {
 	    set pcnum 8
+	    set gpr0num 0
 	} elseif [is_aarch64_target] {
 	    set pcnum 32
+	    set gpr0num 0
 	} elseif [istarget "powerpc*-*-*"] {
 	    set pcnum 64
+	    set gpr0num 0
+	} elseif { [istarget "s390*-*-*"] } {
+	    # Strictly speaking, this is PSWA, not PC.
+	    set pcnum 1
+	    set gpr0num 2
 	} else {
 	    # Other ports support tracepoint should define the number
 	    # of its own pc register.
 	}
 
-	if { $pcnum != 0 } {
+	if { $pcnum != -1 } {
 	    global hex
 	    # Test that register 0 and PC are displayed, and register
 	    # 0 is unavailable.
-	    mi_gdb_test "-data-list-register-values x 0 ${pcnum}" \
-		".*\\^done,register-values=\\\[\{number=\"0\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
+	    mi_gdb_test "-data-list-register-values x ${gpr0num} ${pcnum}" \
+		".*\\^done,register-values=\\\[\{number=\"${gpr0num}\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
 		"-data-list-register-values x"
 
 	    # Test that only available register PC is displayed.
-	    mi_gdb_test "-data-list-register-values --skip-unavailable x 0 ${pcnum}" \
+	    mi_gdb_test "-data-list-register-values --skip-unavailable x ${gpr0num} ${pcnum}" \
 		".*\\^done,register-values=\\\[\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
 		"-data-list-register-values --skip-unavailable x"
 	}
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index fa99fd9..60cf9e8 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -48,6 +48,14 @@ x86_trace_dummy ()
        "    nop\n" \
        )
 
+#elif (defined __s390__)
+
+#define FAST_TRACEPOINT_LABEL(name) \
+  asm ("    .global " SYMBOL(name) "\n" \
+       SYMBOL(name) ":\n" \
+       "    mvc 0(8, %r15), 0(%r15)\n" \
+       )
+
 #else
 
 #error "unsupported architecture for trace tests"
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
index 372a595..b307f3f 100644
--- a/gdb/testsuite/lib/trace-support.exp
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -40,6 +40,10 @@ if [is_amd64_regs_target] {
     set fpreg "r31"
     set spreg "r1"
     set pcreg "pc"
+} elseif { [istarget "s390*-*-*"] } {
+    set fpreg "r11"
+    set spreg "r15"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
-- 
2.7.2

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

* Re: [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-15 18:41         ` [PATCH v4] " Marcin Kościelnicki
@ 2016-03-22  9:16           ` Marcin Kościelnicki
  2016-03-23 15:25           ` Andreas Arnez
  1 sibling, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-22  9:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andreas Arnez

Ping.

On 15/03/16 19:41, Marcin Kościelnicki wrote:
> Also adds s390 support to gdb.trace testsuite.
>
> gdb/gdbserver/ChangeLog:
>
> 	* linux-s390-low.c (s390_supports_tracepoints): New function.
> 	(struct linux_target_ops): Fill supports_tracepoints hook.
>
> gdb/testsuite/ChangeLog:
>
> 	* gdb.trace/ftrace.exp: Set arg0exp for s390.
> 	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
> 	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
> 	variable for GPR 0 instead of assuming it is register 0.
> 	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
> 	* lib/trace-support.exp: Add s390 registers.
> ---
> This fixes a minor conflict with the powerpc regular tracepoint support
> pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
> powerpc branch).
>
>   gdb/gdbserver/ChangeLog                              |  5 +++++
>   gdb/gdbserver/linux-s390-low.c                       | 10 +++++++++-
>   gdb/testsuite/ChangeLog                              |  9 +++++++++
>   gdb/testsuite/gdb.trace/ftrace.exp                   |  5 +++++
>   gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp | 15 ++++++++++++++-
>   gdb/testsuite/gdb.trace/mi-trace-unavailable.exp     | 19 ++++++++++++++-----
>   gdb/testsuite/gdb.trace/trace-common.h               |  8 ++++++++
>   gdb/testsuite/lib/trace-support.exp                  |  4 ++++
>   8 files changed, 68 insertions(+), 7 deletions(-)
>
> diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
> index dda87b0..29a2e4d 100644
> --- a/gdb/gdbserver/ChangeLog
> +++ b/gdb/gdbserver/ChangeLog
> @@ -1,3 +1,8 @@
> +2016-03-15  Marcin Kościelnicki  <koriakin@0x04.net>
> +
> +	* linux-s390-low.c (s390_supports_tracepoints): New function.
> +	(struct linux_target_ops): Fill supports_tracepoints hook.
> +
>   2016-03-09  Marcin Kościelnicki  <koriakin@0x04.net>
>
>   	* linux-ppc-low.c (ppc_supports_tracepoints): New function.
> diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
> index 7304feb..2bcfa7a 100644
> --- a/gdb/gdbserver/linux-s390-low.c
> +++ b/gdb/gdbserver/linux-s390-low.c
> @@ -745,6 +745,14 @@ s390_regs_info (void)
>     return &regs_info;
>   }
>
> +/* The "supports_tracepoints" linux_target_ops method.  */
> +
> +static int
> +s390_supports_tracepoints (void)
> +{
> +  return 1;
> +}
> +
>   struct linux_target_ops the_low_target = {
>     s390_arch_setup,
>     s390_regs_info,
> @@ -771,7 +779,7 @@ struct linux_target_ops the_low_target = {
>     NULL, /* new_fork */
>     NULL, /* prepare_to_resume */
>     NULL, /* process_qsupported */
> -  NULL, /* supports_tracepoints */
> +  s390_supports_tracepoints,
>     NULL, /* get_thread_area */
>     NULL, /* install_fast_tracepoint_jump_pad */
>     NULL, /* emit_ops */
> diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
> index eec8604..9c0fb1b 100644
> --- a/gdb/testsuite/ChangeLog
> +++ b/gdb/testsuite/ChangeLog
> @@ -1,3 +1,12 @@
> +2016-03-15  Marcin Kościelnicki  <koriakin@0x04.net>
> +
> +	* gdb.trace/ftrace.exp: Set arg0exp for s390.
> +	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
> +	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
> +	variable for GPR 0 instead of assuming it is register 0.
> +	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
> +	* lib/trace-support.exp: Add s390 registers.
> +
>   2016-03-14  Simon Marchi  <simon.marchi@ericsson.com>
>
>   	* gdb.base/default.exp: Add $_as_string to the list of expected
> diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
> index 349f4e2..4736f0f 100644
> --- a/gdb/testsuite/gdb.trace/ftrace.exp
> +++ b/gdb/testsuite/gdb.trace/ftrace.exp
> @@ -244,6 +244,11 @@ if [is_amd64_regs_target] {
>       set arg0exp "\$x0"
>   } elseif [istarget "powerpc*-*-*"] {
>       set arg0exp "\$r3"
> +} elseif { [istarget "s390x-*-*"] } {
> +    set arg0exp "\$r2"
> +} elseif { [istarget "s390-*-*"] } {
> +    # On targets with 64-bit GPRs, avoid the high part.
> +    set arg0exp "(\$r2 & 0xffffffff)"
>   } else {
>       set arg0exp ""
>   }
> diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
> index 0daaa25..a69c329 100644
> --- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
> +++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
> @@ -91,10 +91,23 @@ proc test_trace_frame_collected { data_source } {
>   	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \
>   	    "-trace-find frame-number 0"
>
> +	set reg_pattern "\{number=\"$decimal\",value=\"$hex\"\}"
> +
>   	# Test MI command '-trace-frame-collected' dumps only
>   	# collected registers.
> +	if { [istarget "s390*-*-*"] } {
> +	    # Only PC is collected, but on s390 PC is a pseudo-register -
> +	    # collecting it also collects the underlying PSWA register.
> +	    if { "$data_source" != "tfile" } {
> +		set reg_pattern "$reg_pattern,$reg_pattern"
> +	    } else {
> +		# For tfile, PSWM and CC are also guessed.
> +		set reg_pattern "$reg_pattern,$reg_pattern,$reg_pattern,$reg_pattern"
> +	    }
> +	}
> +
>   	mi_gdb_test "-trace-frame-collected" \
> -	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
> +	    "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[$reg_pattern\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\
>   	    "-trace-frame-collected (register)"
>
>   	mi_gdb_test "-trace-find frame-number 1" \
> diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
> index 4228c97..a49cd17 100644
> --- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
> +++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
> @@ -130,30 +130,39 @@ proc test_trace_unavailable { data_source } {
>   	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
>   	    "-trace-find frame-number 1"
>
> -	set pcnum 0
> +	set pcnum -1
> +	set gpr0num -1
>   	if [is_amd64_regs_target] {
>   	    set pcnum 16
> +	    set gpr0num 0
>   	} elseif [is_x86_like_target] {
>   	    set pcnum 8
> +	    set gpr0num 0
>   	} elseif [is_aarch64_target] {
>   	    set pcnum 32
> +	    set gpr0num 0
>   	} elseif [istarget "powerpc*-*-*"] {
>   	    set pcnum 64
> +	    set gpr0num 0
> +	} elseif { [istarget "s390*-*-*"] } {
> +	    # Strictly speaking, this is PSWA, not PC.
> +	    set pcnum 1
> +	    set gpr0num 2
>   	} else {
>   	    # Other ports support tracepoint should define the number
>   	    # of its own pc register.
>   	}
>
> -	if { $pcnum != 0 } {
> +	if { $pcnum != -1 } {
>   	    global hex
>   	    # Test that register 0 and PC are displayed, and register
>   	    # 0 is unavailable.
> -	    mi_gdb_test "-data-list-register-values x 0 ${pcnum}" \
> -		".*\\^done,register-values=\\\[\{number=\"0\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
> +	    mi_gdb_test "-data-list-register-values x ${gpr0num} ${pcnum}" \
> +		".*\\^done,register-values=\\\[\{number=\"${gpr0num}\",value=\"<unavailable>\"\},\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
>   		"-data-list-register-values x"
>
>   	    # Test that only available register PC is displayed.
> -	    mi_gdb_test "-data-list-register-values --skip-unavailable x 0 ${pcnum}" \
> +	    mi_gdb_test "-data-list-register-values --skip-unavailable x ${gpr0num} ${pcnum}" \
>   		".*\\^done,register-values=\\\[\{number=\"${pcnum}\",value=\"${hex}\"\}\\\]" \
>   		"-data-list-register-values --skip-unavailable x"
>   	}
> diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
> index fa99fd9..60cf9e8 100644
> --- a/gdb/testsuite/gdb.trace/trace-common.h
> +++ b/gdb/testsuite/gdb.trace/trace-common.h
> @@ -48,6 +48,14 @@ x86_trace_dummy ()
>          "    nop\n" \
>          )
>
> +#elif (defined __s390__)
> +
> +#define FAST_TRACEPOINT_LABEL(name) \
> +  asm ("    .global " SYMBOL(name) "\n" \
> +       SYMBOL(name) ":\n" \
> +       "    mvc 0(8, %r15), 0(%r15)\n" \
> +       )
> +
>   #else
>
>   #error "unsupported architecture for trace tests"
> diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
> index 372a595..b307f3f 100644
> --- a/gdb/testsuite/lib/trace-support.exp
> +++ b/gdb/testsuite/lib/trace-support.exp
> @@ -40,6 +40,10 @@ if [is_amd64_regs_target] {
>       set fpreg "r31"
>       set spreg "r1"
>       set pcreg "pc"
> +} elseif { [istarget "s390*-*-*"] } {
> +    set fpreg "r11"
> +    set spreg "r15"
> +    set pcreg "pc"
>   } else {
>       set fpreg "fp"
>       set spreg "sp"
>

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

* Re: [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-15 18:41         ` [PATCH v4] " Marcin Kościelnicki
  2016-03-22  9:16           ` Marcin Kościelnicki
@ 2016-03-23 15:25           ` Andreas Arnez
  2016-03-24  1:15             ` Marcin Kościelnicki
  2016-03-29 21:40             ` [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints Marcin Kościelnicki
  1 sibling, 2 replies; 89+ messages in thread
From: Andreas Arnez @ 2016-03-23 15:25 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: gdb-patches, Keith Seitz, Ulrich Weigand

On Tue, Mar 15 2016, Marcin Kościelnicki wrote:

> Also adds s390 support to gdb.trace testsuite.
>
> gdb/gdbserver/ChangeLog:
>
> 	* linux-s390-low.c (s390_supports_tracepoints): New function.
> 	(struct linux_target_ops): Fill supports_tracepoints hook.
>
> gdb/testsuite/ChangeLog:
>
> 	* gdb.trace/ftrace.exp: Set arg0exp for s390.
> 	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
> 	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
> 	variable for GPR 0 instead of assuming it is register 0.
> 	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
> 	* lib/trace-support.exp: Add s390 registers.
> ---
> This fixes a minor conflict with the powerpc regular tracepoint support
> pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
> powerpc branch).

Please also document this new feature in the NEWS file.

[...]

> diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
> index 372a595..b307f3f 100644
> --- a/gdb/testsuite/lib/trace-support.exp
> +++ b/gdb/testsuite/lib/trace-support.exp
> @@ -40,6 +40,10 @@ if [is_amd64_regs_target] {
>      set fpreg "r31"
>      set spreg "r1"
>      set pcreg "pc"
> +} elseif { [istarget "s390*-*-*"] } {
> +    set fpreg "r11"
> +    set spreg "r15"
> +    set pcreg "pc"
>  } else {
>      set fpreg "fp"
>      set spreg "sp"

Without having looked into the details I wonder why we can't use the
default, fp, sp, and pc.  Also, I'd slightly prefer initializing these
variables with their default values first and then adjusting them per
target as required.  (This is just a matter of taste.)

Otherwise the patch looks good to me.  But I think a global- or
testsuite-maintainer should approve the changes to the testsuite.

Thanks,
Andreas

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

* Re: [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-23 15:25           ` Andreas Arnez
@ 2016-03-24  1:15             ` Marcin Kościelnicki
  2016-03-29 18:31               ` Ulrich Weigand
  2016-03-29 21:40             ` [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints Marcin Kościelnicki
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-24  1:15 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches, Keith Seitz, Ulrich Weigand

On 23/03/16 16:25, Andreas Arnez wrote:
> On Tue, Mar 15 2016, Marcin Kościelnicki wrote:
>
>> Also adds s390 support to gdb.trace testsuite.
>>
>> gdb/gdbserver/ChangeLog:
>>
>> 	* linux-s390-low.c (s390_supports_tracepoints): New function.
>> 	(struct linux_target_ops): Fill supports_tracepoints hook.
>>
>> gdb/testsuite/ChangeLog:
>>
>> 	* gdb.trace/ftrace.exp: Set arg0exp for s390.
>> 	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
>> 	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
>> 	variable for GPR 0 instead of assuming it is register 0.
>> 	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
>> 	* lib/trace-support.exp: Add s390 registers.
>> ---
>> This fixes a minor conflict with the powerpc regular tracepoint support
>> pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
>> powerpc branch).
>
> Please also document this new feature in the NEWS file.

OK, I'll submit another patch adding the NEWS entry (it should go after 
the fast tracepoints).
>
> [...]
>
>> diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
>> index 372a595..b307f3f 100644
>> --- a/gdb/testsuite/lib/trace-support.exp
>> +++ b/gdb/testsuite/lib/trace-support.exp
>> @@ -40,6 +40,10 @@ if [is_amd64_regs_target] {
>>       set fpreg "r31"
>>       set spreg "r1"
>>       set pcreg "pc"
>> +} elseif { [istarget "s390*-*-*"] } {
>> +    set fpreg "r11"
>> +    set spreg "r15"
>> +    set pcreg "pc"
>>   } else {
>>       set fpreg "fp"
>>       set spreg "sp"
>
> Without having looked into the details I wonder why we can't use the
> default, fp, sp, and pc.  Also, I'd slightly prefer initializing these
> variables with their default values first and then adjusting them per
> target as required.  (This is just a matter of taste.)

These are user registers, which are not supported by the 
target-independent tracepoint code:

'sp' is a user-register; GDB cannot yet trace user-register contents.

>
> Otherwise the patch looks good to me.  But I think a global- or
> testsuite-maintainer should approve the changes to the testsuite.
>
> Thanks,
> Andreas
>

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

* Re: [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-24  1:15             ` Marcin Kościelnicki
@ 2016-03-29 18:31               ` Ulrich Weigand
  2016-03-29 21:40                 ` Marcin Kościelnicki
  0 siblings, 1 reply; 89+ messages in thread
From: Ulrich Weigand @ 2016-03-29 18:31 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: Andreas Arnez, gdb-patches, Keith Seitz

Marcin Kościelnicki wrote:
> On 23/03/16 16:25, Andreas Arnez wrote:
> > On Tue, Mar 15 2016, Marcin Kościelnicki wrote:
> >
> >> Also adds s390 support to gdb.trace testsuite.
> >>
> >> gdb/gdbserver/ChangeLog:
> >>
> >> 	* linux-s390-low.c (s390_supports_tracepoints): New function.
> >> 	(struct linux_target_ops): Fill supports_tracepoints hook.
> >>
> >> gdb/testsuite/ChangeLog:
> >>
> >> 	* gdb.trace/ftrace.exp: Set arg0exp for s390.
> >> 	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
> >> 	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
> >> 	variable for GPR 0 instead of assuming it is register 0.
> >> 	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
> >> 	* lib/trace-support.exp: Add s390 registers.
> >> ---
> >> This fixes a minor conflict with the powerpc regular tracepoint support
> >> pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
> >> powerpc branch).
> >
> > Please also document this new feature in the NEWS file.
> 
> OK, I'll submit another patch adding the NEWS entry (it should go after 
> the fast tracepoints).

> > Otherwise the patch looks good to me.  But I think a global- or
> > testsuite-maintainer should approve the changes to the testsuite.

Those changes are OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v4] gdbserver/s390: Switch on tracepoint support.
  2016-03-29 18:31               ` Ulrich Weigand
@ 2016-03-29 21:40                 ` Marcin Kościelnicki
  0 siblings, 0 replies; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-29 21:40 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Andreas Arnez, gdb-patches, Keith Seitz

On 29/03/16 20:30, Ulrich Weigand wrote:
> Marcin Kościelnicki wrote:
>> On 23/03/16 16:25, Andreas Arnez wrote:
>>> On Tue, Mar 15 2016, Marcin Kościelnicki wrote:
>>>
>>>> Also adds s390 support to gdb.trace testsuite.
>>>>
>>>> gdb/gdbserver/ChangeLog:
>>>>
>>>> 	* linux-s390-low.c (s390_supports_tracepoints): New function.
>>>> 	(struct linux_target_ops): Fill supports_tracepoints hook.
>>>>
>>>> gdb/testsuite/ChangeLog:
>>>>
>>>> 	* gdb.trace/ftrace.exp: Set arg0exp for s390.
>>>> 	* gdb.trace/mi-trace-frame-collected.exp: Expect 4 registers on s390.
>>>> 	* gdb.trace/mi-trace-unavailable.exp: Set pcnum for s390, add gpr0num
>>>> 	variable for GPR 0 instead of assuming it is register 0.
>>>> 	* gdb.trace/trace-common.h: Add s390 fast tracepoint placeholder.
>>>> 	* lib/trace-support.exp: Add s390 registers.
>>>> ---
>>>> This fixes a minor conflict with the powerpc regular tracepoint support
>>>> pushed in the meantime (mi-trace-unavailable.exp now needs gpr0num in
>>>> powerpc branch).
>>>
>>> Please also document this new feature in the NEWS file.
>>
>> OK, I'll submit another patch adding the NEWS entry (it should go after
>> the fast tracepoints).
>
>>> Otherwise the patch looks good to me.  But I think a global- or
>>> testsuite-maintainer should approve the changes to the testsuite.
>
> Those changes are OK.
>
> Thanks,
> Ulrich
>

Thanks, pushed.

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

* [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints.
  2016-03-23 15:25           ` Andreas Arnez
  2016-03-24  1:15             ` Marcin Kościelnicki
@ 2016-03-29 21:40             ` Marcin Kościelnicki
  2016-03-30  2:49               ` Eli Zaretskii
  1 sibling, 1 reply; 89+ messages in thread
From: Marcin Kościelnicki @ 2016-03-29 21:40 UTC (permalink / raw)
  To: arnez; +Cc: uweigand, gdb-patches, Marcin Kościelnicki

gdb/ChangeLog:

	* NEWS: Mention support for tracepoints on s390*-linux.
---
Here's the promised NEWS entry, pushed as obvious.

 gdb/ChangeLog | 4 ++++
 gdb/NEWS      | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d0f8e7f..25afbef 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2016-03-29  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* NEWS: Mention support for tracepoints on s390*-linux.
+
 2016-03-29  Don Breazeal  <donb@codesourcery.com>
 
 	* gdb/value.c (value_actual_type): Fix formatting issue.
diff --git a/gdb/NEWS b/gdb/NEWS
index 34c5a8d..ce031ee 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -37,6 +37,10 @@ skip -rfunction regular-expression
 maint info line-table REGEXP
   Display the contents of GDB's internal line table data struture.
 
+* Support for tracepoints and fast tracepoints on s390-linux and s390x-linux
+  was added in GDBserver, including JIT compiling fast tracepoint's
+  conditional expression bytecode into native code.
+
 *** Changes in GDB 7.11
 
 * GDB now supports debugging kernel-based threads on FreeBSD.
-- 
2.7.4

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

* Re: [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints.
  2016-03-29 21:40             ` [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints Marcin Kościelnicki
@ 2016-03-30  2:49               ` Eli Zaretskii
  0 siblings, 0 replies; 89+ messages in thread
From: Eli Zaretskii @ 2016-03-30  2:49 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: arnez, uweigand, gdb-patches, koriakin

> From: Marcin Kościelnicki <koriakin@0x04.net>
> Cc: uweigand@de.ibm.com,	gdb-patches@sourceware.org,	Marcin Kościelnicki <koriakin@0x04.net>
> Date: Tue, 29 Mar 2016 23:40:26 +0200
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 34c5a8d..ce031ee 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -37,6 +37,10 @@ skip -rfunction regular-expression
>  maint info line-table REGEXP
>    Display the contents of GDB's internal line table data struture.
>  
> +* Support for tracepoints and fast tracepoints on s390-linux and s390x-linux
> +  was added in GDBserver, including JIT compiling fast tracepoint's
> +  conditional expression bytecode into native code.

OK, thanks.

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

end of thread, other threads:[~2016-03-30  2:49 UTC | newest]

Thread overview: 89+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
2016-01-26 18:17   ` Andreas Arnez
2016-01-29  9:53     ` [PATCH] " Marcin Kościelnicki
2016-02-12 11:20       ` Yao Qi
2016-02-18 18:54       ` Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook Marcin Kościelnicki
2016-01-26 18:12   ` Andreas Arnez
2016-01-26 19:26     ` Marcin Kościelnicki
2016-01-29 18:57       ` Andreas Arnez
2016-02-07 14:00         ` [PATCH 2/8] gdb/s390: Fill supply_pseudo_pc hook Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 4/8] gdb/s390: Fill gen_return_address hook Marcin Kościelnicki
2016-02-07 14:02   ` Marcin Kościelnicki
2016-02-25 19:23     ` Marcin Kościelnicki
2016-03-04 10:42       ` Marcin Kościelnicki
2016-03-11 11:20     ` Andreas Arnez
2016-03-11 11:35       ` Marcin Kościelnicki
2016-03-11 12:18         ` Andreas Arnez
2016-03-11 12:26           ` Marcin Kościelnicki
2016-03-11 15:31             ` Andreas Arnez
2016-03-11 15:44               ` Pedro Alves
2016-03-11 16:45                 ` Andreas Arnez
2016-03-11 17:02                   ` Pedro Alves
2016-03-11 18:17                     ` Eli Zaretskii
2016-03-11 18:37                       ` Pedro Alves
2016-03-11 19:34                         ` Eli Zaretskii
2016-03-15 11:11                           ` Pedro Alves
2016-03-15 11:23                             ` Andreas Arnez
2016-03-15 11:30                               ` Pedro Alves
2016-03-11 18:07                   ` Eli Zaretskii
2016-03-13  9:53               ` Marcin Kościelnicki
2016-03-14 10:07                 ` Andreas Arnez
2016-01-24 12:12 ` [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions Marcin Kościelnicki
2016-03-04 10:41   ` [PATCH v2] " Marcin Kościelnicki
2016-03-14 16:19     ` Andreas Arnez
2016-01-24 12:12 ` [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch Marcin Kościelnicki
2016-01-26 14:58   ` Andreas Arnez
2016-02-07 13:59     ` [PATCH 1/8] gdb: Add supply_pseudo_pc " Marcin Kościelnicki
2016-02-16 18:28       ` Ulrich Weigand
2016-02-16 21:32         ` Marcin Kościelnicki
2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
2016-02-18 10:35           ` [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook Marcin Kościelnicki
2016-02-18 16:03             ` Ulrich Weigand
2016-02-18 16:36               ` [PATCH] " Marcin Kościelnicki
2016-02-18 16:48                 ` Ulrich Weigand
2016-02-18 16:58                   ` Marcin Kościelnicki
2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
2016-02-18 11:39             ` Marcin Kościelnicki
2016-02-18 11:45             ` [PATCH] " Marcin Kościelnicki
2016-02-18 15:40               ` Ulrich Weigand
2016-02-18 15:41                 ` Marcin Kościelnicki
2016-02-18 15:58                   ` Ulrich Weigand
2016-02-18 16:01                     ` Marcin Kościelnicki
2016-02-18 16:06                       ` Ulrich Weigand
2016-02-18 16:11                         ` Marcin Kościelnicki
2016-02-18 16:13                           ` Ulrich Weigand
2016-02-18 16:22                             ` Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 5/8] gdbserver/s390: Switch on tracepoint support Marcin Kościelnicki
2016-02-07 14:04   ` Marcin Kościelnicki
2016-02-22  7:38     ` [PATCH] " Marcin Kościelnicki
2016-03-04 10:39       ` [PATCH v3] " Marcin Kościelnicki
2016-03-15 18:41         ` [PATCH v4] " Marcin Kościelnicki
2016-03-22  9:16           ` Marcin Kościelnicki
2016-03-23 15:25           ` Andreas Arnez
2016-03-24  1:15             ` Marcin Kościelnicki
2016-03-29 18:31               ` Ulrich Weigand
2016-03-29 21:40                 ` Marcin Kościelnicki
2016-03-29 21:40             ` [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints Marcin Kościelnicki
2016-03-30  2:49               ` Eli Zaretskii
2016-01-24 12:12 ` [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks Marcin Kościelnicki
2016-02-07 14:01   ` Marcin Kościelnicki
2016-02-25 19:23     ` Marcin Kościelnicki
2016-03-04 10:42       ` Marcin Kościelnicki
2016-03-11  2:20         ` Marcin Kościelnicki
2016-03-11  9:58     ` Andreas Arnez
2016-03-11 10:04       ` Marcin Kościelnicki
2016-01-24 12:13 ` [PATCH 6/8] gdbserver/s390: Add fast tracepoint support Marcin Kościelnicki
2016-01-25 14:34   ` Antoine Tremblay
2016-02-19 13:41     ` Marcin Kościelnicki
2016-02-19 14:41       ` Antoine Tremblay
2016-03-04 10:40         ` [PATCH v2] " Marcin Kościelnicki
2016-03-14 16:19           ` Andreas Arnez
2016-03-14 16:25             ` Marcin Kościelnicki
2016-01-25 13:27 ` [PATCH 0/8] gdb/s390: Add regular and " Antoine Tremblay
2016-01-25 13:56 ` Pedro Alves
2016-01-25 14:28   ` Marcin Kościelnicki
2016-01-25 15:57     ` Pedro Alves
2016-01-25 16:03       ` Marcin Kościelnicki
2016-02-12 11:04 ` Marcin Kościelnicki

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