]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
s390: Initial support to generate .sframe from CFI directives in assembler
authorJens Remus <jremus@linux.ibm.com>
Fri, 19 Apr 2024 13:34:09 +0000 (15:34 +0200)
committerJens Remus <jremus@linux.ibm.com>
Thu, 16 May 2024 11:32:22 +0000 (13:32 +0200)
This introduces initial support to generate .sframe from CFI directives
in assembler on s390x. Due to the following SFrame limitations it is
incomplete and does not work for most real-world applications (i.e.
generation of SFrame FDE is skipped):

- SFrame FP/RA tracking assumes the register contents to be 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 assumes a static FP register number. The s390x ELF ABI [1]
  does not specify any FP register number. GCC and clang on s390x
  usually use register 11 as frame pointer.
  GCC on s390x can also be observed to use register 14 (e.g. binutils
  and glibc builds) in the stack clash protector in the funcion
  prologue.
  glibc on s390x contains hand-written assembler code that uses
  register 12 for the frame pointer.

This s390x support is largely based on the AArch64 support from commit
b52c4ee46657 ("gas: generate .sframe from CFI directives").

SFrame ABI/arch identifier SFRAME_ABI_S390_ENDIAN_BIG is introduced
for s390 and added to the SFrame specification.

According to the s390x ELF ABI [1] the following calling conventions
are used on s390x architecture:
- Register 15 is used as stack pointer (SP). The CFA is initially
  located at offset +160 from the SP.
- Register 14 is used as return address (RA).
- There is no dedicated frame pointer. GCC and LLVM currently use
  register 11 as frame pointer.

The s390x ELF ABI [1] standard stack frame layout has the following
conventions:
- The return address (RA, r15) may be saved at offset -40 from the
  CFA. Unlike x86 AMD64 architecture it is not necessarily saved on
  the stack. Also compilers may use a non-standard stack frame layout,
  such as but not limited to GCC with option -mpacked-stack.
  Therefore SFrame RA tracking is used.
- The potential frame pointer (FP, r11) may be saved at offset -72
  from the CFA. It is not necessarily saved on the stack and compilers
  may use a non-standard stack frame layout (see above).
  Therefore SFrame FP tracking is used.

Support for SFrame is only enabled for z/Architecture (s390x) with
64-bit architecture mode. It is disabled for 32-bit architecture mode
and ESA/390 (s390).

Add s390-specific SFrame test cases. As for the error test cases add
ones that use a non-default frame pointer (FP) register number and ones
that save the return address (RA) in a non-default RA register number.

[1] ELF ABI s390x Supplement:
    https://github.com/IBM/s390x-abi/releases
[2] ELF ABI s390 Supplement:
    https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390.html
    https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390.pdf

include/
* sframe.h (SFRAME_ABI_S390_ENDIAN_BIG): Define SFrame ABI/arch
identifier for s390x. Reference s390x architecture in comments.

libsframe/
* doc/sframe-spec.texi: Document SFrame ABI/arch identifier for
s390x and reference s390x architecture.

gas/
* config/tc-s390.h: s390x support to generate .sframe from CFI
directives in assembler.
* config/tc-s390.c: Likewise.
* gen-sframe.c: Reference s390x architecture in comments.
* NEWS: Update news.

gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: Enable common SFrame test cases
for s390x. Add s390-specific SFrame (error) test cases.
* gas/cfi-sframe/cfi-sframe-s390-1.s: New s390-specific SFrame
test case.
* gas/cfi-sframe/cfi-sframe-s390-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-2.s: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-err-1.s: New s390-specific
SFrame error test case that uses a non-default frame-pointer
register as CFA base address.
* gas/cfi-sframe/cfi-sframe-s390-err-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-err-2.s: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-err-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-err-3.s: New s390-specific
SFrame error test case that uses a non-default return-address
register.
* gas/cfi-sframe/cfi-sframe-s390-err-3.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s: New s390-
specific SFrame test case that saves RA and FP individually
on the stack.
* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s: New s390-
specific SFRame error test case that saves FP and RA
individually, to trigger FP without RA.
* gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s: New
s390-specific SFrame error test case that saves FP and RA
individually in registers.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d:
Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s: New
s390-specific SFrame error test case that saves RA and FP
individually in registers.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d:
Likewise.

Reviewed-by: Andreas Krebbel <krebbel@linux.ibm.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
25 files changed:
gas/NEWS
gas/config/tc-s390.c
gas/config/tc-s390.h
gas/gen-sframe.c
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-2.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-3.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-offset-err-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
include/sframe.h
libsframe/doc/sframe-spec.texi

index cb58ca8fb8d40b7b34a23452ec0b37bdb6049570..b1c72cd997f5c107dda821d52250fae6510c0e4c 100644 (file)
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Initial support to generate .sframe from CFI directives on s390x. 
+
 * Support the NF feature in Intel APX.
 
 * Remove KEYLOCKER and SHA promotions from EVEX MAP4.
index 659c6af392bd3c00c4b63d63ef4d5ac5e3a4b09a..1f8b67adbdead0ecd53b475d88a08bea81f63662 100644 (file)
@@ -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.  */
+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 */
@@ -2860,6 +2873,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.  */
+
+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)
 {
index cd353045a822d0ac6c769d9809869d51d6d7e028..c8f172d8737b72f63567ff916f60e7c7c062ecf3 100644 (file)
@@ -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 register number for SFrame stack trace info.  */
+extern unsigned int s390_sframe_cfa_sp_reg;
+#define SFRAME_CFA_SP_REG s390_sframe_cfa_sp_reg
+
+/* The frame-pointer register number for SFrame stack trace info.  */
+extern unsigned int s390_sframe_cfa_fp_reg;
+#define SFRAME_CFA_FP_REG s390_sframe_cfa_fp_reg
+
+/* The return address register number for SFrame stack trace info.  */
+extern unsigned int s390_sframe_cfa_ra_reg;
+#define SFRAME_CFA_RA_REG s390_sframe_cfa_ra_reg
+
+/* Specify if RA tracking is needed.  */
+extern bool s390_sframe_ra_tracking_p (void);
+#define sframe_ra_tracking_p s390_sframe_ra_tracking_p
+
+/* Specify the fixed offset to recover RA from CFA.
+   (useful only when 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.  */
+unsigned char s390_sframe_get_abi_arch (void);
+#define sframe_get_abi_arch s390_sframe_get_abi_arch
index bd03be478e13518dc737b3fdb75e537db9ba7bf8..dd97d4f883935e9911b85b8349c9c6e96efa466d 100644 (file)
@@ -675,7 +675,7 @@ output_sframe_internal (void)
 #endif
   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.  */
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 (file)
index 0000000..211804a
--- /dev/null
@@ -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-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-1.s
new file mode 100644 (file)
index 0000000..56d8425
--- /dev/null
@@ -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 (file)
index 0000000..211804a
--- /dev/null
@@ -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 (file)
index 0000000..4d58cda
--- /dev/null
@@ -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 (file)
index 0000000..e0b8903
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - non-SP/FP CFA base register
+#as: --gsframe
+#warning: skipping SFrame FDE due to .cfi_def_cfa_register defining non-SP/FP register 10 as CFA base 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 (file)
index 0000000..aef3040
--- /dev/null
@@ -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 (file)
index 0000000..45c090f
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - non-SP/FP CFA base register
+#as: --gsframe
+#warning: skipping SFrame FDE due to .cfi_def_cfa defining non-SP/FP register 10 as CFA base 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-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-err-2.s
new file mode 100644 (file)
index 0000000..b6bbcab
--- /dev/null
@@ -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 (file)
index 0000000..9bd970c
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - non-default RA register
+#as: --gsframe
+#warning: skipping SFrame FDE due to non-default return-address 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 (file)
index 0000000..4075588
--- /dev/null
@@ -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 (file)
index 0000000..f613b73
--- /dev/null
@@ -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 (file)
index 0000000..3d9c8cb
--- /dev/null
@@ -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 (file)
index 0000000..cc22bef
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - FP without RA saved on stack
+#as: --gsframe
+#warning: skipping SFrame FDE due to 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 (file)
index 0000000..a84c391
--- /dev/null
@@ -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 (file)
index 0000000..2b9456b
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - FP and RA saved in register
+#as: --gsframe
+#warning: skipping SFrame FDE due to .cfi_register specifying FP 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 (file)
index 0000000..48b01ac
--- /dev/null
@@ -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 (file)
index 0000000..4c15bd0
--- /dev/null
@@ -0,0 +1,15 @@
+#name: SFrame generation on s390 - FP and RA saved in register
+#as: --gsframe
+#warning: skipping SFrame FDE due to .cfi_register specifying RA 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 (file)
index 0000000..1d44971
--- /dev/null
@@ -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
index cfae28d39aaf6593a6c1c20db512b13398c47501..67735d437c2a926d56e906cde65d2efd41475f79 100644 (file)
@@ -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
@@ -99,3 +100,16 @@ if { [istarget "aarch64*-*-*"] && [gas_sframe_check] } then {
     run_dump_test "cfi-sframe-aarch64-2"
     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"
+}
index b3d0c2e937d305873682f6bd1cd7ad348a4d0582..90bc92a32f84ff7d914cd4ad032501c50a89e34e 100644 (file)
@@ -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.  */
 
 /* 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.
 
    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
index d0f99bd698ebfd6beda45831a563f1af29c24bd7..a81faf49f5c100a57e3854a2a4d23381a30b70a3 100644 (file)
@@ -74,8 +74,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.
 
 A portion of the SFrame format follows an unaligned on-disk representation.
 Some data structures, however, (namely the SFrame header and the SFrame
@@ -366,6 +366,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