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))
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);
/* 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.
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.
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. */
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;
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");
/* 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;
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)
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)
!= 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);
}
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)
}
/* 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. */
/* 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. */
/* 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);
/* 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. */
/* 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. */
{
/* 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);
}