[PATCH 1/4] LoongArch: Initial support to generate .sframe from CFI directives in assembler
Huang Pei
huangpei@loongson.cn
Thu Sep 25 12:48:28 GMT 2025
This introduces initial support to generate .sframe from CFI directives
in assembler on LoongArch 64-bit. There are two remaining issues:
- LoongArch ELF ABI say nothing about stack backtrace based on
frame-pointer(FP), so there is same limitation as s390x that FP is saved
on stack but RA not saved
- LoongArch ELF ABI say nothing about using float point register or
other integer register to save SP/FP/RA(but the ISA support it), but
DRAP need to save the original SP into caller-saved register, when
aligned to the new position. Since DRAP is delayed till SFrame V3, just
leave it some time.
Later patches will solve the Issue one.
include/
* sframe.h: Add loongarch architecture.
(SFRAME_ABI_LOONGARCH_ENDIAN_LITTLE): Define SFrame arch/ABI
identifier for LoongArch.
libsframe/
* sframe.c: no swapping.
gas/config/
* tc-loongarch.h: loongarch 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_rg_offset): Define.
(sframe_get_abi_arch): Define.
* tc-loongarch.c: loongarch support to generate .sframe from CFI
directives in assembler.
(loongarch_sframe_cfa_sp_reg, loongarch_sframe_fp_reg,
loongarch_sframe_ra_reg): New. Initialize to DWARF register
numbers f stack pointer(SP, r3), frame pointer(FP, r22) and
return address register(RA, r1).
(loongarch_support_sframe_p): New function. Return true.
(loongarch_sframe_cfa_ra_offset): New Function. Return
SFRAME_CFA_FIXED_RA_INVALID).
(loongarch_sframe_get_abi_arch): New function. Return
SFRAME_ABI_LOONGARCH_ENDIAN_LITTLE.
gas/testsuite/gas/cfi-sframe/
* cfi-sframe.exp: Enable common SFrame tests for loongarch. Add
loongarch-specific SFrame (error) tests.
* cfi-sframe-loongarch-1.d: New loongarch-specific SFrame test.
* cfi-sframe-loongarch-1.s: Likewise.
* cfi-sframe-loongarch-2.d: Likewise.
* cfi-sframe-loongarch-2.s: Likewise.
* cfi-sframe-loongarch-3.d: Likewise.
* cfi-sframe-loongarch-3.d: Likewise.
* cfi-sframe-loongarch-err-1.d: New Loongarch-specific SFrame
error test that FP is saved on stack without RA saved.
* cfi-sframe-loongarch-err-1.s: Likewise.
gas/testsuite/cfi-sframe/
* cfi-sframe-loongarch-err-1.s: Rename to ...
* cfi-sframe-loongarch-err-1.d: Deleted.
* cfi-sframe-loongarch-4.d: New test for representing FP without
RA saved in SFrame.
Signed-off-by: Huang Pei <huangpei@loongson.cn>
---
gas/config/tc-loongarch.c | 48 ++++++++++++++
gas/config/tc-loongarch.h | 28 +++++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-1.d | 21 +++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-1.s | 45 ++++++++++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-2.d | 23 +++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-2.s | 50 +++++++++++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-3.d | 25 ++++++++
.../gas/cfi-sframe/cfi-sframe-loongarch-3.s | 62 +++++++++++++++++++
.../cfi-sframe/cfi-sframe-loongarch-err-1.d | 15 +++++
.../cfi-sframe/cfi-sframe-loongarch-err-1.s | 62 +++++++++++++++++++
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 10 ++-
include/sframe.h | 1 +
.../ld-loongarch-elf/ld-loongarch-elf.exp | 4 ++
ld/testsuite/ld-loongarch-elf/sframe-bar.s | 17 +++++
ld/testsuite/ld-loongarch-elf/sframe-foo.s | 8 +++
.../ld-loongarch-elf/sframe-simple-1.d | 27 ++++++++
libsframe/sframe.c | 1 +
17 files changed, 446 insertions(+), 1 deletion(-)
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.s
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.s
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.s
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.s
create mode 100644 ld/testsuite/ld-loongarch-elf/sframe-bar.s
create mode 100644 ld/testsuite/ld-loongarch-elf/sframe-foo.s
create mode 100644 ld/testsuite/ld-loongarch-elf/sframe-simple-1.d
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 4593f06614a..4ce7bc409f4 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -27,6 +27,8 @@
#include "opcode/loongarch.h"
#include "obj-elf.h"
#include "bfd/elfxx-loongarch.h"
+#include "sframe.h"
+#include "gen-sframe.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -118,6 +120,11 @@ static const char default_arch[] = DEFAULT_ARCH;
static bool call36 = 0;
+unsigned int loongarch_sframe_cfa_sp_reg;
+/* The other CFA base register for SFrame stack trace info. */
+unsigned int loongarch_sframe_cfa_ra_reg;
+unsigned int loongarch_sframe_cfa_fp_reg;
+
/* The lowest 4-bit is the bytes of instructions. */
#define RELAX_BRANCH_16 0xc0000014
#define RELAX_BRANCH_21 0xc0000024
@@ -512,6 +519,9 @@ md_begin ()
align_hash = htab_create (10, align_sec_sym_hash, align_sec_sym_eq, free);
+ loongarch_sframe_cfa_sp_reg = 3;
+ loongarch_sframe_cfa_fp_reg = 22;
+ loongarch_sframe_cfa_ra_reg = 1;
/* FIXME: expressionS use 'offsetT' as constant,
* we want this is 64-bit type. */
assert (8 <= sizeof (offsetT));
@@ -1900,6 +1910,44 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
return reloc;
}
+/* Whether SFrame stack trace info is supported. */
+
+bool
+loongarch_support_sframe_p (void)
+{
+ /* At this time, SFrame is supported for all LoongArch ABI, since
+ * there is *Only One* calling convention */
+ return true;
+}
+
+/* Whether SFrame return address tracking is needed. */
+
+bool
+loongarch_sframe_ra_tracking_p (void)
+{
+ /* LoongArch ABI *Does Not* specify the position of RA in call
+ * frame */
+ return true;
+}
+
+/* The fixed offset from CFA for SFrame to recover the return address.
+ (useful only when SFrame RA tracking is not needed). */
+
+offsetT
+loongarch_sframe_cfa_ra_offset (void)
+{
+ return (offsetT) SFRAME_CFA_FIXED_RA_INVALID;
+}
+
+/* Get the abi/arch identifier for SFrame. */
+
+unsigned char
+loongarch_sframe_get_abi_arch (void)
+{
+
+ return SFRAME_ABI_LOONGARCH_ENDIAN_LITTLE;
+}
+
/* Standard calling conventions leave the CFA at SP on entry. */
void
loongarch_cfi_frame_initial_instructions (void)
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 38ecd036d34..ea13f390b61 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -148,4 +148,32 @@ struct reloc_info
#define md_finish loongarch_md_finish
extern void loongarch_md_finish (void);
+/* Whether SFrame stack trace info is supported. */
+extern bool loongarch_support_sframe_p (void);
+#define support_sframe_p loongarch_support_sframe_p
+
+/* The stack pointer DWARF register number for SFrame CFA tracking. */
+extern unsigned int loongarch_sframe_cfa_sp_reg;
+#define SFRAME_CFA_SP_REG loongarch_sframe_cfa_sp_reg
+
+/* The frame pointer DWARF register number for SFrame CFA and FP tracking. */
+extern unsigned int loongarch_sframe_cfa_fp_reg;
+#define SFRAME_CFA_FP_REG loongarch_sframe_cfa_fp_reg
+
+/* The return address DWARF register number for SFrame RA tracking. */
+extern unsigned int loongarch_sframe_cfa_ra_reg;
+#define SFRAME_CFA_RA_REG loongarch_sframe_cfa_ra_reg
+
+/* Whether SFrame return address tracking is needed. */
+extern bool loongarch_sframe_ra_tracking_p (void);
+#define sframe_ra_tracking_p loongarch_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 loongarch_sframe_cfa_ra_offset (void);
+#define sframe_cfa_ra_offset loongarch_sframe_cfa_ra_offset
+
+/* The abi/arch identifier for SFrame. */
+unsigned char loongarch_sframe_get_abi_arch (void);
+#define sframe_get_abi_arch loongarch_sframe_get_abi_arch
#endif
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.d
new file mode 100644
index 00000000000..24a2f857c61
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.d
@@ -0,0 +1,21 @@
+#name: SFrame generation on loongarch -- Only CFA
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 3
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 88 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+0 +u +u +
+ 0+0004 +sp\+96 +u +u +
+ 0+0054 +sp\+0 +u +u +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.s
new file mode 100644
index 00000000000..f04f5409fb0
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-1.s
@@ -0,0 +1,45 @@
+ .cfi_sections .sframe
+ .cfi_startproc
+ addi.d $r3, $r3, -96
+ .cfi_def_cfa_offset 96
+ st.d $r23, $r3, 88
+ st.d $r24, $r3, 80
+ st.d $r25, $r3, 72
+ st.d $r26, $r3, 64
+ st.d $r27, $r3, 56
+ st.d $r28, $r3, 48
+ st.d $r29, $r3, 40
+ st.d $r30, $r3, 32
+ st.d $r31, $r3, 24
+ .cfi_offset 23, -8
+ .cfi_offset 24, -16
+ .cfi_offset 25, -24
+ .cfi_offset 26, -32
+ .cfi_offset 27, -40
+ .cfi_offset 28, -48
+ .cfi_offset 29, -56
+ .cfi_offset 30, -64
+ .cfi_offset 31, -72
+ nop
+ ld.d $r31, $r3, 24
+ ld.d $r30, $r3, 32
+ ld.d $r29, $r3, 40
+ ld.d $r28, $r3, 48
+ ld.d $r27, $r3, 56
+ ld.d $r26, $r3, 64
+ ld.d $r25, $r3, 72
+ ld.d $r24, $r3, 80
+ ld.d $r23, $r3, 88
+ .cfi_restore 31
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_restore 28
+ .cfi_restore 27
+ .cfi_restore 26
+ .cfi_restore 25
+ .cfi_restore 24
+ .cfi_restore 23
+ addi.d $r3, $r3, 96
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.d
new file mode 100644
index 00000000000..8d59d67db51
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.d
@@ -0,0 +1,23 @@
+#name: SFrame generation on loongarch -- RA without FP
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 5
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 100 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+0 +u +u +
+ 0+0004 +sp\+96 +u +u +
+ 0+002c +sp\+96 +u +c\-8 +
+ 0+005c +sp\+96 +u +u +
+ 0+0060 +sp\+0 +u +u +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.s
new file mode 100644
index 00000000000..b6dcf3d442b
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-2.s
@@ -0,0 +1,50 @@
+ .cfi_sections .sframe
+ .cfi_startproc
+ addi.d $r3, $r3, -96
+ .cfi_def_cfa_offset 96
+ st.d $r1, $r3, 88
+ st.d $r23, $r3, 80
+ st.d $r24, $r3, 72
+ st.d $r25, $r3, 64
+ st.d $r26, $r3, 56
+ st.d $r27, $r3, 48
+ st.d $r28, $r3, 40
+ st.d $r29, $r3, 32
+ st.d $r30, $r3, 24
+ st.d $r31, $r3, 16
+ .cfi_offset 1, -8
+ .cfi_offset 23, -16
+ .cfi_offset 24, -24
+ .cfi_offset 25, -32
+ .cfi_offset 26, -40
+ .cfi_offset 27, -48
+ .cfi_offset 28, -56
+ .cfi_offset 29, -64
+ .cfi_offset 30, -72
+ .cfi_offset 31, -80
+ nop
+ ld.d $r31, $r3, 8
+ ld.d $r30, $r3, 16
+ ld.d $r29, $r3, 24
+ ld.d $r28, $r3, 32
+ ld.d $r27, $r3, 40
+ ld.d $r26, $r3, 48
+ ld.d $r25, $r3, 56
+ ld.d $r24, $r3, 64
+ ld.d $r23, $r3, 72
+ ld.d $r22, $r3, 80
+ ld.d $r1, $r3, 88
+ .cfi_restore 31
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_restore 28
+ .cfi_restore 27
+ .cfi_restore 26
+ .cfi_restore 25
+ .cfi_restore 24
+ .cfi_restore 23
+ .cfi_restore 1
+ addi.d $r3, $r3, 96
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.d
new file mode 100644
index 00000000000..9945b20a9f9
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.d
@@ -0,0 +1,25 @@
+#name: SFrame generation on loongarch -- RA and FP with alloca
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 7
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 124 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+0 +u +u +
+ 0+0004 +sp\+96 +u +u +
+ 0+0030 +sp\+96 +c\-16 +c\-8 +
+ 0+0038 +fp\+96 +c\-16 +c\-8 +
+ 0+0048 +sp\+96 +c\-16 +c\-8 +
+ 0+0074 +sp\+96 +u +u +
+ 0+0078 +sp\+0 +u +u +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.s
new file mode 100644
index 00000000000..f257f26f157
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-3.s
@@ -0,0 +1,62 @@
+ .cfi_sections .sframe
+ .cfi_startproc
+ addi.d $r3, $r3, -96
+ .cfi_def_cfa_offset 96
+ st.d $r1, $r3, 88
+ st.d $r22, $r3, 80
+ st.d $r23, $r3, 72
+ st.d $r24, $r3, 64
+ st.d $r25, $r3, 56
+ st.d $r26, $r3, 48
+ st.d $r27, $r3, 40
+ st.d $r28, $r3, 32
+ st.d $r29, $r3, 24
+ st.d $r30, $r3, 16
+ st.d $r31, $r3, 8
+ .cfi_offset 1, -8
+ .cfi_offset 22, -16
+ .cfi_offset 23, -24
+ .cfi_offset 24, -32
+ .cfi_offset 25, -40
+ .cfi_offset 26, -48
+ .cfi_offset 27, -56
+ .cfi_offset 28, -64
+ .cfi_offset 29, -72
+ .cfi_offset 30, -80
+ .cfi_offset 31, -88
+ nop
+ move $r22, $r3
+ .cfi_def_cfa_register 22
+
+ addi.d $r5, $r5, 15
+ bstrins.d $r5, $r0, 3, 0
+ sub.d $r3, $r3, $r5
+
+ move $r3, $r22
+ .cfi_def_cfa_register 3
+ ld.d $r31, $r3, 8
+ ld.d $r30, $r3, 16
+ ld.d $r29, $r3, 24
+ ld.d $r28, $r3, 32
+ ld.d $r27, $r3, 40
+ ld.d $r26, $r3, 48
+ ld.d $r25, $r3, 56
+ ld.d $r24, $r3, 64
+ ld.d $r23, $r3, 72
+ ld.d $r22, $r3, 80
+ ld.d $r1, $r3, 88
+ .cfi_restore 31
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_restore 28
+ .cfi_restore 27
+ .cfi_restore 26
+ .cfi_restore 25
+ .cfi_restore 24
+ .cfi_restore 23
+ .cfi_restore 22
+ .cfi_restore 1
+ addi.d $r3, $r3, 96
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.d
new file mode 100644
index 00000000000..a62e56cc4a1
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.d
@@ -0,0 +1,15 @@
+#name: SFrame generation on loongarch -- FP without RA saved in register
+#as: --gsframe
+#warning: FP without RA on stack
+#objdump: --sframe=.sframe
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 0
+ Num FREs: 0
+
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.s
new file mode 100644
index 00000000000..8d304c29bbd
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-loongarch-err-1.s
@@ -0,0 +1,62 @@
+ .cfi_sections .sframe
+ .cfi_startproc
+ addi.d $r3, $r3, -96
+ .cfi_def_cfa_offset 96
+ #st.d $r1, $r3, 88
+ st.d $r22, $r3, 80
+ st.d $r23, $r3, 72
+ st.d $r24, $r3, 64
+ st.d $r25, $r3, 56
+ st.d $r26, $r3, 48
+ st.d $r27, $r3, 40
+ st.d $r28, $r3, 32
+ st.d $r29, $r3, 24
+ st.d $r30, $r3, 16
+ st.d $r31, $r3, 8
+ #.cfi_offset 1, -8
+ .cfi_offset 22, -16
+ .cfi_offset 23, -24
+ .cfi_offset 24, -32
+ .cfi_offset 25, -40
+ .cfi_offset 26, -48
+ .cfi_offset 27, -56
+ .cfi_offset 28, -64
+ .cfi_offset 29, -72
+ .cfi_offset 30, -80
+ .cfi_offset 31, -88
+ nop
+ move $r22, $r3
+ .cfi_def_cfa_register 22
+
+ addi.d $r5, $r5, 15
+ bstrins.d $r5, $r0, 3, 0
+ sub.d $r3, $r3, $r5
+
+ move $r3, $r22
+ .cfi_def_cfa_register 3
+ ld.d $r31, $r3, 8
+ ld.d $r30, $r3, 16
+ ld.d $r29, $r3, 24
+ ld.d $r28, $r3, 32
+ ld.d $r27, $r3, 40
+ ld.d $r26, $r3, 48
+ ld.d $r25, $r3, 56
+ ld.d $r24, $r3, 64
+ ld.d $r23, $r3, 72
+ ld.d $r22, $r3, 80
+ #ld.d $r1, $r3, 88
+ .cfi_restore 31
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_restore 28
+ .cfi_restore 27
+ .cfi_restore 26
+ .cfi_restore 25
+ .cfi_restore 24
+ .cfi_restore 23
+ .cfi_restore 22
+ #.cfi_restore 1
+ addi.d $r3, $r3, 96
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 9380c98fc3d..6509713974f 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -28,7 +28,7 @@ proc gas_x86_64_check { } {
# common tests
if { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]
- || [istarget "s390x-*-*"]) \
+ || [istarget "s390x-*-*"] || [istarget "loongarch64-*-*"]) \
&& [gas_sframe_check] } then {
global ASFLAGS
@@ -90,3 +90,11 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-s390x-fpra-register-1"
run_dump_test "cfi-sframe-s390x-fpra-register-2"
}
+
+# loongarch specific tests
+if { [istarget "loongarch64-*-*"] && [gas_sframe_check] } then {
+ run_dump_test "cfi-sframe-loongarch-1"
+ run_dump_test "cfi-sframe-loongarch-2"
+ run_dump_test "cfi-sframe-loongarch-3"
+ run_dump_test "cfi-sframe-loongarch-err-1"
+}
diff --git a/include/sframe.h b/include/sframe.h
index 7523adbef3a..65fc33aafe6 100644
--- a/include/sframe.h
+++ b/include/sframe.h
@@ -105,6 +105,7 @@ extern "C"
#define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 /* AARCH64 little endian. */
#define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 /* AMD64 little endian. */
#define SFRAME_ABI_S390X_ENDIAN_BIG 4 /* s390x big endian. */
+#define SFRAME_ABI_LOONGARCH_ENDIAN_LITTLE 5 /* loongarch little endian. */
/* SFrame FRE types. */
#define SFRAME_FRE_TYPE_ADDR1 0
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index a33727f2efd..984367796f2 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -240,5 +240,9 @@ if [istarget "loongarch64-*-*"] {
run_dump_test "provide_abs"
run_dump_test "provide_noabs"
+ if { ![skip_sframe_tests] } {
+ run_dump_test "sframe-simple-1"
+ }
+
}
diff --git a/ld/testsuite/ld-loongarch-elf/sframe-bar.s b/ld/testsuite/ld-loongarch-elf/sframe-bar.s
new file mode 100644
index 00000000000..739d4dd8a92
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/sframe-bar.s
@@ -0,0 +1,17 @@
+ .text
+ .globl bar
+ .type bar, @function
+bar:
+ .cfi_startproc
+ addi.d $r3, $r3, -64
+ .cfi_def_cfa_offset 64
+ st.d $r1, $r3, 56
+ .cfi_offset 1, -8
+
+ bl %plt(foo)
+
+ ld.d $r1, $r3, 56
+ .cfi_restore 1
+ addi.d $r3, $r3, 64
+ .cfi_def_cfa_offset 0
+ .cfi_endproc
diff --git a/ld/testsuite/ld-loongarch-elf/sframe-foo.s b/ld/testsuite/ld-loongarch-elf/sframe-foo.s
new file mode 100644
index 00000000000..cdc36a5bb61
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/sframe-foo.s
@@ -0,0 +1,8 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ move $a0, $zero
+ ret
+ .cfi_endproc
diff --git a/ld/testsuite/ld-loongarch-elf/sframe-simple-1.d b/ld/testsuite/ld-loongarch-elf/sframe-simple-1.d
new file mode 100644
index 00000000000..1ae73de2828
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/sframe-simple-1.d
@@ -0,0 +1,27 @@
+#as: --gsframe
+#source: sframe-foo.s
+#source: sframe-bar.s
+#objdump: --sframe=.sframe
+#ld: -shared
+#name: SFrame simple link
+
+.*: file format .*
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_SORTED,
+ SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 2
+ Num FREs: 2
+
+ Function Index :
+
+#...
+ STARTPC +CFA +FP +RA +
+ 0+[0-9a-f]+ +sp\+0 +u +u +
+
+#...
+ STARTPC +CFA +FP +RA +
+ 0+[0-9a-f]+ +sp\+0 +u +u +
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index 85500791f8a..c064b722d23 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -164,6 +164,7 @@ need_swapping (int endian)
{
case SFRAME_ABI_AARCH64_ENDIAN_LITTLE:
case SFRAME_ABI_AMD64_ENDIAN_LITTLE:
+ case SFRAME_ABI_LOONGARCH_ENDIAN_LITTLE:
return !is_little;
case SFRAME_ABI_AARCH64_ENDIAN_BIG:
case SFRAME_ABI_S390X_ENDIAN_BIG:
--
2.45.2
More information about the Binutils
mailing list