[PATCH v3 04/11] s390: Represent FP/RA saved in register in SFrame
Indu Bhagat
indu.bhagat@oracle.com
Sat Jul 5 23:03:30 GMT 2025
On 6/27/25 4:08 AM, Jens Remus wrote:
> GCC on s390x, when in a leaf function, can be observed to save the
> frame pointer (FP) and/or return address (RA) register in a floating-
> point registers (FPR) instead of on the stack. This is declared using
> the following CFI directive:
>
> .cfi_register <fp/ra-regnum>, <fpr-regnum>
>
> SFrame cannot represent the FP and/or RA being saved in another
> register. It does only track the CFA base register (SP/FP), CFA offset
> from CFA base register, and FP and RA save area offsets from CFA.
>
> On s390x the FP and/or RA are only saved in another FPR when in a leaf
> function. That is a function that does not call any other function.
> Therefore it can ever only be the topmost function in a call chain.
> An unwinder by default has access to all registers of the function that
> is the topmost on the call stack. Therefore no further information
> is required to restore FP/RA from the FPR.
>
> Represent FP/RA saved in another register on s390x, by encoding the
> DWARF register number shifted by one to the left with the least-
> significant bit set in the offset as follows:
>
> offset = (regnum << 1) | 1
>
> The use of the least-significant bit of the offset as indication is
> possible, as the stack pointer (SP), the CFA, and any register save
> area slots are 8-byte aligned according to the s390x ELF ABI:
> - The stack pointer (SP) "shall maintain an 8-byte alignment". [1]
> - The CFA is defined as SP at call site +160. [2]
> - Pointers and 8-byte integers, such as general register values, must
> be 8-byte aligned. [3]
> SFrame FP and RA stack offsets must therefore always be a multiple of
> 8 on s390x. Note that for the same reason the DWARF data alignment
> factor is -8 on s390x (see DWARF2_CIE_DATA_ALIGNMENT).
>
> Add s390x-specific SFrame (error) tests for FP/RA saved in FPRs in leaf
> function.
>
> [1]: s390x ELF ABI, sections "Register Roles" and "Stack Frame
> Allocation", https://github.com/IBM/s390x-abi/releases
> [2]: s390x ELF ABI, commit 4e38ad9c8a88 ("Document the CFA"),
> https://github.com/IBM/s390x-abi/commit/4e38ad9c8a88
> [3]: s390x ELF ABI, section "Fundamental Types", table "Scalar types",
> https://github.com/IBM/s390x-abi/releases
>
> include/
> * sframe.h (SFRAME_S390X_OFFSET_IS_REGNUM): New s390x-specific
> macro to test whether an SFrame FP/RA offset is a DWARF register
> number.
> (SFRAME_S390X_OFFSET_ENCODE_REGNUM): New s390x-specific macro to
> encode a DWARF register number into an SFrame FP/RA offset.
> (SFRAME_S390X_OFFSET_DECODE_REGNUM): New s390x-specific macro to
> decode an SFrame FP/RA offset into a DWARF register number.
> * sframe-api.h (sframe_fre_get_fp_offset,
> sframe_fre_get_fp_offset): Add comment that for s390x the offset
> may be an encoded register number.
>
> gas/
> * gen-sframe.c (s390_sframe_xlate_do_register): New S390-
> specific function. Uses SFRAME_S390X_OFFSET_ENCODE_REGNUM to
> represent FP/RA saved in another register on s390x.
> (sframe_xlate_do_register): Invoke s390_sframe_xlate_do_register
> on s390x.
>
> libsframe/
> * sframe.c (sframe_fre_get_fp_offset, sframe_fre_get_fp_offset):
> Add comment that for s390x the offset may be an encoded register
> number.
> * sframe-dump.c (is_sframe_abi_arch_s390x): New helper to test
> whether ABI/arch is s390x.
> (dump_sframe_func_with_fres): Use SFRAME_S390X_OFFSET_IS_REGNUM
> and SFRAME_S390X_OFFSET_DECODE_REGNUM to dump FP/RA saved in
> another register on s390x.
> * doc/sframe-spec.texi (s390x): Document s390x-specific
> representation of FP/RA saved in another register.
>
> gas/testsuite/
> * gas/cfi-sframe/cfi-sframe.exp: Update s390x-specific SFrame
> (error) tests.
> * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.s: Rename
> to ...
> * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d:
> Likewise.
> * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.s: This. Test
> no longer triggers a warning, as SFrame can represent FP and RA
> saved in registers.
> * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d: Likewise.
> * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d: Test
> now triggers a different warning, as SFrame can represent FP and
> RA saved in registers, but not FP without RA saved in register.
>
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Few nits below.
Otherwise, LGTM.
Reviewed-by: Indu Bhagat <indu.bhagat@oracle.com>
> ---
>
> Notes (jremus):
> Changes in V3:
> - Update "Changes from Version 1 to Version 2" in SFrame spec. (Indu)
> - Reword use of "FRE bytes" in SFrame spec. (Indu)
> - Add comment on sframe_fre_get_{fp|ra}_offset that for s390x the offset
> may be an encoded register number.
> - Move comment on sframe_fre_get_ra_offset that for s390x the offset may
> be SFRAME_FRE_RA_OFFSET_INVALID to next patch.
>
> Changes in V2:
> - Reword commit message (s390 to s390x). (Indu)
> - Rename s390x-specific macros from *_S390_* to *_S390X_*. (Indu)
> - Use "s390x" instead of "S390" in comments and SFrame spec. (Indu)
> - Add comment on sframe_fre_get_{fp|ra}_offset that for s390x the offset
> may be an encoded register number. (Indu)
> - Add documentation that for s390x stack tracers need to implement
> checks when restoring FP and RA from registers. (Indu)
> - Add comment on sframe_fre_get_ra_offset that for s390x the offset may
> be SFRAME_FRE_RA_OFFSET_INVALID when FP without RA saved.
> - Reword test names.
> - Adjust tests to commit bd9dc0a281a4 ("gas: sframe: reword diagnostic
> to address ambiguity")
> - Rename CFI SFrame test file names from s390 to s390x. (Indu)
> - Reword test names.
>
> gas/gen-sframe.c | 35 ++++++++++++++++
> .../cfi-sframe-s390x-fpra-register-1.d | 22 ++++++++++
> ...2.s => cfi-sframe-s390x-fpra-register-1.s} | 0
> .../cfi-sframe-s390x-fpra-register-err-1.d | 4 +-
> .../cfi-sframe-s390x-fpra-register-err-2.d | 15 -------
> gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 2 +-
> include/sframe-api.h | 10 ++++-
> include/sframe.h | 13 ++++++
> libsframe/doc/sframe-spec.texi | 41 ++++++++++++++-----
> libsframe/sframe-dump.c | 24 ++++++++++-
> libsframe/sframe.c | 10 ++++-
> 11 files changed, 142 insertions(+), 34 deletions(-)
> create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
> rename gas/testsuite/gas/cfi-sframe/{cfi-sframe-s390x-fpra-register-err-2.s => cfi-sframe-s390x-fpra-register-1.s} (100%)
> delete mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d
>
> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
> index 89a61df4449e..a170c5b67e0d 100644
> --- a/gas/gen-sframe.c
> +++ b/gas/gen-sframe.c
> @@ -1126,6 +1126,37 @@ sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_U
> return SFRAME_XLATE_OK;
> }
>
> +/* S390-specific translate DW_CFA_register into SFrame context.
> + Return SFRAME_XLATE_OK if success. */
> +
> +static int
> +s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
> + struct cfi_insn_data *cfi_insn)
> +{
> + /* The scratchpad FRE currently being updated with each cfi_insn
> + being interpreted. This FRE eventually gets linked in into the
> + list of FREs for the specific function. */
> + struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
> +
> + gas_assert (cur_fre);
> +
> + /* Change the rule for the register indicated by the register number to
> + be the specified register. Encode the register number as offset by
> + shifting it to the left by one and setting the least-significant bit
> + (LSB). The LSB can be used to differentiate offsets from register
> + numbers, as offsets from CFA are always a multiple of -8 on s390x. */
> + if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
> + sframe_fre_set_bp_track (cur_fre,
> + SFRAME_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
> + else if (sframe_ra_tracking_p ()
> + && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
> + sframe_fre_set_ra_track (cur_fre,
> + SFRAME_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
> +
> + /* Safe to skip. */
> + return SFRAME_XLATE_OK;
Remove comment "Safe to skip."
> +}
> +
> /* Translate DW_CFA_register into SFrame context.
> Return SFRAME_XLATE_OK if success. */
>
> @@ -1133,6 +1164,10 @@ static int
> sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
> struct cfi_insn_data *cfi_insn)
> {
> + /* Conditionally invoke S390-specific implementation. */
> + if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
> + return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
> +
> /* Previous value of register1 is register2. However, if the specified
> register1 is not interesting (FP or RA reg), the current DW_CFA_register
> instruction can be safely skipped without sacrificing the asynchronicity of
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
> new file mode 100644
> index 000000000000..0a5c8eb579e3
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
> @@ -0,0 +1,22 @@
> +#name: SFrame generation on s390x - RA and then FP saved in registers
> +#objdump: --sframe=.sframe
> +#...
> +Contents of the SFrame section .sframe:
> +
> + Header :
> +
> + Version: SFRAME_VERSION_2
> + Flags: NONE
> + Num FDEs: 1
> + Num FREs: 5
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x0, size = 26 bytes
> + STARTPC +CFA +FP +RA +
> + 0+0000 +sp\+160 +u +u +
> + 0+0004 +sp\+160 +u +r16 +
> + 0+0008 +sp\+160 +r17 +r16 +
> + 0+0014 +sp\+160 +u +r16 +
> + 0+0018 +sp\+160 +u +u +
> +#pass
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.s
> similarity index 100%
> rename from gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.s
> rename to gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.s
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d
> index 7f1acd8c5d05..23e0411d8a2c 100644
> --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d
> @@ -1,6 +1,6 @@
> -#name: SFrame generation on s390x - FP and then RA saved in register
> +#name: SFrame generation on s390x - FP without RA saved in registers
> #as: --gsframe
> -#warning: FP register 11 in .cfi_register
> +#warning: FP without RA on stack
> #objdump: --sframe=.sframe
> #...
> Contents of the SFrame section .sframe:
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d
> deleted file mode 100644
> index 6573d01b997b..000000000000
> --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -#name: SFrame generation on s390x - RA and then FP saved in register
> -#as: --gsframe
> -#warning: RA register 14 in .cfi_register
> -#objdump: --sframe=.sframe
> -#...
> -Contents of the SFrame section .sframe:
> -
> - Header :
> -
> - Version: SFRAME_VERSION_2
> - Flags: NONE
> - Num FDEs: 0
> - Num FREs: 0
> -
> -#pass
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> index d17cd767cc6e..1e7fc9e03cad 100644
> --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> @@ -120,6 +120,6 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
> run_dump_test "cfi-sframe-s390x-err-3"
> run_dump_test "cfi-sframe-s390x-fpra-offset-1"
> run_dump_test "cfi-sframe-s390x-fpra-offset-err-1"
> + run_dump_test "cfi-sframe-s390x-fpra-register-1"
> run_dump_test "cfi-sframe-s390x-fpra-register-err-1"
> - run_dump_test "cfi-sframe-s390x-fpra-register-err-2"
> }
> diff --git a/include/sframe-api.h b/include/sframe-api.h
> index 77ba32b0f4b9..f47afff1fd5e 100644
> --- a/include/sframe-api.h
> +++ b/include/sframe-api.h
> @@ -198,12 +198,18 @@ extern int32_t
> sframe_fre_get_cfa_offset (sframe_decoder_ctx *dtcx,
> sframe_frame_row_entry *fre, int *errp);
>
> -/* Get the FP offset from the FRE. If the offset is invalid, sets errp. */
> +/* Get the FP offset from the FRE. If the offset is invalid, sets errp.
> +
> + For s390x the offset may be an encoded register number, indicated by
> + LSB set to one, which is only valid in the topmost frame. */
> extern int32_t
> sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
> sframe_frame_row_entry *fre, int *errp);
>
> -/* Get the RA offset from the FRE. If the offset is invalid, sets errp. */
> +/* Get the RA offset from the FRE. If the offset is invalid, sets errp.
> +
> + For s390x the offset may be an encoded register number, indicated by
> + LSB set to one, which is only valid in the topmost frame. */
> extern int32_t
> sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx,
> sframe_frame_row_entry *fre, int *errp);
> diff --git a/include/sframe.h b/include/sframe.h
> index a87d6d491a2f..393748bcd2ad 100644
> --- a/include/sframe.h
> +++ b/include/sframe.h
> @@ -347,6 +347,19 @@ typedef struct sframe_frame_row_entry_addr4
> SP value offset from CFA is -160. */
> #define SFRAME_S390X_SP_VAL_OFFSET (-160)
>
> +/* On s390x, the FP and RA registers can be saved either on the stack or,
> + in case of leaf functions, in registers. Store DWARF register numbers
> + encoded as offset by using the least-significant bit (LSB) as indicator:
> + - LSB=0: Stack offset. The s390x ELF ABI mandates that stack register
> + slots must be 8-byte aligned.
> + - LSB=1: DWARF register number shifted to the left by one. */
> +#define SFRAME_S390X_OFFSET_IS_REGNUM(offset) \
> + ((offset) & 1)
> +#define SFRAME_S390X_OFFSET_ENCODE_REGNUM(regnum) \
> + (((regnum) << 1) | 1)
> +#define SFRAME_S390X_OFFSET_DECODE_REGNUM(offset) \
> + ((offset) >> 1)
> +
Perhaps it wont hurt to also use "SFRAME_V2" as prefix in the names:
- SFRAME_V2_S390X_OFFSET_IS_REGNUM
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM
This also aligns well with the choice made in the rest of the series
(SFRAME_V2_FRE_S390X_CFA_OFFSET_ENCODE,
SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE).
> #ifdef __cplusplus
> }
> #endif
> diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi
> index ce06e50e3d1f..98c056c213d2 100644
> --- a/libsframe/doc/sframe-spec.texi
> +++ b/libsframe/doc/sframe-spec.texi
> @@ -134,7 +134,13 @@ architecture (64-bit) s390x ABI. Other s390x-specific backward compatible
> changes including the following helper definitions have been incrementally
> added to SFrame version 2 only:
> @itemize @bullet
> -@item SFRAME_S390X_SP_VAL_OFFSET: SP value offset from CFA.
> +@item SFRAME_S390X_SP_VAL_OFFSET: SP value offset (from CFA).
> +@item SFRAME_S390X_OFFSET_IS_REGNUM: Test whether FP/RA offset is an encoded
> +DWARF register number.
> +@item SFRAME_S390X_OFFSET_ENCODE_REGNUM: Encode a DWARF register number as an
> +FP/RA offset.
> +@item SFRAME_S390X_OFFSET_DECODE_REGNUM: Decode a DWARF register number from
> +an FP/RA offset.
> @end itemize
> @end itemize
>
> @@ -772,10 +778,11 @@ This section covers the ABI/arch-specific definition of the SFrame file format.
>
> Currently, the only part of the SFrame file format definition that is
> ABI/arch-specific is the interpretation of the variable number of bytes at the
> -tail end of each SFrame FRE. Currently, these bytes are only used for
> -representing stack offsets (for all the currently supported ABIs). It is
> -recommended to peruse this section along with @xref{SFrame Frame Row Entries}
> -for clarity of context.
> +tail end of each SFrame FRE. Currently, these bytes are used for representing
> +stack offsets (for AMD64 and AARCH64 ABIs). For s390x ABI, the interpretation
> +of these bytes may be stack offsets or even register numbers. It is recommended
> +to peruse this section along with @xref{SFrame Frame Row Entries} for clarity of
> +context.
>
> Future ABIs must specify the algorithm for identifying the appropriate SFrame
> FRE stack offsets in this chapter. This should inevitably include the
> @@ -870,16 +877,30 @@ frame only. The third stack offset is used to locate the FP stack slot, by
> interpreting it as: FP = CFA + offset3. FP remains unchanged, if the offset is
> not available.
>
> -Given the nature of things, the number of stack offsets seen on s390x per
> -SFrame FRE is either 1, 2, or 3.
> +In leaf functions the RA and FP may be saved in other registers, such as
> +floating-point registers (FPRs), instead of on the stack. To represent this
> +in the SFrame stack trace format the DWARF register number is encoded as
> +RA/FP offset using the least-significant bit (LSB) as indication:
> +offset = (regnum << 1) | 1. A LSB of zero indicates a stack slot offset.
> +A LSB of one indicates a DWARF register number, which is interpreted as:
> +regnum = offset >> 1. Given the nature of leaf functions, this can only occur
> +in the topmost frame during stack tracing. It is recommended that a stack
> +tracer implementation performs the required checks to ensure that restoring
> +FP and RA from the said register locations is done only for topmost stack
> +frame in the callchain.
> +
> +Given the nature of things, the number of stack offsets and/or register numbers
> +seen on s390x per SFrame FRE is either 1, 2, or 3.
>
> Hence, in summary:
>
> -@multitable {Offset ID} {Interpretation in s390x in X}
> +@multitable @columnfractions .15 .85
> @headitem Offset ID @tab Interpretation in s390x
> @item 1 @tab CFA = @code{BASE_REG} + offset1
> -@item 2 @tab RA = CFA + offset2
> -@item 3 @tab FP = CFA + offset3
> +@item 2 @tab RA stack slot = CFA + offset2, if (offset2 & 1 == 0)
> + @*RA register number = offset2 >> 1, if (offset2 & 1 == 1)
> +@item 3 @tab FP stack slot = CFA + offset3, if (offset3 & 1 == 0)
> + @*FP register number = offset3 >> 1, if (offset3 & 1 == 1)
> @end multitable
>
> The s390x ELF ABI defines the CFA as stack pointer (SP) at call site +160. The
> diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c
> index 1fa508d9bad2..09ecd4faab54 100644
> --- a/libsframe/sframe-dump.c
> +++ b/libsframe/sframe-dump.c
> @@ -40,6 +40,14 @@ is_sframe_abi_arch_aarch64 (sframe_decoder_ctx *sfd_ctx)
> return aarch64_p;
> }
>
> +/* Return TRUE if the SFrame section is associated with the s390x ABI. */
> +
> +static bool
> +is_sframe_abi_arch_s390x (sframe_decoder_ctx *sfd_ctx)
> +{
> + return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390X_ENDIAN_BIG;
> +}
> +
> static void
> dump_sframe_header (sframe_decoder_ctx *sfd_ctx)
> {
> @@ -175,7 +183,13 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
>
> /* Dump SP/FP info. */
> if (err[1] == 0)
> - sprintf (temp, "c%+d", fp_offset);
> + {
> + if (is_sframe_abi_arch_s390x (sfd_ctx)
> + && SFRAME_S390X_OFFSET_IS_REGNUM (fp_offset))
> + sprintf (temp, "r%d", SFRAME_S390X_OFFSET_DECODE_REGNUM (fp_offset));
> + else
> + sprintf (temp, "c%+d", fp_offset);
> + }
> else
> strcpy (temp, "u");
> printf ("%-10s", temp);
> @@ -187,7 +201,13 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
> != SFRAME_CFA_FIXED_RA_INVALID)
> strcpy (temp, "f");
> else if (err[2] == 0)
> - sprintf (temp, "c%+d", ra_offset);
> + {
> + if (is_sframe_abi_arch_s390x (sfd_ctx)
> + && SFRAME_S390X_OFFSET_IS_REGNUM (ra_offset))
> + sprintf (temp, "r%d", SFRAME_S390X_OFFSET_DECODE_REGNUM (ra_offset));
> + else
> + sprintf (temp, "c%+d", ra_offset);
> + }
> else
> strcpy (temp, "u");
>
> diff --git a/libsframe/sframe.c b/libsframe/sframe.c
> index 4a62b8bb2762..e5f9b198402d 100644
> --- a/libsframe/sframe.c
> +++ b/libsframe/sframe.c
> @@ -679,7 +679,10 @@ sframe_fre_get_cfa_offset (sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED,
> return sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, errp);
> }
>
> -/* Get the FP offset from the FRE. If the offset is invalid, sets errp. */
> +/* Get the FP offset from the FRE. If the offset is invalid, sets errp.
> +
> + For s390x the offset may be an encoded register number, indicated by
> + LSB set to one, which is only valid in the topmost frame. */
>
> int32_t
> sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
> @@ -706,7 +709,10 @@ sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
> return sframe_get_fre_offset (fre, fp_offset_idx, errp);
> }
>
> -/* Get the RA offset from the FRE. If the offset is invalid, sets errp. */
> +/* Get the RA offset from the FRE. If the offset is invalid, sets errp.
> +
> + For s390x the offset may be an encoded register number, indicated by
> + LSB set to one, which is only valid in the topmost frame. */
>
> int32_t
> sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx,
More information about the Binutils
mailing list