From 42c46c4c7c35678efcd8ba5bf57ae5882cdad79d Mon Sep 17 00:00:00 2001 From: Jens Remus Date: Thu, 16 May 2024 13:55:44 +0200 Subject: s390: Initial support for s390x Signed-off-by: Jens Remus --- include/sframe-api.h | 7 +++++ libsframe/sframe.c | 34 ++++++++++++++++++++++ .../libsframest/sframe-stacktrace-regs.h | 27 +++++++++++++++++ .../libsframest/sframe-stacktrace.c | 16 ++++++++++ 4 files changed, 84 insertions(+) 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 @@ extern int 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 @@ sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, 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 @@ get_context_ra (ucontext_t *cp) 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_unwind (struct sframest_ctx *sf, void **ra_lst, int *ra_size) 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 @@ sframe_unwind (struct sframest_ctx *sf, void **ra_lst, int *ra_size) 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 -- cgit v1.1