[PATCH 3/8] s390: Initial support to generate .sframe from CFI directives in assembler

Indu Bhagat indu.bhagat@oracle.com
Wed Apr 16 06:13:33 GMT 2025


Hi Jens,

Thanks for your patches.

On 4/2/25 9:11 AM, Jens Remus wrote:
> This introduces initial support to generate .sframe from CFI directives
> in assembler on 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.
> 
> - 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.
> > - 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.

For stack clash protection, is the code sequence amenable to usage of 
r11 instead ?

>    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_S390_ENDIAN_BIG is introduced
> for s390/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.

I guess saying that "Register 11 is the preferred frame pointer (FP)" is 
somewhat confusing to me.  Especially when I read it in conjunction with 
the above comment around code generated for stack clash protector mode 
and...

> - 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 is only enabled for z/Architecture with 64-bit
> addressing mode (s390x).  It is disabled for z/Architecture with 32-bit
> addressing mode and ESA/390 (s390).
> 
> 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

...this.

This commit suggests r11 as "Commonly used as frame pointer", but at the 
same time also adds "If a frame pointer is maintained, it should be 
stored in \texttt{r11}".

The latter seems to suggest that r11 is now _the_ frame pointer 
register, not just "Commonly used as frame pointer" or the "preferred 
frame pointer".  I find the language shifting in terms of the implied 
strictness, and hence, confusing.

IOW, we do want r11 to be the designated frame pointer, so that code 
generated by conforming compiler also works well for stack tracing using 
SFrame.

> [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.
> 	(FRAME_ABI_S390_ENDIAN_BIG): Define SFrame ABI/arch identifier

Typo: SFRAME_ABI_S390_ENDIAN_BIG

> 	for s390x.
> 	(SFRAME_S390_SP_VAL_OFFSET): Define s390x-specific SP value
> 	offset from CFA.
> 
> libsframe/
> 	* sframe.c (need_swapping): Add SFRAME_ABI_S390_ENDIAN_BIG.
> 	* doc/sframe-spec.texi (SFRAME_ABI_S390_ENDIAN_BIG, S390,
> 	SFRAME_S390_SP_VAL_OFFSET): Document SFrame ABI/arch identifier
> 	for S390, add references to S390 architecture, and document
> 	S390-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_S390_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_S390_SP_VAL_OFFSET.
> 	* NEWS: Add news entry.
> 

I think adding an entry in binutils/NEWS is also a good idea to announce 
SFrame for s390x in general.

Perhaps as another patch by itself if you like.

> gas/testsuite/
> 	* gas/cfi-sframe/cfi-sframe.exp: Enable common SFrame tests for
> 	s390x.  Add s390-specific SFrame (error) tests.
> 	* gas/cfi-sframe/cfi-sframe-s390-1.d: New s390-specific SFrame
> 	test.
> 	* gas/cfi-sframe/cfi-sframe-s390-1.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-2.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-1.d: New s390-specific
> 	SFrame error test that uses a non-default frame-pointer register
> 	as CFA base register.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-1.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-2.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-3.d: New s390-specific
> 	SFrame error test that uses a non-default return address
> 	register.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-3.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d: New s390-
> 	specific SFrame test that saves RA and FP individually on the
> 	stack.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d: New s390-
> 	specific SFrame error test that saves FP and RA individually, to
> 	trigger FP without RA saved.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d: New
> 	s390-specific SFrame error test that saves FP and RA
> 	individually in registers.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s:
> 	Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d: New
> 	s390-specific SFrame error test that saves RA and FP
> 	individually in registers.
> 	* gas/cfi-sframe/cfi-sframe-s390-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>
> ---
>   gas/NEWS                                      |  3 +
>   gas/config/tc-s390.c                          | 55 +++++++++++++++++++
>   gas/config/tc-s390.h                          | 31 +++++++++++
>   gas/gen-sframe.c                              |  8 ++-
>   .../gas/cfi-sframe/cfi-sframe-s390-1.d        | 23 ++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-1.s        | 37 +++++++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-2.d        | 23 ++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-2.s        | 37 +++++++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-1.d    | 15 +++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-1.s    | 37 +++++++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-2.d    | 15 +++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-2.s    | 37 +++++++++++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-3.d    | 15 +++++
>   .../gas/cfi-sframe/cfi-sframe-s390-err-3.s    |  5 ++
>   .../cfi-sframe-s390-fpra-offset-1.d           | 22 ++++++++
>   .../cfi-sframe-s390-fpra-offset-1.s           | 15 +++++
>   .../cfi-sframe-s390-fpra-offset-err-1.d       | 15 +++++
>   .../cfi-sframe-s390-fpra-offset-err-1.s       | 15 +++++
>   .../cfi-sframe-s390-fpra-register-err-1.d     | 15 +++++
>   .../cfi-sframe-s390-fpra-register-err-1.s     | 15 +++++
>   .../cfi-sframe-s390-fpra-register-err-2.d     | 15 +++++
>   .../cfi-sframe-s390-fpra-register-err-2.s     | 15 +++++
>   gas/testsuite/gas/cfi-sframe/cfi-sframe.exp   | 16 +++++-
>   include/sframe.h                              | 11 +++-
>   ld/testsuite/ld-s390/s390.exp                 |  4 ++
>   ld/testsuite/ld-s390/sframe-bar.s             | 21 +++++++
>   ld/testsuite/ld-s390/sframe-foo.s             |  9 +++
>   ld/testsuite/ld-s390/sframe-simple-1.d        | 30 ++++++++++
>   libsframe/doc/sframe-spec.texi                | 41 +++++++++++++-
>   libsframe/sframe.c                            |  1 +
>   30 files changed, 593 insertions(+), 8 deletions(-)
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d
>   create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s
>   create mode 100644 ld/testsuite/ld-s390/sframe-bar.s
>   create mode 100644 ld/testsuite/ld-s390/sframe-foo.s
>   create mode 100644 ld/testsuite/ld-s390/sframe-simple-1.d
> 
> diff --git a/gas/NEWS b/gas/NEWS
> index b4fc2e9e9be2..27de1f55af92 100644
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -1,5 +1,8 @@
>   -*- text -*-
>   
> +* Initial support to generate SFrame stack trace information (.sframe) from
> +  CFI directives on s390x.
> +
>   * Support for x86 AVX10.2 256 bit rounding has been dropped, as all the
>     hardware would directly support 512 bit vecotr width.
>   
> diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c
> index a0cfeead2535..91593b2e8503 100644
> --- a/gas/config/tc-s390.c
> +++ b/gas/config/tc-s390.c
> @@ -24,6 +24,8 @@
>   #include "subsegs.h"
>   #include "dwarf2dbg.h"
>   #include "dw2gencfi.h"
> +#include "sframe.h"
> +#include "gen-sframe.h"
>   
>   #include "opcode/s390.h"
>   #include "elf/s390.h"
> @@ -97,6 +99,17 @@ const char FLT_CHARS[] = "dD";
>   /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
>   int s390_cie_data_alignment;
>   
> +/* Register numbers used for SFrame stack trace info.  */
> +
> +/* Stack-pointer DWARF register number according to s390x ELF ABI.  */
> +unsigned int s390_sframe_cfa_sp_reg = 15;
> +
> +/* Frame-pointer DWARF register number accoring to s390x GCC/LLVM convention.  */

I was going to say - Not just convention anymore.  Its as per the ABI.

But I am not sure anymore, given the fuzzy strictness level in the 
language used in commit log and the ABI commit.

> +unsigned int s390_sframe_cfa_fp_reg = 11;
> +
> +/* Return-address DWARF register number according to s390x ELF ABI.  */
> +unsigned int s390_sframe_cfa_ra_reg = DWARF2_DEFAULT_RETURN_COLUMN;
> +
>   /* The target specific pseudo-ops which we support.  */
>   
>   /* Define the prototypes for the pseudo-ops */
> @@ -2867,6 +2880,48 @@ tc_s390_regname_to_dw2regnum (char *regname)
>     return regnum;
>   }
>   
> +/* Whether SFrame stack trace info is supported.  */
> +
> +bool
> +s390_support_sframe_p (void)
> +{
> +  /* At this time, SFrame is supported for s390x (64-bit) only.  */
> +  return (s390_arch_size == 64);
> +}
> +
> +/* Specify if RA tracking is needed.  */
> +
> +bool
> +s390_sframe_ra_tracking_p (void)
> +{
> +  return true;
> +}
> +
> +/* Specify the fixed offset to recover RA from CFA.
> +   (useful only when RA tracking is not needed).  */
> +
> +offsetT
> +s390_sframe_cfa_ra_offset (void)
> +{
> +  return (offsetT) SFRAME_CFA_FIXED_RA_INVALID;
> +}
> +
> +/* Get the abi/arch indentifier for SFrame.  */

Typo: identifier

> +
> +unsigned char
> +s390_sframe_get_abi_arch (void)
> +{
> +  unsigned char sframe_abi_arch = 0;
> +
> +  if (s390_support_sframe_p ())
> +    {
> +      gas_assert (target_big_endian);
> +      sframe_abi_arch = SFRAME_ABI_S390_ENDIAN_BIG;
> +    }
> +
> +  return sframe_abi_arch;
> +}
> +
>   void
>   s390_elf_final_processing (void)
>   {
> diff --git a/gas/config/tc-s390.h b/gas/config/tc-s390.h
> index 9206c029a1c1..5c58a110eca0 100644
> --- 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 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 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 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 indentifier for SFrame.  */

Typo: identifier

> +unsigned char s390_sframe_get_abi_arch (void);
> +#define sframe_get_abi_arch s390_sframe_get_abi_arch

BTW, I make some comments below regarding using "s390x" to be more precise.

To be clear, I think these usages above of "s390", however, make sense.

> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
> index 5b5e7b14b3ab..4d00c4be0a80 100644
> --- a/gas/gen-sframe.c
> +++ b/gas/gen-sframe.c
> @@ -727,7 +727,7 @@ output_sframe_internal (void)
>       }
>     out_one (fixed_ra_offset);
>   
> -  /* None of the AMD64, or AARCH64 ABIs need the auxiliary header.
> +  /* None of the AMD64, AARCH64, or S390 ABIs need the auxiliary header.
>        When the need does arise to use this field, the appropriate backend
>        must provide this information.  */
>     out_one (0); /* Auxiliary SFrame header length.  */
> @@ -1133,7 +1133,11 @@ sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_U
>         || (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
>   #endif
>         /* Ignore SP reg, if offset matches assumed default rule.  */
> -      || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG && cfi_insn->u.ri.offset != 0))
> +      || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG
> +	  && ((sframe_get_abi_arch () != SFRAME_ABI_S390_ENDIAN_BIG
> +	       && cfi_insn->u.ri.offset != 0)
> +	      || (sframe_get_abi_arch () == SFRAME_ABI_S390_ENDIAN_BIG
> +		  && cfi_insn->u.ri.offset != SFRAME_S390_SP_VAL_OFFSET))))
>       {
>         as_warn (_("skipping SFrame FDE; %s with %s reg %u"),
>   	       cfi_esc_p ? ".cfi_escape DW_CFA_val_offset" : ".cfi_val_offset",
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.d
> new file mode 100644
> index 000000000000..211804a2309a
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.d
> @@ -0,0 +1,23 @@
> +#objdump: --sframe=.sframe
> +#name: SFrame generation on s390

Using the string "s390x" will be more appropriate IMO.  For all the 
applicable tests.

> +#...
> +Contents of the SFrame section .sframe:
> +
> +  Header :
> +
> +    Version: SFRAME_VERSION_2
> +    Flags: NONE
> +    Num FDEs: 1
> +    Num FREs: 6
> +
> +  Function Index :
> +
> +    func idx \[0\]: pc = 0x0, size = 40 bytes
> +    STARTPC +CFA +FP +RA +
> +    0+0000 +sp\+160 +u +u +
> +    0+0006 +sp\+160 +c\-72 +c\-48 +
> +    0+000c +sp\+336 +c\-72 +c\-48 +
> +    0+0010 +fp\+336 +c\-72 +c\-48 +
> +    0+001c +sp\+160 +u +u +
> +    0+001e +fp\+336 +c\-72 +c\-48 +
> +#pass
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s
> new file mode 100644
> index 000000000000..56d8425ae2b1
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s
> @@ -0,0 +1,37 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stmg	%r6,%r15,48(%r15)
> +	.cfi_offset 6, -112
> +	.cfi_offset 7, -104
> +	.cfi_offset 8, -96
> +	.cfi_offset 9, -88
> +	.cfi_offset 10, -80
> +	.cfi_offset 11, -72
> +	.cfi_offset 12, -64
> +	.cfi_offset 13, -56
> +	.cfi_offset 14, -48
> +	.cfi_offset 15, -40
> +	lay	%r15,-176(%r15)
> +	.cfi_def_cfa_offset 336
> +	lgr	%r11,%r15
> +	.cfi_def_cfa_register 11
> +	lay	%r15,-128(%r15)
> +.Lreturn:
> +	lmg	%r6,%r15,224(%r11)
> +	.cfi_remember_state
> +	.cfi_restore 15
> +	.cfi_restore 14
> +	.cfi_restore 13
> +	.cfi_restore 12
> +	.cfi_restore 11
> +	.cfi_restore 10
> +	.cfi_restore 9
> +	.cfi_restore 8
> +	.cfi_restore 7
> +	.cfi_restore 6
> +	.cfi_def_cfa 15, 160
> +	br	%r14
> +	.cfi_restore_state
> +	lay     %r15,-128(%r15)
> +	j	.Lreturn
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.d
> new file mode 100644
> index 000000000000..211804a2309a
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.d
> @@ -0,0 +1,23 @@
> +#objdump: --sframe=.sframe
> +#name: SFrame generation on s390
> +#...
> +Contents of the SFrame section .sframe:
> +
> +  Header :
> +
> +    Version: SFRAME_VERSION_2
> +    Flags: NONE
> +    Num FDEs: 1
> +    Num FREs: 6
> +
> +  Function Index :
> +
> +    func idx \[0\]: pc = 0x0, size = 40 bytes
> +    STARTPC +CFA +FP +RA +
> +    0+0000 +sp\+160 +u +u +
> +    0+0006 +sp\+160 +c\-72 +c\-48 +
> +    0+000c +sp\+336 +c\-72 +c\-48 +
> +    0+0010 +fp\+336 +c\-72 +c\-48 +
> +    0+001c +sp\+160 +u +u +
> +    0+001e +fp\+336 +c\-72 +c\-48 +
> +#pass
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.s
> new file mode 100644
> index 000000000000..4d58cdaf64a7
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.s
> @@ -0,0 +1,37 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stmg	%r6,%r15,48(%r15)
> +	.cfi_rel_offset 6, 48
> +	.cfi_rel_offset 7, 56
> +	.cfi_rel_offset 8, 64
> +	.cfi_rel_offset 9, 72
> +	.cfi_rel_offset 10, 80
> +	.cfi_rel_offset 11, 88
> +	.cfi_rel_offset 12, 96
> +	.cfi_rel_offset 13, 104
> +	.cfi_rel_offset 14, 112
> +	.cfi_rel_offset 15, 120
> +	lay	%r15,-176(%r15)
> +	.cfi_def_cfa_offset 336
> +	lgr	%r11,%r15
> +	.cfi_def_cfa_register 11
> +	lay	%r15,-128(%r15)
> +.Lreturn:
> +	lmg	%r6,%r15,224(%r11)
> +	.cfi_remember_state
> +	.cfi_restore 15
> +	.cfi_restore 14
> +	.cfi_restore 13
> +	.cfi_restore 12
> +	.cfi_restore 11
> +	.cfi_restore 10
> +	.cfi_restore 9
> +	.cfi_restore 8
> +	.cfi_restore 7
> +	.cfi_restore 6
> +	.cfi_def_cfa 15, 160
> +	br	%r14
> +	.cfi_restore_state
> +	lay     %r15,-128(%r15)
> +	j	.Lreturn
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.d
> new file mode 100644
> index 000000000000..9556e9846539
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - non-SP/FP CFA base register
> +#as: --gsframe
> +#warning: skipping SFrame FDE; non-SP/FP register 10 in .cfi_def_cfa_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-s390-err-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.s
> new file mode 100644
> index 000000000000..aef3040e8de3
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.s
> @@ -0,0 +1,37 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stmg	%r6,%r15,48(%r15)
> +	.cfi_offset 6, -112
> +	.cfi_offset 7, -104
> +	.cfi_offset 8, -96
> +	.cfi_offset 9, -88
> +	.cfi_offset 10, -80
> +	.cfi_offset 11, -72
> +	.cfi_offset 12, -64
> +	.cfi_offset 13, -56
> +	.cfi_offset 14, -48
> +	.cfi_offset 15, -40
> +	lay	%r15,-176(%r15)
> +	.cfi_def_cfa_offset 336
> +	lgr	%r10,%r15
> +	.cfi_def_cfa_register 10	# non-default frame-pointer register
> +	lay	%r15,-128(%r15)
> +.Lreturn:
> +	lmg	%r6,%r15,224(%r10)
> +	.cfi_remember_state
> +	.cfi_restore 15
> +	.cfi_restore 14
> +	.cfi_restore 13
> +	.cfi_restore 12
> +	.cfi_restore 11
> +	.cfi_restore 10
> +	.cfi_restore 9
> +	.cfi_restore 8
> +	.cfi_restore 7
> +	.cfi_restore 6
> +	.cfi_def_cfa 15, 160
> +	br	%r14
> +	.cfi_restore_state
> +	lay     %r15,-128(%r15)
> +	j	.Lreturn
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.d
> new file mode 100644
> index 000000000000..f625007498b9
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - non-SP/FP CFA base register
> +#as: --gsframe
> +#warning: skipping SFrame FDE; non-SP/FP register 10 in .cfi_def_cfa
> +#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-s390-err-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.s
> new file mode 100644
> index 000000000000..b6bbcab1a66b
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.s
> @@ -0,0 +1,37 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stmg	%r6,%r15,48(%r15)
> +	.cfi_offset 6, -112
> +	.cfi_offset 7, -104
> +	.cfi_offset 8, -96
> +	.cfi_offset 9, -88
> +	.cfi_offset 10, -80
> +	.cfi_offset 11, -72
> +	.cfi_offset 12, -64
> +	.cfi_offset 13, -56
> +	.cfi_offset 14, -48
> +	.cfi_offset 15, -40
> +	lay	%r15,-176(%r15)
> +	.cfi_def_cfa_offset 336
> +	lgr	%r10,%r15
> +	.cfi_def_cfa 10, 336		# non-default frame-pointer register
> +	lay	%r15,-128(%r15)
> +.Lreturn:
> +	lmg	%r6,%r15,224(%r10)
> +	.cfi_remember_state
> +	.cfi_restore 15
> +	.cfi_restore 14
> +	.cfi_restore 13
> +	.cfi_restore 12
> +	.cfi_restore 11
> +	.cfi_restore 10
> +	.cfi_restore 9
> +	.cfi_restore 8
> +	.cfi_restore 7
> +	.cfi_restore 6
> +	.cfi_def_cfa 15, 160
> +	br	%r14
> +	.cfi_restore_state
> +	lay     %r15,-128(%r15)
> +	j	.Lreturn
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.d
> new file mode 100644
> index 000000000000..d4b981de9400
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - non-default RA register
> +#as: --gsframe
> +#warning: skipping SFrame FDE; non-default RA register 7
> +#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-s390-err-3.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.s
> new file mode 100644
> index 000000000000..40755883c827
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.s
> @@ -0,0 +1,5 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	.cfi_return_column 7		# non-default return-address register
> +	br	%r7
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d
> new file mode 100644
> index 000000000000..f613b73af4c8
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d
> @@ -0,0 +1,22 @@
> +#objdump: --sframe=.sframe
> +#name: SFrame generation on s390 - FP and RA saved on stack
> +#...
> +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 = 34 bytes
> +    STARTPC +CFA +FP +RA +
> +    0+0000 +sp\+160 +u +u +
> +    0+0006 +sp\+160 +u +c\-48 +
> +    0+000c +sp\+160 +c\-72 +c\-48 +
> +    0+001a +sp\+160 +u +c\-48 +
> +    0+0020 +sp\+160 +u +u +
> +#pass
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s
> new file mode 100644
> index 000000000000..3d9c8cbdb774
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s
> @@ -0,0 +1,15 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stg	%r14,112(%r15)
> +	.cfi_rel_offset 14, 112
> +	stg	%r11,88(%r15)
> +	.cfi_rel_offset 11, 88
> +	la	%r11,0
> +	la	%r14,0
> +.Lreturn:
> +	lg	%r11,88(%r15)
> +	.cfi_restore 11
> +	lg	%r14,112(%r15)
> +	.cfi_restore 14
> +	br	%r14
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d
> new file mode 100644
> index 000000000000..468a150bad26
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - FP without RA saved on stack
> +#as: --gsframe
> +#warning: skipping SFrame FDE; FP without RA on stack
> +#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-s390-fpra-offset-err-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s
> new file mode 100644
> index 000000000000..a84c39105f28
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s
> @@ -0,0 +1,15 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	stg	%r11,88(%r15)
> +	.cfi_rel_offset 11, 88
> +	stg	%r14,112(%r15)
> +	.cfi_rel_offset 14, 112
> +	la	%r11,0
> +	la	%r14,0
> +.Lreturn:
> +	lg	%r14,112(%r15)
> +	.cfi_restore 14
> +	lg	%r11,88(%r15)
> +	.cfi_restore 11
> +	br	%r14
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
> new file mode 100644
> index 000000000000..ca6f9df729d1
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - FP and RA saved in register
> +#as: --gsframe
> +#warning: skipping SFrame FDE; FP register 11 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-s390-fpra-register-err-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s
> new file mode 100644
> index 000000000000..48b01ac5f57b
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s
> @@ -0,0 +1,15 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	ldgr	%f2,%r11
> +	.cfi_register 11, 17
> +	ldgr	%f0,%r14
> +	.cfi_register 14, 16
> +	la	%r11,0
> +	la	%r14,0
> +.Lreturn:
> +	lgdr	%r14,%f0
> +	.cfi_restore 14
> +	lgdr	%r11,%f2
> +	.cfi_restore 11
> +	br	%r14
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d
> new file mode 100644
> index 000000000000..670146c8eb14
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d
> @@ -0,0 +1,15 @@
> +#name: SFrame generation on s390 - FP and RA saved in register
> +#as: --gsframe
> +#warning: skipping SFrame FDE; 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-s390-fpra-register-err-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s
> new file mode 100644
> index 000000000000..1d4497178ada
> --- /dev/null
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s
> @@ -0,0 +1,15 @@
> +	.cfi_sections .sframe
> +	.cfi_startproc
> +	ldgr	%f0,%r14
> +	.cfi_register 14, 16
> +	ldgr	%f2,%r11
> +	.cfi_register 11, 17
> +	la	%r11,0
> +	la	%r14,0
> +.Lreturn:
> +	lgdr	%r11,%f2
> +	.cfi_restore 11
> +	lgdr	%r14,%f0
> +	.cfi_restore 14
> +	br	%r14
> +	.cfi_endproc
> diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> index a09946635c20..04ffbde260aa 100644
> --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
> @@ -64,7 +64,8 @@ proc gas_x86_64_check { } {
>   }
>   
>   # common tests
> -if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \
> +if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"] ||
> +       [istarget "s390x-*-*"]) \
>          && [gas_sframe_check] } then {
>   
>       global ASFLAGS
> @@ -105,3 +106,16 @@ if { [istarget "aarch64*-*-*"] && [gas_sframe_check] } then {
>       run_dump_test "cfi-sframe-aarch64-4"
>       run_dump_test "cfi-sframe-aarch64-pac-ab-key-1"
>   }
> +
> +# s390 specific tests
> +if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
> +    run_dump_test "cfi-sframe-s390-1"
> +    run_dump_test "cfi-sframe-s390-2"
> +    run_dump_test "cfi-sframe-s390-err-1"
> +    run_dump_test "cfi-sframe-s390-err-2"
> +    run_dump_test "cfi-sframe-s390-err-3"
> +    run_dump_test "cfi-sframe-s390-fpra-offset-1"
> +    run_dump_test "cfi-sframe-s390-fpra-offset-err-1"
> +    run_dump_test "cfi-sframe-s390-fpra-register-err-1"
> +    run_dump_test "cfi-sframe-s390-fpra-register-err-2"
> +}
> diff --git a/include/sframe.h b/include/sframe.h
> index a965e23bdd18..684aab811f8d 100644
> --- a/include/sframe.h
> +++ b/include/sframe.h
> @@ -93,6 +93,7 @@ extern "C"
>   #define SFRAME_ABI_AARCH64_ENDIAN_BIG      1 /* AARCH64 big endian.  */
>   #define SFRAME_ABI_AARCH64_ENDIAN_LITTLE   2 /* AARCH64 little endian.  */
>   #define SFRAME_ABI_AMD64_ENDIAN_LITTLE     3 /* AMD64 little endian.  */
> +#define SFRAME_ABI_S390_ENDIAN_BIG         4 /* S390 big endian.  */
>   

I think being more precise and using "S390X" is better.  What is the 
reason to say S390 instead of S390X ?

>   /* SFrame FRE types.  */
>   #define SFRAME_FRE_TYPE_ADDR1	0
> @@ -190,7 +191,7 @@ typedef struct sframe_func_desc_entry
>        - 2-bits: Unused.
>        ------------------------------------------------------------------------
>        |     Unused    |  PAC auth A/B key (aarch64) |  FDE type |   FRE type   |
> -     |               |        Unused (amd64)       |           |              |
> +     |               |     Unused (amd64, s390)    |           |              |
>        ------------------------------------------------------------------------
>        8               6                             5           4              0     */
>     uint8_t sfde_func_info;
> @@ -248,7 +249,7 @@ typedef struct sframe_fre_info
>        - 1 bit: Mangled RA state bit (aarch64 only).
>        ----------------------------------------------------------------------------------
>        | Mangled-RA (aarch64) |  Size of offsets   |   Number of offsets    |   base_reg |
> -     |  Unused (amd64)      |                    |                        |            |
> +     | Unused (amd64, s390) |                    |                        |            |
>        ----------------------------------------------------------------------------------
>        8                     7                    5                        1            0
>   
> @@ -274,7 +275,7 @@ typedef struct sframe_fre_info
>   
>   /* SFrame Frame Row Entry definitions.
>   
> -   Used for both AMD64 and AARCH64.
> +   Used for AMD64, AARCH64, and S390.

"s390x" ?

>   
>      An SFrame Frame Row Entry is a self-sufficient record which contains
>      information on how to generate the stack trace for the specified range of
> @@ -342,6 +343,10 @@ typedef struct sframe_frame_row_entry_addr4
>   #define SFRAME_FRE_TYPE_ADDR4_LIMIT   \
>     (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8))
>   
> +/* On S390, the CFA is defined as SP at call site + 160.  Therefore the
> +   SP value offset from CFA is -160.  */
> +#define SFRAME_S390_SP_VAL_OFFSET		-160
> +

I think its better to use s390x rather than s390 as these are two 
different ABIs.  SFrame support is for s390x only.

Is there any plan to later add support for s390 too ?

>   #ifdef	__cplusplus
>   }
>   #endif
> diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp
> index b5a9ea3c64a1..cf3a904481f8 100644
> --- a/ld/testsuite/ld-s390/s390.exp
> +++ b/ld/testsuite/ld-s390/s390.exp
> @@ -138,4 +138,8 @@ if { ([istarget "s390-*-*"] || [istarget "s390x-*-*"]) } {
>   
>   if [istarget "s390x-*-*"] {
>       run_ld_link_tests $s390xtests
> +
> +    if { ![skip_sframe_tests] } {
> +	run_dump_test "sframe-simple-1"
> +    }
>   }
> diff --git a/ld/testsuite/ld-s390/sframe-bar.s b/ld/testsuite/ld-s390/sframe-bar.s
> new file mode 100644
> index 000000000000..f7075697d1e3
> --- /dev/null
> +++ b/ld/testsuite/ld-s390/sframe-bar.s
> @@ -0,0 +1,21 @@
> +	.text
> +	.globl	bar
> +	.type	bar, @function
> +bar:
> +	.cfi_startproc
> +	stmg	%r14,%r15,112(%r15)
> +	.cfi_rel_offset %r14, 112
> +	.cfi_rel_offset %r15, 120
> +	lay	%r15,-160(%r15)
> +	.cfi_adjust_cfa_offset 160
> +	clgfi	%r2,1000
> +	jle	.Lreturn
> +	brasl	%r14,foo@PLT
> +.Lreturn:
> +	lay	%r15,160(%r15)
> +	.cfi_adjust_cfa_offset -160
> +	lg	%r14,112(%r15)
> +	.cfi_restore %r14
> +	br	%r14
> +	.cfi_endproc
> +	.size	bar, .-bar
> diff --git a/ld/testsuite/ld-s390/sframe-foo.s b/ld/testsuite/ld-s390/sframe-foo.s
> new file mode 100644
> index 000000000000..75657e93e33b
> --- /dev/null
> +++ b/ld/testsuite/ld-s390/sframe-foo.s
> @@ -0,0 +1,9 @@
> +	.text
> +	.globl	foo
> +	.type	foo, @function
> +foo:
> +	.cfi_startproc
> +	msgfi	%r2,42
> +	br	%r14
> +	.cfi_endproc
> +	.size	foo, .-foo
> diff --git a/ld/testsuite/ld-s390/sframe-simple-1.d b/ld/testsuite/ld-s390/sframe-simple-1.d
> new file mode 100644
> index 000000000000..4df5d492f01e
> --- /dev/null
> +++ b/ld/testsuite/ld-s390/sframe-simple-1.d
> @@ -0,0 +1,30 @@
> +#as: --gsframe
> +#source: sframe-foo.s
> +#source: sframe-bar.s
> +#objdump: --sframe=.sframe
> +#ld: -shared --no-rosegment
> +#name: SFrame simple link
> +
> +.*: +file format .*
> +
> +Contents of the SFrame section .sframe:
> +  Header :
> +
> +    Version: SFRAME_VERSION_2
> +    Flags: SFRAME_F_FDE_SORTED
> +    Num FDEs: 2
> +    Num FREs: 6
> +
> +  Function Index :
> +
> +    func idx \[0\]: pc = 0x228, size = 8 bytes
> +    STARTPC +CFA +FP +RA +
> +    0+228 +sp\+160 +u +u +
> +
> +    func idx \[1\]: pc = 0x230, size = 42 bytes
> +    STARTPC +CFA +FP +RA +
> +    0+230 +sp\+160 +u +u +
> +    0+236 +sp\+160 +u +c-48 +
> +    0+23c +sp\+320 +u +c-48 +
> +    0+252 +sp\+160 +u +c-48 +
> +    0+258 +sp\+160 +u +u +
> diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi
> index ae115705ca73..eba497b4d371 100644
> --- a/libsframe/doc/sframe-spec.texi
> +++ b/libsframe/doc/sframe-spec.texi
> @@ -79,8 +79,8 @@ The SFrame stack trace information is provided in a loaded section, known as the
>   @code{.sframe} section.  When available, the @code{.sframe} section appears in
>   a new segment of its own, PT_GNU_SFRAME.
>   
> -The SFrame format is currently supported only for select ABIs, namely, AMD64
> -and AAPCS64.
> +The SFrame format is currently supported only for select ABIs, namely, AMD64,
> +AAPCS64, and s390.
>   

s390x?

>   A portion of the SFrame format follows an unaligned on-disk representation.
>   Some data structures, however, (namely the SFrame header and the SFrame
> @@ -401,6 +401,10 @@ in the format.
>   @item @code{SFRAME_ABI_AMD64_ENDIAN_LITTLE}
>   @tab 3 @tab AMD64 little-endian
>   
> +@tindex SFRAME_ABI_S390_ENDIAN_BIG
> +@item @code{SFRAME_ABI_S390_ENDIAN_BIG}
> +@tab 4 @tab s390 big-endian
> +
>   @end multitable
>   
>   The presence of an explicit identification of ABI/arch in SFrame may allow
> @@ -772,6 +776,7 @@ auxiliary SFrame header, etc., if used, must also be outlined here.
>   @menu
>   * AMD64::
>   * AArch64::
> +* S390::
>   @end menu
>   
>   @node AMD64
> @@ -828,6 +833,38 @@ Hence, in summary:
>   @item 3 @tab FP = CFA + offset3
>   @end multitable
>   
> +@node S390
> +@section S390
> +
> +Irrespective of the ABI, the first stack offset is always used to locate the
> +CFA, by interpreting it as: CFA = @code{BASE_REG} + offset1.
> +The identification of the @code{BASE_REG} is done by using the
> +@code{fre_cfa_base_reg_id} field in the SFrame FRE info word.
> +
> +On S390, the s390x ELF ABI does not mandate the precise location in a function
> +where the return address (RA) and frame pointer (FP) are saved, if at all.
> +Hence the need to track RA in the SFrame stack trace format.  As RA is being
> +tracked in this ABI, the second stack offset is always used to locate the RA
> +stack slot, by interpreting it as: RA = CFA + offset2.  The third stack offset
> +is used to locate the FP stack slot, by interpreting it as: FP = CFA + offset3.
> +
> +Given the nature of things, the number of stack offsets seen on S390 per
> +SFrame FRE is either 1, 2, or 3.
> +
> +Hence, in summary:
> +
> +@multitable {Offset ID} {Interpretation in S390 in X}
> +@headitem Offset ID @tab Interpretation in S390
> +@item 1 @tab CFA = @code{BASE_REG} + offset1
> +@item 2 @tab RA = CFA + offset2
> +@item 3 @tab FP = CFA + offset3
> +@end multitable
> +
> +On S390, specifically s390x, the CFA is defined as stack pointer (SP) at call
> +site +160.  The SP can therefore be obtained using the SP value offset from CFA
> +@code{SFRAME_S390_SP_VAL_OFFSET} of -160 as follows:
> +SP = CFA + @code{SFRAME_S390_SP_VAL_OFFSET}
> +
>   @node Generating Stack Traces using SFrame
>   @appendix Generating Stack Traces using SFrame
>   
> diff --git a/libsframe/sframe.c b/libsframe/sframe.c
> index 89bc06263cef..b4b3c0c41aa2 100644
> --- a/libsframe/sframe.c
> +++ b/libsframe/sframe.c
> @@ -165,6 +165,7 @@ need_swapping (int endian)
>         case SFRAME_ABI_AMD64_ENDIAN_LITTLE:
>   	return !is_little;
>         case SFRAME_ABI_AARCH64_ENDIAN_BIG:
> +      case SFRAME_ABI_S390_ENDIAN_BIG:
>   	return is_little;
>         default:
>   	break;

I cannot help but notice this funny little function named 
"need_swapping" which takes "endian" as input arg (which is actually the 
ABI) and returns the value in based on the variable named "is_little". 
So many misnomers in this one function...Anyway, something that be 
improved later.


More information about the Binutils mailing list