[RFC 21/28] [SFrame-V3] gas: sframe: add handling for .cfi_register for FP and RA
Indu Bhagat
indu.bhagat@oracle.com
Tue Dec 9 09:07:46 GMT 2025
More information about the Binutils mailing list
Tue Dec 9 09:07:46 GMT 2025
- Previous message (by thread): [RFC 20/28] [SFrame-V3] gas: x86: testsuite: add new testcases for SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
- Next message (by thread): [RFC 21/28] [SFrame-V3] gas: sframe: add handling for .cfi_register for FP and RA
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Use SFrame FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
When FP, RA were moved to a general-purpose register, the SFrame
generation previously warned and skipped the FDE (except on S390X). This
patch updates the translator to detect`.cfi_register` for RA (and FP) on
AMD64, tracks the destination register in the SFrame row entry, and
emits the register in the relevant FRE offsets in SFrame FDE type
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
gas/
* gen-sframe.c (output_sframe_row_entry_offsets): Emit register
encoding for RA if tracked.
(sframe_row_entry_initialize): Propagate ra_reg and ra_deref_p.
(sframe_xlate_do_register): Handle .cfi_register for RA/FP on
AMD64 by setting flex_topmost_p and recording the register.
* gen-sframe.h (struct sframe_row_entry): Add ra_reg and
ra_deref_p.
testsuite/gas/
* cfi-sframe/cfi-sframe.exp: Run new test.
* cfi-sframe/cfi-sframe-x86_64-6.d: New test.
* cfi-sframe/cfi-sframe-x86_64-6.s: New test.
---
gas/gen-sframe.c | 72 +++++++++++++++----
gas/gen-sframe.h | 4 ++
.../gas/cfi-sframe/cfi-sframe-x86_64-6.d | 21 ++++++
.../gas/cfi-sframe/cfi-sframe-x86_64-6.s | 13 ++++
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 1 +
5 files changed, 96 insertions(+), 15 deletions(-)
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.s
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 11cc828dbde..89675379d51 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -644,13 +644,25 @@ output_sframe_row_entry_offsets (const struct sframe_func_entry *sframe_fde,
/* RA tracking enabled or not, emit two offsets for RA.
Aside, emitting SFRAME_FRE_RA_OFFSET_INVALID is equivalent to emitting
- SFRAME_V3_FLEX_FDE_REG_ENCODE (0, 0, 0).
- FIXME - This may change later when we implement handling .cfi_register
- RA, reg. Emit two 0 offsets for now. */
- fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
- /* FIXME Offset 0 for now. */
- fre_offset_func_map[idx].out_func (0);
- fre_write_offsets += 2;
+ SFRAME_V3_FLEX_FDE_REG_ENCODE (0, 0, 0). */
+ if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
+ {
+ /* Output RA related FRE offsets. */
+ reg_data = SFRAME_V3_FLEX_FDE_REG_ENCODE (sframe_fre->ra_reg,
+ sframe_fre->ra_deref_p,
+ 1 /* reg_p. */);
+ offset_data = sframe_fre->ra_offset;
+ fre_offset_func_map[idx].out_func (reg_data);
+ fre_offset_func_map[idx].out_func (offset_data);
+ fre_write_offsets += 2;
+ }
+ else
+ {
+ fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
+ /* FIXME Offset 0 for now. */
+ fre_offset_func_map[idx].out_func (0);
+ fre_write_offsets += 2;
+ }
if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
{
@@ -1116,7 +1128,9 @@ sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
cur_fre->fp_offset = prev_fre->fp_offset;
cur_fre->fp_deref_p = prev_fre->fp_deref_p;
cur_fre->ra_loc = prev_fre->ra_loc;
+ cur_fre->ra_reg = prev_fre->ra_reg;
cur_fre->ra_offset = prev_fre->ra_offset;
+ cur_fre->ra_deref_p = prev_fre->ra_deref_p;
/* Treat RA mangling as a sticky bit. It retains its value until another
.cfi_negate_ra_state is seen. */
cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
@@ -1440,6 +1454,18 @@ s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
}
/* Translate DW_CFA_register into SFrame context.
+
+ This opcode indicates: Previous value of register1 is register2. This is
+ not representable in SFrame stack trace format. Detect the use of registers
+ interesting to SFrame (FP, RA for this opcode), and skip FDE generation
+ while warning the user.
+
+ Two exceptions apply though:
+ - for S390X, the stack offsets are used to carry register number in
+ default FDE types. So invoke S390X specific handling.
+ - for AMD64, the flexible topmost frame encoding
+ SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME can be used for FP, RA registers.
+
Return SFRAME_XLATE_OK if success. */
static int
@@ -1449,15 +1475,31 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
/* Conditionally invoke S390-specific implementation. */
if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
+ else if (sframe_get_abi_arch () == SFRAME_ABI_AMD64_ENDIAN_LITTLE)
+ {
+ struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
- /* Previous value of register1 is register2. However, if the specified
- register1 is not interesting (FP or RA reg), the current DW_CFA_register
- instruction can be safely skipped without sacrificing the asynchronicity of
- stack trace information. */
- if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG
- || cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
- /* Ignore SP reg, as it can be recovered from the CFA tracking info. */
- )
+ if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
+ {
+ sframe_fre_set_fp_track (cur_fre, 0);
+ cur_fre->fp_reg = cfi_insn->u.rr.reg2;
+ cur_fre->fp_deref_p = false;
+ cur_fre->merge_candidate = false;
+ xlate_ctx->flex_topmost_p = true;
+ }
+ else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
+ {
+ sframe_fre_set_ra_track (cur_fre, 0);
+ cur_fre->ra_reg = cfi_insn->u.rr.reg2;
+ cur_fre->ra_deref_p = false;
+ cur_fre->merge_candidate = false;
+ xlate_ctx->flex_topmost_p = true;
+ }
+ }
+ else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
+ /* Ignore SP reg, as it can be recovered from the CFA tracking
+ info. */
+ || cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
{
as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
diff --git a/gas/gen-sframe.h b/gas/gen-sframe.h
index 4921e796a10..6c0699dec46 100644
--- a/gas/gen-sframe.h
+++ b/gas/gen-sframe.h
@@ -87,9 +87,13 @@ struct sframe_row_entry
bool fp_deref_p;
/* Track RA location. Specify whether it is in register or memory. */
+ unsigned int ra_reg;
unsigned int ra_loc;
/* If RA is stashed on stack, note the offset. */
offsetT ra_offset;
+ /* Whether RA recovery needs dereferencing. This is tracked for
+ SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME SFrame FDE type. */
+ bool ra_deref_p;
};
/* SFrame Function Description Entry. */
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.d
new file mode 100644
index 00000000000..1906a0b5630
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.d
@@ -0,0 +1,21 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: DW_CFA_register RA in flex FDE type
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_3
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ CFA fixed RA offset: -8
+ Num FDEs: 1
+ Num FREs: 3
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 7 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+8 +u +f +
+ 0+0004 +sp\+40 +u +f +
+ 0+0005 +sp\+0 +u +r2\+0 +
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.s
new file mode 100644
index 00000000000..69a3efb7e85
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-6.s
@@ -0,0 +1,13 @@
+ .p2align 4
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ sub $0x20,%rsp
+ .cfi_adjust_cfa_offset 0x20
+ popq %rcx
+ .cfi_register 16, 2
+ .cfi_def_cfa_offset 0
+ jmp *%rcx
+ .cfi_endproc
+ .size foo, .-foo
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 489b3ff003f..d7a2afbaf3d 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -64,6 +64,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-x86_64-3"
run_dump_test "cfi-sframe-x86_64-4"
run_dump_test "cfi-sframe-x86_64-5"
+ run_dump_test "cfi-sframe-x86_64-6"
run_dump_test "cfi-sframe-x86_64-pr33170"
run_dump_test "cfi-sframe-x86_64-signal-1"
run_dump_test "cfi-sframe-x86_64-empty-1"
--
2.43.0
- Previous message (by thread): [RFC 20/28] [SFrame-V3] gas: x86: testsuite: add new testcases for SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
- Next message (by thread): [RFC 21/28] [SFrame-V3] gas: sframe: add handling for .cfi_register for FP and RA
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list