s390: Initial support for s390x

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
diff --git a/include/sframe-api.h b/include/sframe-api.h
index 280e285..3723760 100644
--- a/include/sframe-api.h
+++ b/include/sframe-api.h
@@ -152,6 +152,13 @@
 sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc,
 		 sframe_frame_row_entry *frep);
 
+/* Find the first SFrame Row Entry of the SFrame Function Descriptor Entry
+   which contains the PC.  Returns SFRAME_ERR if failure.  */
+
+int
+sframe_find_fre0 (sframe_decoder_ctx *ctx, int32_t pc,
+		  sframe_frame_row_entry *frep);
+
 /* Get the FRE_IDX'th FRE of the function at FUNC_IDX'th function
    index entry in the SFrame decoder CTX.  Returns error code as
    applicable.  */
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index 460face..d112d7c 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -1159,6 +1159,40 @@
   return sframe_set_errno (&err, SFRAME_ERR_FDE_INVAL);
 }
 
+/* Find the first SFrame Row Entry of the SFrame Function Descriptor Entry
+   which contains the PC.  Returns SFRAME_ERR if failure.  */
+
+int
+sframe_find_fre0 (sframe_decoder_ctx *ctx, int32_t pc,
+		  sframe_frame_row_entry *frep)
+{
+  sframe_frame_row_entry cur_fre;
+  sframe_func_desc_entry *fdep;
+  uint32_t fre_type;
+  const char *fres;
+  size_t size = 0;
+  int err = 0;
+
+  if ((ctx == NULL) || (frep == NULL))
+    return sframe_set_errno (&err, SFRAME_ERR_INVAL);
+
+  /* Find the FDE which contains the PC, then scan its fre entries.  */
+  fdep = sframe_get_funcdesc_with_addr_internal (ctx, pc, &err);
+  if (fdep == NULL || ctx->sfd_fres == NULL)
+    return sframe_set_errno (&err, SFRAME_ERR_DCTX_INVAL);
+
+  fre_type = sframe_get_fre_type (fdep);
+
+  fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off;
+
+  err = sframe_decode_fre (fres, &cur_fre, fre_type, &size);
+  if (err)
+    return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL);
+
+  sframe_frame_row_entry_copy (frep, &cur_fre);
+  return 0;
+}
+
 /* Return the number of function descriptor entries in the SFrame decoder
    DCTX.  */
 
diff --git a/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace-regs.h b/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace-regs.h
index 88da50b..ca68918 100644
--- a/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace-regs.h
+++ b/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace-regs.h
@@ -77,6 +77,33 @@
   return cp->uc_mcontext.regs[UNWIND_AARCH64_X30];
 }
 
+#elif defined (__s390x__)
+
+static inline uint64_t
+get_context_pc (ucontext_t *cp)
+{
+//  return cp->uc_mcontext.psw.addr;
+  return cp->uc_mcontext.gregs[14];
+}
+
+static inline uint64_t
+get_context_rsp (ucontext_t *cp)
+{
+  return cp->uc_mcontext.gregs[15];
+}
+
+static inline uint64_t
+get_context_rfp (ucontext_t *cp)
+{
+  return cp->uc_mcontext.gregs[11];
+}
+
+static inline uint64_t
+get_context_ra (ucontext_t *cp)
+{
+  return cp->uc_mcontext.gregs[14];
+}
+
 #endif
 
 #endif /* SFRAME_STACKTRACE_REGS_H.  */
diff --git a/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace.c b/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace.c
index 4c30951..99f58b7 100644
--- a/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace.c
+++ b/libsframe/testsuite/libsframe.stacktrace/libsframest/sframe-stacktrace.c
@@ -91,6 +91,10 @@
   sframe_decoder_ctx *dctx;
   int cfa_offset, rfp_offset, ra_offset, errnum, i, count;
   sframe_frame_row_entry fred, *frep = &fred;
+#if defined(__s390x__)
+  sframe_frame_row_entry fred0, *fre0p = &fred0;
+  int cfa0_offset;
+#endif
   uint64_t pc, rfp, rsp, ra, sframe_vma;
   ucontext_t context, *cp = &context;
   int err = 0;
@@ -161,7 +165,19 @@
 	      if (sframe_bt_errno (&errnum))
 		return sframe_bt_ret_set_errno (&err, SFRAME_BT_ERR_FRE_INVAL);
 	    }
+#if defined (__s390x__)
+	  errnum = sframe_find_fre0 (dctx, pc, fre0p);
+	  if (errnum != 0)
+	    goto find_fre_ra_err;
+
+	  cfa0_offset = sframe_fre_get_cfa_offset (dctx, fre0p, &errnum);
+	  if (errnum == SFRAME_ERR_FREOFFSET_NOPRESENT)
+	    return sframe_bt_ret_set_errno (&err, SFRAME_BT_ERR_CFA_OFFSET);
+
+	  rsp = cfa - cfa0_offset;
+#else
 	  rsp = cfa;
+#endif
 	  pc = return_addr;
 
 	  /* Check if need to update the SFrame stack trace info for the return