[PATCH v3 03/11] s390: Initial support to generate .sframe from CFI directives in assembler

Jens Remus jremus@linux.ibm.com
Mon Jul 7 15:22:17 GMT 2025


Hello Indu,

thank you for the review and feedback!

On 06.07.2025 01:03, Indu Bhagat via Binutils wrote:
> On 6/27/25 4:08 AM, Jens Remus wrote:
>> This introduces initial support to generate .sframe from CFI directives
>> in assembler on s390 64-bit (s390x).  Due to SFrame V2 format
>> limitations it has the following limitations, some of them getting
>> addressed by subsequent patches, which cause generation of SFrame FDE
>> to be skipped:
>>
>> - SFrame FP/RA tracking only supports register contents being saved on
>>    the stack (i.e. .cfi_offset).  It does not support FP/RA register
>>    contents being saved in other registers (i.e. .cfi_register).  GCC on
>>    s390x can be observed to save the FP/RA register contents in floating-
>>    point registers, but only in leaf functions.
>>    This issue is detailed further and resolved in the subsequent commit
>>    "s390: Represent FP/RA saved in register in SFrame".
>>
>> - SFrame FP/RA tracking cannot represent FP without RA saved.  This is
>>    because the format assumes SFrame FDE offset2 to be the RA offset, if
>>    there are two offsets, and offset3 to be the FP offset, if there are
>>    three offsets.  There is no mean to distinguish whether offset2 is the
>>    RA or FP offset, if there are only two offsets.
>>    This issue is detailed further and resolved in the subsequent commit
>>    "s390: Represent FP without RA saved in SFrame".
>>
>> - SFrame assumes a dedicated FP register number.  The s390x ELF ABI [1]
>>    does only designate register 11 as preferred FP register number.  In
>>    general GCC and Clang on s390x use register 11 as frame pointer.
>>    GCC on s390x can be observed to use register 14 as frame pointer in
>>    the stack clash protector in the function prologue.
>>    glibc on s390x contains hand-written assembler code that uses
>>    register 12 as frame pointer.
>>
>> This s390x support is largely based on the AArch64 support from commit
>> b52c4ee46657 ("gas: generate .sframe from CFI directives").
>>
>> The SFrame ABI/arch identifier SFRAME_ABI_S390X_ENDIAN_BIG is introduced
>> for s390x and added to the SFrame format specification.
>>
>> The s390x ELF ABI [1] specifies the following C calling conventions for
>> s390x architecture:
>> - Register 15 is the stack pointer (SP).
>> - Register 14 contains the return address (RA) at function entry.
>> - There is no dedicated frame pointer register.  Register 11 is the
>>    preferred frame pointer (FP). [2]  GCC and Clang in general use
>>    register 11 as frame pointer.
>> - The CFA is defined as SP at call site +160. [3]  The SP at call site
>>    can therefore be derived from the CFA using a SP value offset from CFA
>>    of -160.
>>
>> The s390x ELF ABI [1] does not assign any standard save slot to each
>> register in the register save area of a stack frame.  Neither the
>> return address (RA, r14) nor preferred frame pointer (FP, r11)
>> necessarily need to be saved.  Therefore SFrame RA and FP tracking is
>> used.
>>
>> Support for SFrame on s390 is only enabled for the 64-bit s390x ELF ABI
>> (z/Architecture with 64-bit addressing mode).  It is disabled for the
>> 32-bit s390 ELF ABI (ESA/390 or z/Architecture with 32-bit addressing
>> mode).
>>
>> s390x-specific SFrame assembler and linker tests are added, including
>> error tests for use of a non-preferred frame pointer (FP) register and
>> specification of a non-default return address (RA) register.
>>
>> [1]: s390x ELF ABI, https://github.com/IBM/s390x-abi/releases
>> [2]: s390x ELF ABI, commit f00421825979 ("Add information about the frame
>>       pointer register"),
>>       https://github.com/IBM/s390x-abi/commit/f00421825979
>> [3]: s390x ELF ABI, commit 4e38ad9c8a88 ("Document the CFA"),
>>       https://github.com/IBM/s390x-abi/commit/4e38ad9c8a88
>>
>> include/
>>     * sframe.h: Add reference to s390x architecture in comments.
>>     (SFRAME_ABI_S390X_ENDIAN_BIG): Define SFrame ABI/arch identifier
>>     for s390x.
>>     (SFRAME_S390X_SP_VAL_OFFSET): Define s390x-specific SP value
>>     offset from CFA.
>>
>> libsframe/
>>     * sframe.c (need_swapping): Add SFRAME_ABI_S390X_ENDIAN_BIG.
>>     * doc/sframe-spec.texi (SFRAME_ABI_S390X_ENDIAN_BIG, s390x,
>>     SFRAME_S390X_SP_VAL_OFFSET): Document SFrame ABI/arch identifier
>>     for s390x, add references to s390x architecture, and document
>>     s390x-specifics, such as the SP value offset from CFA of -160.
>>
>> gas/
>>     * config/tc-s390.h: s390x support to generate .sframe from CFI
>>     directives in assembler.
>>     (support_sframe_p): Define.
>>     (SFRAME_CFA_SP_REG, SFRAME_CFA_FP_REG, SFRAME_CFA_RA_REG):
>>     Define.
>>     (sframe_ra_tracking_p): Define.
>>     (sframe_cfa_ra_offset): Define.
>>     (sframe_get_abi_arch): Define.
>>     * config/tc-s390.c: s390x support to generate .sframe from CFI
>>     directives in assembler.
>>     (s390_sframe_cfa_sp_reg, s390_sframe_cfa_fp_reg,
>>     s390_sframe_cfa_ra_reg): New.  Initialize to DWARF register
>>     numbers of stack pointer (SP, r15), preferred frame pointer
>>     (FP, r11), and return address (RA, r14) registers.
>>     (s390_support_sframe_p): New function.  Return true if s390x.
>>     (s390_sframe_ra_tracking_p): New function.  Return true.
>>     (s390_sframe_cfa_ra_offset): New function.  Return
>>     SFRAME_CFA_FIXED_RA_INVALID.
>>     (s390_sframe_get_abi_arch): New function.  Return
>>     SFRAME_ABI_S390X_ENDIAN_BIG if s390x, otherwise zero.
>>     * gen-sframe.c: Add reference to s390x architecture in comments.
>>     (sframe_xlate_do_val_offset): Add support for s390x-specific
>>     SFRAME_S390X_SP_VAL_OFFSET.
>>     * NEWS: Add news entry.
>>
>> gas/testsuite/
>>     * gas/cfi-sframe/cfi-sframe.exp: Enable common SFrame tests for
>>     s390x.  Add s390x-specific SFrame (error) tests.
>>     * gas/cfi-sframe/cfi-sframe-s390x-1.d: New s390x-specific SFrame
>>     test.
>>     * gas/cfi-sframe/cfi-sframe-s390x-1.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-2.d: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-2.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-1.d: New s390x-specific
>>     SFrame error test that uses a non-default frame-pointer register
>>     as CFA base register.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-1.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-2.d: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-2.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-3.d: New s390x-specific
>>     SFrame error test that uses a non-default return address
>>     register.
>>     * gas/cfi-sframe/cfi-sframe-s390x-err-3.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-1.d: New s390x-
>>     specific SFrame test that saves RA and FP individually on the
>>     stack.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-1.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-err-1.d: New
>>     s390x-specific SFrame error test that saves FP and RA
>>     individually, to trigger FP without RA saved.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-err-1.s: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d: New
>>     s390x-specific SFrame error test that saves FP and RA
>>     individually in registers.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.s:
>>     Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d: New
>>     s390x-specific SFrame error test that saves RA and FP
>>     individually in registers.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.s:
>>     Likewise.
>>
>> ld/testsuite/
>>     * ld-s390/s390.exp: Add simple SFrame test.
>>     * ld-s390/sframe-simple-1.d: New simple SFrame test.
>>     * ld-s390/sframe-bar.s: Likewise.
>>     * ld-s390/sframe-foo.s: Likewise.
>>
>> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
>> ---
>>
>> Notes (jremus):
>>      Changes in V3:
>>      - Reword commit message, adding pointers to subsequent commits. (Indu)
>>      - Remove dash in terms "frame-pointer" and "return-address". (Indu)
>>      - Separate mnemonic from operand(s) in tests using tab. (Indu)
>>      - Follow the "No Trailing operator" rule in tests. (Indu)
>>      - Update "Changes from Version 1 to Version 2" in SFrame spec. (Indu)
>>      - Reword RA description in S390 section in SFrame spec. (Indu)
>>  
> 
> Thanks Jens.
> 
> This looks good to me.
> 
> Reviewed-by: Indu Bhagat <indu.bhagat@oracle.com>
> 
> One question below.

>> diff --git a/gas/config/tc-s390.h b/gas/config/tc-s390.h

>> @@ -98,3 +98,34 @@ extern int s390_cie_data_alignment;
>>   extern void s390_elf_final_processing (void);
>>     #define elf_tc_final_processing s390_elf_final_processing
>> +
>> +/* SFrame.  */
>> +
>> +/* Whether SFrame stack trace info is supported.  */
>> +extern bool s390_support_sframe_p (void);
>> +#define support_sframe_p s390_support_sframe_p
>> +
>> +/* The stack pointer DWARF register number for SFrame CFA tracking.  */
>> +extern const unsigned int s390_sframe_cfa_sp_reg;
>> +#define SFRAME_CFA_SP_REG s390_sframe_cfa_sp_reg
>> +
>> +/* The frame pointer DWARF register number for SFrame CFA and FP tracking.  */
>> +extern const unsigned int s390_sframe_cfa_fp_reg;
>> +#define SFRAME_CFA_FP_REG s390_sframe_cfa_fp_reg
>> +
>> +/* The return address DWARF register number for SFrame RA tracking.  */
>> +extern const unsigned int s390_sframe_cfa_ra_reg;
>> +#define SFRAME_CFA_RA_REG s390_sframe_cfa_ra_reg
>> +
>> +/* Whether SFrame return address tracking is needed.  */
>> +extern bool s390_sframe_ra_tracking_p (void);
>> +#define sframe_ra_tracking_p s390_sframe_ra_tracking_p
>> +
>> +/* The fixed offset from CFA for SFrame to recover the return address.
>> +   (useful only when SFrame RA tracking is not needed).  */
>> +extern offsetT s390_sframe_cfa_ra_offset (void);
>> +#define sframe_cfa_ra_offset s390_sframe_cfa_ra_offset
>> +
>> +/* The abi/arch identifier for SFrame.  */
>> +unsigned char s390_sframe_get_abi_arch (void);
>> +#define sframe_get_abi_arch s390_sframe_get_abi_arch
> 
> With (IIUC) no non-ELF targets for s390x, then, apart from the obvious
> (s390x-linux as supported, s390-linux as not supported), are there
> other targets that you'd recommend for testing / building ?

None that I am aware of.  Note that the native (auto detected) target
that supports SFrame is "s390x-ibm-linux-gnu".  That is what I have
tested on.

> (Endianness related testing: covered by some cross builds for aarch64
> target should suffice for the endian swapping code that cross builds
> for s390x may use).

I tested "aarch64-linux-gnu" and "x86_64-pc-linux-gnu" cross builds
on s390x to verify that my changes do not break those.  I also tested
"s390x-ibm-linux-gnu" cross build on x86-64 to verify there are no
endianness issues in my changes.

Regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com

IBM

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



More information about the Binutils mailing list