From: Indu Bhagat Date: Mon, 17 Nov 2025 18:36:27 +0000 (-0800) Subject: [SFrame-V3] libsframe: testsuite: add new argument to offset access APIs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0376b79f9b7c8450b12f7a6362ffea0c5433919;p=thirdparty%2Fbinutils-gdb.git [SFrame-V3] libsframe: testsuite: add new argument to offset access APIs For FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME, the offsets are not only laid out differently, they also have different encoding. Adjust the APIs in libsframe to get stack frame offsets by adding a new argument type. ATM, the stack tracer testsuite is not using this newly externalized API sframe_get_fre_offset. So not exposing this via the libsframe.ver file is OK for now. At the moment, like the generation routines in GAS, the textual dump routines in sframe-dump.c are also unaware of SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME FDE type. In the next commits, these capabilities will be added. include/ * sframe-api.h (MAX_NUM_STACK_OFFSETS): Increase the number of stack offsets to 6 to accommodate the FDE type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME. (sframe_get_fre_offset): Make extern. (sframe_fre_get_cfa_offset): Add new arg. (sframe_fre_get_fp_offset): Likewise. (sframe_fre_get_ra_offset): Likewise. libsframe/ * libsframe/sframe-dump.c (dump_sframe_func_with_fres): Pass 0 for FDE type. * sframe.c (sframe_fre_get_cfa_offset): Handle FDE type. (sframe_fre_get_fp_offset): Likewise. (sframe_fre_get_ra_offset): Likewise. libsframe/testsuite/ * libsframe.find/findfre-1.c: Pass 0 for FDE type. * libsframe.find/findfunc-1.c: Likewise. * libsframe.find/plt-findfre-1.c: Likewise. * libsframe.find/plt-findfre-2.c: Likewise. --- diff --git a/include/sframe-api.h b/include/sframe-api.h index 1a3b2c307ba..bea7cc099b8 100644 --- a/include/sframe-api.h +++ b/include/sframe-api.h @@ -31,7 +31,7 @@ extern "C" typedef struct sframe_decoder_ctx sframe_decoder_ctx; typedef struct sframe_encoder_ctx sframe_encoder_ctx; -#define MAX_NUM_STACK_OFFSETS 3 +#define MAX_NUM_STACK_OFFSETS 6 #define MAX_OFFSET_BYTES \ ((SFRAME_FRE_OFFSET_4B * 2 * MAX_NUM_STACK_OFFSETS)) @@ -199,6 +199,9 @@ sframe_decoder_get_funcdesc_v3 (const sframe_decoder_ctx *dctx, extern void dump_sframe (const sframe_decoder_ctx *decoder, uint64_t addr); +extern int32_t +sframe_get_fre_offset (const sframe_frame_row_entry *fre, int idx, int *errp); + /* Get the base reg id from the FRE info. Sets errp if fails. */ extern uint8_t sframe_fre_get_base_reg_id (const sframe_frame_row_entry *fre, int *errp); @@ -206,7 +209,9 @@ sframe_fre_get_base_reg_id (const sframe_frame_row_entry *fre, int *errp); /* Get the CFA offset from the FRE. If the offset is invalid, sets errp. */ extern int32_t sframe_fre_get_cfa_offset (const sframe_decoder_ctx *dtcx, - const sframe_frame_row_entry *fre, int *errp); + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp); /* Get the FP offset from the FRE. If the offset is invalid, sets errp. @@ -214,7 +219,9 @@ sframe_fre_get_cfa_offset (const sframe_decoder_ctx *dtcx, LSB set to one, which is only valid in the topmost frame. */ extern int32_t sframe_fre_get_fp_offset (const sframe_decoder_ctx *dctx, - const sframe_frame_row_entry *fre, int *errp); + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp); /* Get the RA offset from the FRE. If the offset is invalid, sets errp. @@ -224,7 +231,9 @@ sframe_fre_get_fp_offset (const sframe_decoder_ctx *dctx, LSB set to one, which is only valid in the topmost frame. */ extern int32_t sframe_fre_get_ra_offset (const sframe_decoder_ctx *dctx, - const sframe_frame_row_entry *fre, int *errp); + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp); /* Get whether the RA is mangled. */ diff --git a/libsframe/libsframe.ver b/libsframe/libsframe.ver index 99027497486..f6dbde273de 100644 --- a/libsframe/libsframe.ver +++ b/libsframe/libsframe.ver @@ -6,6 +6,7 @@ LIBSFRAME_3.0 { sframe_fde_create_func_info; sframe_calc_fre_type; sframe_fre_get_base_reg_id; + sframe_get_fre_offset; sframe_fre_get_cfa_offset; sframe_fre_get_fp_offset; sframe_fre_get_ra_offset; diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c index eda97b70b78..6da571a841c 100644 --- a/libsframe/sframe-dump.c +++ b/libsframe/sframe-dump.c @@ -232,9 +232,9 @@ dump_sframe_func_with_fres (const sframe_decoder_ctx *sfd_ctx, assert no error for base reg id and RA undefined. */ base_reg_id = sframe_fre_get_base_reg_id (&fre, &err[0]); ra_undefined_p = sframe_fre_get_ra_undefined_p (sfd_ctx, &fre, &err[0]); - cfa_offset = sframe_fre_get_cfa_offset (sfd_ctx, &fre, &err[0]); - fp_offset = sframe_fre_get_fp_offset (sfd_ctx, &fre, &err[1]); - ra_offset = sframe_fre_get_ra_offset (sfd_ctx, &fre, &err[2]); + cfa_offset = sframe_fre_get_cfa_offset (sfd_ctx, &fre, 0, &err[0]); + fp_offset = sframe_fre_get_fp_offset (sfd_ctx, &fre, 0, &err[1]); + ra_offset = sframe_fre_get_ra_offset (sfd_ctx, &fre, 0, &err[2]); /* Dump VMA. */ printf ("\n"); diff --git a/libsframe/sframe.c b/libsframe/sframe.c index dd16d3218b9..d223941b34b 100644 --- a/libsframe/sframe.c +++ b/libsframe/sframe.c @@ -821,7 +821,7 @@ fde_func (const void *p1, const void *p2) /* Get IDX'th offset from FRE. Set errp as applicable. */ -static int32_t +int32_t sframe_get_fre_offset (const sframe_frame_row_entry *fre, int idx, int *errp) { uint8_t offset_cnt, offset_size; @@ -938,13 +938,18 @@ sframe_fre_get_base_reg_id (const sframe_frame_row_entry *fre, int *errp) int32_t sframe_fre_get_cfa_offset (const sframe_decoder_ctx *dctx, - const sframe_frame_row_entry *fre, int *errp) + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp) { int err; - int32_t offset = sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, &err); + bool flex_p = (fde_type == SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME); + uint32_t idx = flex_p ? 1 : 0; + int32_t offset = sframe_get_fre_offset (fre, idx, &err); /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets). */ - if (!err && sframe_decoder_get_abi_arch (dctx) == SFRAME_ABI_S390X_ENDIAN_BIG) + if (!err && !flex_p + && sframe_decoder_get_abi_arch (dctx) == SFRAME_ABI_S390X_ENDIAN_BIG) offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset); if (errp) @@ -959,13 +964,17 @@ sframe_fre_get_cfa_offset (const sframe_decoder_ctx *dctx, int32_t sframe_fre_get_fp_offset (const sframe_decoder_ctx *dctx, - const sframe_frame_row_entry *fre, int *errp) + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp) { uint32_t fp_offset_idx = 0; + bool flex_p = (fde_type == SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME); + int8_t fp_offset = sframe_decoder_get_fixed_fp_offset (dctx); /* If the FP offset is not being tracked, return the fixed FP offset from the SFrame header. */ - if (fp_offset != SFRAME_CFA_FIXED_FP_INVALID + if (!flex_p && fp_offset != SFRAME_CFA_FIXED_FP_INVALID && !sframe_get_fre_ra_undefined_p (fre->fre_info)) { if (errp) @@ -980,6 +989,8 @@ sframe_fre_get_fp_offset (const sframe_decoder_ctx *dctx, != SFRAME_CFA_FIXED_RA_INVALID) ? SFRAME_FRE_RA_OFFSET_IDX : SFRAME_FRE_FP_OFFSET_IDX); + fp_offset_idx = flex_p ? SFRAME_FRE_FP_OFFSET_IDX * 2 + 1 : fp_offset_idx; + return sframe_get_fre_offset (fre, fp_offset_idx, errp); } @@ -992,12 +1003,17 @@ sframe_fre_get_fp_offset (const sframe_decoder_ctx *dctx, int32_t sframe_fre_get_ra_offset (const sframe_decoder_ctx *dctx, - const sframe_frame_row_entry *fre, int *errp) + const sframe_frame_row_entry *fre, + uint32_t fde_type, + int *errp) { + uint32_t ra_offset_idx = 0; int8_t ra_offset = sframe_decoder_get_fixed_ra_offset (dctx); + bool flex_p = (fde_type == SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME); + /* If the RA offset was not being tracked, return the fixed RA offset from the SFrame header. */ - if (ra_offset != SFRAME_CFA_FIXED_RA_INVALID + if (!flex_p && ra_offset != SFRAME_CFA_FIXED_RA_INVALID && !sframe_get_fre_ra_undefined_p (fre->fre_info)) { if (errp) @@ -1006,7 +1022,10 @@ sframe_fre_get_ra_offset (const sframe_decoder_ctx *dctx, } /* Otherwise, get the RA offset from the FRE. */ - return sframe_get_fre_offset (fre, SFRAME_FRE_RA_OFFSET_IDX, errp); + ra_offset_idx = (flex_p + ? SFRAME_FRE_RA_OFFSET_IDX * 2 + 1 + : SFRAME_FRE_RA_OFFSET_IDX); + return sframe_get_fre_offset (fre, ra_offset_idx, errp); } /* Get whether the RA is mangled. */ diff --git a/libsframe/testsuite/libsframe.find/findfre-1.c b/libsframe/testsuite/libsframe.find/findfre-1.c index 58cbbb85e77..89357ca46cd 100644 --- a/libsframe/testsuite/libsframe.find/findfre-1.c +++ b/libsframe/testsuite/libsframe.find/findfre-1.c @@ -132,31 +132,31 @@ void test_text_findfre (const char suffix, int64_t text_vaddr, /* Find the third FRE in first FDE. */ lookup_pc = func1_start_vaddr + 0x15 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x3), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x3), "findfre-1%c: Find third FRE", suffix); /* Find an FRE for PC at the end of range covered by FRE. */ lookup_pc = func1_start_vaddr + 0x9 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x2), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x2), "findfre-1%c: Find FRE for last PC covered by FRE", suffix); /* Find the last FRE in first FDE. */ lookup_pc = func1_start_vaddr + 0x39 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x8), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x8), "findfre-1%c: Find last FRE", suffix); /* Find the second FRE in second FDE. */ lookup_pc = func2_start_vaddr + 0x11 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x12), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x12), "findfre-1%c: Find second FRE", suffix); /* Find the first FRE in second FDE. */ lookup_pc = func2_start_vaddr + 0x0 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x10), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x10), "findfre-1%c: Find first FRE", suffix); /* Find FRE for PC out of range. Expect error code. */ diff --git a/libsframe/testsuite/libsframe.find/findfunc-1.c b/libsframe/testsuite/libsframe.find/findfunc-1.c index c8d9a0191ed..60b2404454f 100644 --- a/libsframe/testsuite/libsframe.find/findfunc-1.c +++ b/libsframe/testsuite/libsframe.find/findfunc-1.c @@ -212,19 +212,19 @@ void test_text_findfre (const char suffix, int64_t text_vaddr, /* Find an FRE for PC in FDE1. */ lookup_pc = func1_start_vaddr + 0x9 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x2), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x2), "findfunc-1%c: Find FRE in FDE1", suffix); /* Find an FRE for PC in FDE2. */ lookup_pc = func2_start_vaddr + 0x11 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x12), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x12), "findfunc-1%c: Find FRE in FDE2", suffix); /* Find an FRE for PC in FDE3. */ lookup_pc = func3_start_vaddr + 0x10 - sframe_vaddr; err = sframe_find_fre (dctx, lookup_pc, &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x18), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x18), "findfunc-1%c: Find FRE in FDE3", suffix); sframe_encoder_free (&encode); diff --git a/libsframe/testsuite/libsframe.find/plt-findfre-1.c b/libsframe/testsuite/libsframe.find/plt-findfre-1.c index 5363ac7d1f6..594a6a2f8e0 100644 --- a/libsframe/testsuite/libsframe.find/plt-findfre-1.c +++ b/libsframe/testsuite/libsframe.find/plt-findfre-1.c @@ -86,32 +86,32 @@ void test_plt_findfre (const char suffix, int64_t plt_vaddr, /* Find the first FRE in PLT1. */ err = sframe_find_fre (dctx, (plt_vaddr + 0x0 - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x1), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x1), "plt-findfre-1%c: Find first FRE in PLT1", suffix); /* Find the second FRE. */ err = sframe_find_fre (dctx, (plt_vaddr + 0x6 - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x2), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x2), "plt-findfre-1%c: Find second FRE in PLT1", suffix); /* Find the last FRE. */ err = sframe_find_fre (dctx, (plt_vaddr + 0xc - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x3), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x3), "plt-findfre-1%c: Find last FRE in PLT1", suffix); /* Find the first FRE in PLT4. */ err = sframe_find_fre (dctx, (plt_vaddr + 16*3 + 0x0 - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x1), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x1), "plt-findfre-1%c: Find first FRE in PLT4", suffix); /* Find the second FRE in PLT4. */ err = sframe_find_fre (dctx, (plt_vaddr + 16*3 + 0x6 - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x2), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x2), "plt-findfre-1%c: Find second FRE in PLT4", suffix); /* Find the last FRE in PLT4. */ err = sframe_find_fre (dctx, (plt_vaddr + 16*3 + 0xc - sframe_vaddr), &frep); - TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x3), + TEST ((err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 0x3), "plt-findfre-1%c: Find last FRE in PLT4", suffix); /* Find no FRE for out of range PLT6. */ diff --git a/libsframe/testsuite/libsframe.find/plt-findfre-2.c b/libsframe/testsuite/libsframe.find/plt-findfre-2.c index 4cb04bd14c8..248465c84e9 100644 --- a/libsframe/testsuite/libsframe.find/plt-findfre-2.c +++ b/libsframe/testsuite/libsframe.find/plt-findfre-2.c @@ -134,12 +134,12 @@ void test_plt_findfre (const char suffix, const int64_t plt_vaddr, /* Find the only FRE in PLT0 at offset 0. */ err = sframe_find_fre (dctx, (plt_vaddr + 0 - sframe_vaddr), &frep); - TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLT0_CFA_OFFSET_MAGIC, + TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 160 + PLT0_CFA_OFFSET_MAGIC, "plt-findfre-2%c: Find only FRE in PLT0 at offset 0", suffix); /* Find the only FRE in PLT0 at offset PLT_SIZE-1. */ err = sframe_find_fre (dctx, (plt_vaddr + (PLT_SIZE-1) - sframe_vaddr), &frep); - TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLT0_CFA_OFFSET_MAGIC, + TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 160 + PLT0_CFA_OFFSET_MAGIC, "plt-findfre-2%c: Find only FRE in PLT0 at offset PLT_SIZE-1", suffix); /* Find the only FRE in PLT1-5 at offset 0 and PLT_SIZE-1. */ @@ -147,12 +147,12 @@ void test_plt_findfre (const char suffix, const int64_t plt_vaddr, { /* Find the only FRE in PLTN at offset 0. */ err = sframe_find_fre (dctx, (plt_vaddr + i * PLT_SIZE + 0 - sframe_vaddr), &frep); - TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLTN_CFA_OFFSET_MAGIC, + TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 160 + PLTN_CFA_OFFSET_MAGIC, "plt-findfre-2%c: Find only FRE in PLT%d at offset 0", suffix, i); /* Find the only FRE in PLTN at offset 31. */ err = sframe_find_fre (dctx, (plt_vaddr + i * PLT_SIZE + (PLT_SIZE-1) - sframe_vaddr), &frep); - TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLTN_CFA_OFFSET_MAGIC, + TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, 0, &err) == 160 + PLTN_CFA_OFFSET_MAGIC, "plt-findfre-2%c: Find only FRE in PLT%d at offset PLT_SIZE-1", suffix, i); }