[PATCH v4 3/4] gas: sframe: Represent .cfi_undefined RA as FRE without offsets
Indu Bhagat
indu.bhagat@oracle.com
Tue Jul 29 07:12:34 GMT 2025
On 7/25/25 9:23 AM, Jens Remus wrote:
> In DWARF CFI an "undefined" register rule for the return address (RA)
> register indicates that there is no return address and the stack trace
> is complete.
>
> Represent DW_CFA_undefined as SFrame FRE without any offsets, so that a
> stack tracer implementation can use this as indication that an outermost
> frame has been reached and the stack trace is complete.
>
> This representation is backward compatible, as existing stack tracers
> should already deal with the case, that an SFrame FRE a so far invalid
> offset count of zero and stop the trace.
>
> include/
> * sframe.h (SFRAME_V2_FRE_RA_UNDEFINED_P): New macro to test
> FRE info word for RA undefined.
>
> gas/
> * gen-sframe.h (struct sframe_row_entry): Add ra_undefined flag.
> * gen-sframe.c (sframe_row_entry_new): Initialize ra_undefined
> flag to not set.
> (sframe_row_entry_initialize): Treat ra_undefined flag as
> sticky.
> (sframe_fre_set_ra_track): Reset ra_undefined flag.
> (sframe_xlate_do_restore): Reset ra_undefined flag to saved
> state.
> (sframe_xlate_do_same_value): Reset ra_undefined flag.
> (sframe_xlate_do_cfi_undefined): For RA set ra_undefined flag.
> (get_fre_base_reg_id, get_fre_num_offsets,
> sframe_get_fre_offset_size): Return 0 if ra_undefined flag set.
> (output_sframe_row_entry): Represent RA undefined as SFrame FRE
> without any offsets (e.g. no CFA, RA, nor FP offsets).
>
> libsframe/
> * doc/sframe-spec.texi (Changes from Version 1 to Version 2):
> Mention that a SFrame FRE without any offsets flag indicates an
> outermost frame with an undefined RA.
> (fre_offset_count): Document that a FRE offset count of zero
> indicates an outermost frame with an undefined RA.
> * sframe-dump.c (dump_sframe_func_with_fres): Show FRE without
> any offsets as "RA undefined".
>
> gas/testsuite/
> * gas/cfi-sframe/cfi-sframe.exp: Run tests for .cfi_undefined RA
> on AArch64, s390x, and x86-64.
> * gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.d: Add test
> for .cfi_undefined RA on AArch64.
> * gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.s: Likewise.
> * as/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.d: Add test
> for .cfi_undefined RA on s390x.
> * gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.s: Likewise.
> * gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.d: Add test
> for .cfi_undefined RA on x86-64.
> * gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.s: Likewise.
>
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> ---
>
> Notes (jremus):
> Changes in V4:
> - Represent RA undefined as SFrame FRE without any offsets. (Indu)
> This aligns to DWARF and saves from adding a SFrame FDE flag.
>
> Changes in V3:
> - Introduce a FDE info word flag ra_undefined. Represent RA undefined
> as FDE without any FREs and the ra_undefined flag set. (Indu)
> - Set sfde_func_start_fre_off to zero, if FDE without any FREs.
> - In x86-64 tests use spaces to separate mnemonic from operands. (Indu)
> - Reword commit subject, commit message, and GNU ChangeLog.
>
> An alternative to introducing a FDE info word flag ra_undefined would
> be to repurpose the FRE offset in the FDE to carry indications, if
> the FRE count is zero. While that would be easy in the assembler to
> generate and easy for a stack tracer to process it would require
> a few modifications in libsframe to preserve those special FRE offset
> values.
>
> Wouldn't it make sense to remove the half baked versioned operations
> (see struct sframe_version_ops) with a preparatory cleanup patch? I
> don't see how the current implementation would work in the future.
> The operations would otherwise probably need to be split up into
> smaller ones: fde_info_init(fde_type, fre_type), fde_info_set_pauth_key,
> fde_info_set_ra_undefined, ... .
>
Yeah, sure. Makes sense.
> Changes in V2:
> - Use sframe_xlate_ctx_init to re-initialize translation context.
> - Reword comment on sframe_xlate_do_cfi_escape.
> - Reword comment in sframe_do_fde for SFRAME_XLATE_RA_UNDEFINED.
> - Reword comment in create_sframe_all for SFRAME_XLATE_RA_UNDEFINED.
>
> gas/gen-sframe.c | 52 +++++++++++++++++--
> gas/gen-sframe.h | 3 ++
> .../cfi-sframe-aarch64-ra-undefined-1.d | 20 +++++++
> .../cfi-sframe-aarch64-ra-undefined-1.s | 13 +++++
> .../cfi-sframe-s390x-ra-undefined-1.d | 21 ++++++++
> .../cfi-sframe-s390x-ra-undefined-1.s | 11 ++++
> .../cfi-sframe-x86_64-ra-undefined-1.d | 22 ++++++++
> .../cfi-sframe-x86_64-ra-undefined-1.s | 11 ++++
> gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 3 ++
> include/sframe.h | 1 +
> libsframe/doc/sframe-spec.texi | 10 +++-
> libsframe/sframe-dump.c | 15 +++++-
> 12 files changed, 174 insertions(+), 8 deletions(-)
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.d
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.s
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.d
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.s
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.d
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.s
>
> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
> index acea1dc7dbb7..eeb1607105f7 100644
> --- a/gas/gen-sframe.c
> +++ b/gas/gen-sframe.c
> @@ -164,6 +164,7 @@ sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
> {
> fre->ra_loc = SFRAME_FRE_ELEM_LOC_STACK;
> fre->ra_offset = ra_offset;
> + fre->ra_undefined = false;
> fre->merge_candidate = false;
> }
>
> @@ -335,6 +336,9 @@ get_fre_base_reg_id (struct sframe_row_entry *sframe_fre)
> unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
> unsigned fre_base_reg = SFRAME_BASE_REG_SP;
>
> + if (sframe_fre->ra_undefined)
> + return 0;
> +
This effectively means SFRAME_BASE_REG_FP; return 0 is generally
confusing to read (at least for me).
How about we return the SFRAME_BASE_REG_SP instead with some code
comments if you see fit.
> if (cfi_insn_cfa_base_reg == SFRAME_CFA_FP_REG)
> fre_base_reg = SFRAME_BASE_REG_FP;
>
> @@ -353,6 +357,10 @@ get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
> /* Atleast 1 must always be present (to recover CFA). */
> unsigned int fre_num_offsets = 1;
>
> + /* Represent RA undefined as FRE without any offsets. */
> + if (sframe_fre->ra_undefined)
> + return 0;
> +
> if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
> fre_num_offsets++;
> if (sframe_ra_tracking_p ()
> @@ -377,6 +385,10 @@ sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre)
>
> unsigned int fre_offset_size = 0;
>
> + /* Represent RA undefined as FRE without any offsets. */
> + if (sframe_fre->ra_undefined)
> + return 0;
> +
> /* What size of offsets appear in this frame row entry. */
> cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
> if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
> @@ -514,6 +526,8 @@ sframe_row_entry_new (void)
> initialize it in sframe_row_entry_initialize () with the sticky
> bit if set. */
> fre->mangled_ra_p = false;
> + /* Reset the RA undefined status by to zero by default. */
> + fre->ra_undefined = false;
>
> return fre;
> }
> @@ -588,6 +602,13 @@ output_sframe_row_entry (symbolS *fde_start_addr,
> fre_offset_size, sframe_fre->mangled_ra_p);
> out_one (fre_info);
>
> + /* Represent RA undefined as FRE without any offsets. */
> + if (sframe_fre->ra_undefined)
> + {
> + gas_assert (fre_num_offsets == 0);
> + return;
> + }
> +
> idx = sframe_fre_offset_func_map_index (fre_offset_size);
> gas_assert (idx < SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX);
>
> @@ -942,6 +963,10 @@ sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
> /* Treat RA mangling as a sticky bit. It retains its value until another
> .cfi_negate_ra_state is seen. */
> cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
> + /* Treat RA undefined as a sticky bit. It retains its value until a
> + .cfi_offset RA, .cfi_register RA, .cfi_restore RA, or .cfi_same_value RA
> + is seen. */
> + cur_fre->ra_undefined = prev_fre->ra_undefined;
> }
>
> /* Return SFrame register name for SP, FP, and RA, or NULL if other. */
> @@ -1317,6 +1342,7 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
> gas_assert (cur_fre);
> cur_fre->ra_loc = cie_fre->ra_loc;
> cur_fre->ra_offset = cie_fre->ra_offset;
> + cur_fre->ra_undefined = cie_fre->ra_undefined;
> cur_fre->merge_candidate = false;
> }
> return SFRAME_XLATE_OK;
> @@ -1603,9 +1629,15 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
> /* Translate DW_CFA_undefined into SFrame context.
>
> DW_CFA_undefined op indicates that from now on, the previous value of
> - register can’t be restored anymore. In SFrame stack trace, we cannot
> - represent such a semantic. So, we skip generating an SFrame FDE for this,
> - when a register of interest is used with DW_CFA_undefined.
> + register can’t be restored anymore. In DWARF, for the return address (RA)
> + register, this indicates to an unwinder that there is no return address
> + and the unwind is complete.
> +
> + In SFrame, represent the use of the RA register with DW_CFA_undefined as
> + SFrame FRE without any offsets. Stack tracers can use this as indication
> + that an outermost frame has been reached and the stack trace is complete.
> + The use of other registers of interest with DW_CFA_undefined cannot be
> + represented in SFrame. Therefore skip generating an SFrame FDE.
>
> Return SFRAME_XLATE_OK if success. */
>
> @@ -1614,15 +1646,24 @@ sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUT
> const struct cfi_insn_data *cfi_insn)
> {
> if (cfi_insn->u.r == SFRAME_CFA_FP_REG
> - || cfi_insn->u.r == SFRAME_CFA_RA_REG
> || cfi_insn->u.r == SFRAME_CFA_SP_REG)
> {
> as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"),
> sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
> return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
> }
> + else if (cfi_insn->u.r == SFRAME_CFA_RA_REG)
> + {
> + /* Represent RA undefined (i.e. outermost frame) as FRE without any
> + offsets. */
> + struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
> +
> + gas_assert (cur_fre);
> + /* Set RA undefined status bit. */
> + cur_fre->ra_undefined = true;
> + cur_fre->merge_candidate = false;
> + }
>
> - /* Safe to skip. */
> return SFRAME_XLATE_OK;
> }
>
> @@ -1670,6 +1711,7 @@ sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx,
> {
> cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_REG;
> cur_fre->ra_offset = 0;
> + cur_fre->ra_undefined = false;
> cur_fre->merge_candidate = false;
> }
> else if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
> diff --git a/gas/gen-sframe.h b/gas/gen-sframe.h
> index e4a4c6ea0ceb..13956489b09a 100644
> --- a/gas/gen-sframe.h
> +++ b/gas/gen-sframe.h
> @@ -55,6 +55,9 @@ struct sframe_row_entry
> /* Whether the return address is mangled with pauth code. */
> bool mangled_ra_p;
>
> + /* Whether RA is undefined. */
> + bool ra_undefined;
> +
Can we rename this to ra_undefined_p as well ?
> /* Track CFA base (architectural) register ID. */
> unsigned int cfa_base_reg;
> /* Offset from the CFA base register for recovering CFA. */
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.d
> new file mode 100644
> index 000000000000..f6bd6d71008b
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.d
> @@ -0,0 +1,20 @@
> +#as: --gsframe
> +#objdump: --sframe=.sframe
> +#name: SFrame generation on aarch64 - .cfi_undefined RA
> +#...
> +Contents of the SFrame section .sframe:
> + Header :
> +
> + Version: SFRAME_VERSION_2
> + Flags: SFRAME_F_FDE_FUNC_START_PCREL
> + Num FDEs: 1
> + Num FREs: 4
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x0, size = 16 bytes
> + STARTPC +CFA +FP +RA +
> + 0+0000 +sp\+0 +u +u +
> + 0+0004 +sp\+16 +c\-16 +c\-8 +
> + 0+0008 +RA undefined
> + 0+000c +RA undefined
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.s
> new file mode 100644
> index 000000000000..7b28ab8f6528
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-aarch64-ra-undefined-1.s
> @@ -0,0 +1,13 @@
> + .cfi_startproc
> + stp fp, lr, [sp, #-16]!
> + .cfi_def_cfa_offset 16
> + .cfi_offset 29, -16
> + .cfi_offset 30, -8
> + nop
> + .cfi_undefined 30
> + ldp fp, lr, [sp], #16
> + .cfi_restore 20
> + .cfi_restore 19
> + .cfi_def_cfa_offset 0
> + ret lr
> + .cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.d
> new file mode 100644
> index 000000000000..dfd47e30bbe9
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.d
> @@ -0,0 +1,21 @@
> +#name: SFrame generation on s390x - .cfi_undefined RA
> +#as: --gsframe
> +#objdump: --sframe=.sframe
> +#...
> +Contents of the SFrame section .sframe:
> +
> + Header :
> +
> + Version: SFRAME_VERSION_2
> + Flags: SFRAME_F_FDE_FUNC_START_PCREL
> + Num FDEs: 1
> + Num FREs: 4
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x0, size = 18 bytes
> + STARTPC +CFA +FP +RA +
> + 0+0000 +sp\+160 +u +u +
> + 0+0006 +sp\+160 +u +c\-48 +
> + 0+000a +RA undefined
> + 0+0010 +sp\+160 +u +u +
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.s
> new file mode 100644
> index 000000000000..dda7abcdf4d7
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-ra-undefined-1.s
> @@ -0,0 +1,11 @@
> + .cfi_startproc
> + stmg %r11,%r15,48(%r15)
> + .cfi_offset 14, -48
> + .cfi_offset 15, -40
> + nop
> + .cfi_undefined 14
> + lmg %r14,%r15,160+48(%r11)
> + .cfi_restore 15
> + .cfi_restore 14
> + br %r14
> + .cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.d
> new file mode 100644
> index 000000000000..a635c3cd9cbf
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.d
> @@ -0,0 +1,22 @@
> +#as: --gsframe -O0
> +#objdump: --sframe=.sframe
> +#name: SFrame generation on x86_64 - .cfi_undefined RA
> +#...
> +Contents of the SFrame section .sframe:
> +
> + Header :
> +
> + Version: SFRAME_VERSION_2
> + Flags: SFRAME_F_FDE_FUNC_START_PCREL
> + CFA fixed RA offset: \-8
> + Num FDEs: 1
> + Num FREs: 4
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x0, size = 6 bytes
> + STARTPC +CFA +FP +RA +
> + 0+0000 +sp\+8 +u +f +
> + 0+0001 +sp\+16 +c\-16 +f +
> + 0+0004 +fp\+16 +c\-16 +f +
> + 0+0005 +RA undefined
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.s
> new file mode 100644
> index 000000000000..0f5b9c71715f
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-ra-undefined-1.s
> @@ -0,0 +1,11 @@
> + .cfi_startproc
> + pushq %rbp
> + .cfi_def_cfa_offset 16
> + .cfi_offset 6, -16
> + movq %rsp, %rbp
> + .cfi_def_cfa_register 6
> + nop
> + .cfi_undefined 16
> + .cfi_def_cfa 7, 8
> + ret
> + .cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> index 9380c98fc3db..41b927fd7196 100644
> --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> @@ -64,6 +64,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
> run_dump_test "cfi-sframe-x86_64-empty-2"
> run_dump_test "cfi-sframe-x86_64-empty-3"
> run_dump_test "cfi-sframe-x86_64-empty-4"
> + run_dump_test "cfi-sframe-x86_64-ra-undefined-1"
> set ASFLAGS "$old_ASFLAGS"
> }
> }
> @@ -75,6 +76,7 @@ if { [istarget "aarch64*-*-*"] && [gas_sframe_check] } then {
> run_dump_test "cfi-sframe-aarch64-3"
> run_dump_test "cfi-sframe-aarch64-4"
> run_dump_test "cfi-sframe-aarch64-pac-ab-key-1"
> + run_dump_test "cfi-sframe-aarch64-ra-undefined-1"
> }
>
> # s390x specific tests
> @@ -89,4 +91,5 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
> run_dump_test "cfi-sframe-s390x-fpra-offset-2"
> run_dump_test "cfi-sframe-s390x-fpra-register-1"
> run_dump_test "cfi-sframe-s390x-fpra-register-2"
> + run_dump_test "cfi-sframe-s390x-ra-undefined-1"
> }
> diff --git a/include/sframe.h b/include/sframe.h
> index 7523adbef3a8..127bf3750577 100644
> --- a/include/sframe.h
> +++ b/include/sframe.h
> @@ -287,6 +287,7 @@ typedef struct sframe_fre_info
> #define SFRAME_V1_FRE_OFFSET_COUNT(data) (((data) >> 1) & 0xf)
> #define SFRAME_V1_FRE_OFFSET_SIZE(data) (((data) >> 5) & 0x3)
> #define SFRAME_V1_FRE_MANGLED_RA_P(data) (((data) >> 7) & 0x1)
> +#define SFRAME_V2_FRE_RA_UNDEFINED_P(data) (SFRAME_V1_FRE_OFFSET_COUNT (data) == 0)
>
> /* SFrame Frame Row Entry definitions.
>
> diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi
> index 7307789df264..346d29a51ac0 100644
> --- a/libsframe/doc/sframe-spec.texi
> +++ b/libsframe/doc/sframe-spec.texi
> @@ -165,6 +165,11 @@ CFA offset adjustment and then scale down by CFA offset alignment factor).
> @item SFRAME_V2_S390X_CFA_OFFSET_DECODE: Decode CFA offset (i.e., scale up
> by CFA offset alignment factor and then revert CFA offset adjustment).
> @end itemize
> +@item
> +An SFrame FRE info word offset count of zero indicates that the return
> +address (RA) is undefined for the range of PCs covered by the SFrame FRE.
> +A stack tracer may use this as indication that an outermost frame has been
> +reached and the stack trace is complete.
Please go ahead and use "errata 2" in the spec. I will later add a way
to say that this spec is the draft version.
> @end itemize
>
> SFrame version 1 is now obsolete and should not be used.
> @@ -771,7 +776,10 @@ SFRAME_FRE_OFFSET_4B.
> @item 1-4
> @tab @code{fre_offset_count}
> @tab A max value of 15 is allowed. Typically, a value of upto 3 is sufficient
> -for most ABIs to track all three of CFA, FP and RA.
> +for most ABIs to track all three of CFA, FP and RA. A value of zero indicates
> +that the return address (RA) is undefined. A stack tracer may use this as
> +indication that an outermost frame has been reached and the stack trace is
> +complete.
>
> @item 0
> @tab @code{fre_cfa_base_reg_id}
> diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c
> index d55d3847194e..bada1ee6c684 100644
> --- a/libsframe/sframe-dump.c
> +++ b/libsframe/sframe-dump.c
> @@ -130,6 +130,7 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
> uint64_t func_start_pc_vma = 0;
> uint64_t fre_start_pc_vma = 0;
> const char *base_reg_str[] = {"fp", "sp"};
> + int offset_count = 0;
> int32_t cfa_offset = 0;
> int32_t fp_offset = 0;
> int32_t ra_offset = 0;
> @@ -180,15 +181,25 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
> : func_start_pc_vma + fre.fre_start_addr);
>
> /* FIXME - fixup the err caching in array.
> - assert no error for base reg id. */
> + assert no error for base reg id and offset count. */
> base_reg_id = sframe_fre_get_base_reg_id (&fre, &err[0]);
> + offset_count = sframe_fre_get_offset_count (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]);
>
> - /* Dump CFA info. */
> + /* Dump VMA. */
> printf ("\n");
> printf (" %016"PRIx64, fre_start_pc_vma);
> +
> + /* Dump RA undefined (FRE without any offsets). */
> + if (offset_count == 0)
> + {
> + printf (" RA undefined");
> + continue;
> + }
> +
> + /* Dump CFA info. */
> sprintf (temp, "%s+%d", base_reg_str[base_reg_id], cfa_offset);
> printf (" %-10s", temp);
>
More information about the Binutils
mailing list