[PATCH 4/4] gas: sframe: handle .cfi_same_value
Indu Bhagat
indu.bhagat@oracle.com
Sun May 11 07:35:38 GMT 2025
Fix PR gas/32953 - sframe: incorrect handling of .cfi_same_value in gas
As per documentation, .cfi_same_value indicates that: Current value of
register is the same like in the previous frame, i.e. no restoration
needed. SFrame has no means to encode this information.
Skip generating FDE, but warn if it is for a register of interest.
gas/
* gen-sframe.c (sframe_xlate_do_same_value): New definition.
(sframe_do_cfi_insn): Handle DW_CFA_same_value.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: Add new tests.
* gas/cfi-sframe/cfi-sframe-common-11.d: New test.
* gas/cfi-sframe/cfi-sframe-common-11.s: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s: New test.
---
gas/gen-sframe.c | 30 +++++++++++++++++--
.../gas/cfi-sframe/cfi-sframe-common-11.d | 22 ++++++++++++++
.../gas/cfi-sframe/cfi-sframe-common-11.s | 12 ++++++++
.../cfi-sframe/cfi-sframe-x86_64-empty-5.d | 17 +++++++++++
.../cfi-sframe/cfi-sframe-x86_64-empty-5.s | 6 ++++
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 2 ++
6 files changed, 86 insertions(+), 3 deletions(-)
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.s
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index a87d464fd5f..f989627193f 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1533,6 +1533,32 @@ sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUT
return SFRAME_XLATE_OK;
}
+/* Translate DW_CFA_same_value into SFrame context.
+
+ DW_CFA_undefined op implies that current value of register is the same like
+ in the previous frame, i.e. no restoration needed. In SFrame stack trace,
+ we cannot represent such a semantic. So, we skip generating an SFrame FDE
+ for this, when a register of interest is used with DW_CFA_same_value.
+
+ Return SFRAME_XLATE_OK if success. */
+
+static int
+sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
+ const struct cfi_insn_data *cfi_insn)
+{
+ if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG
+ || (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
+ || cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG)
+ {
+ as_warn (_("skipping SFrame FDE; %s reg %u in .cfi_same_value"),
+ sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
+ return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
+ }
+
+ /* Safe to skip. */
+ return SFRAME_XLATE_OK;
+}
+
/* Returns the DWARF call frame instruction name or fake CFI name for the
specified CFI opcode, or NULL if the value is not recognized. */
@@ -1632,13 +1658,11 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
case CFI_escape:
err = sframe_xlate_do_cfi_escape (xlate_ctx, cfi_insn);
break;
- /* Following CFI opcodes are not processed at this time.
- These do not impact the coverage of the basic stack tracing
- information as conveyed in the SFrame format. */
case DW_CFA_undefined:
err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn);
break;
case DW_CFA_same_value:
+ err = sframe_xlate_do_same_value (xlate_ctx, cfi_insn);
break;
default:
/* Other skipped operations may, however, impact the asynchronicity. */
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.d
new file mode 100644
index 00000000000..25848150135
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.d
@@ -0,0 +1,22 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_same_value test
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: NONE
+#? CFA fixed FP offset: \-?\d+
+#? CFA fixed RA offset: \-?\d+
+ Num FDEs: 1
+ Num FREs: 2
+
+ Function Index :
+ func idx \[0\]: pc = 0x0, size = 8 bytes
+ STARTPC + CFA + FP + RA +
+#...
+ 0+0004 +sp\+16 +u +[uf] +
+
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.s
new file mode 100644
index 00000000000..e299f586cf2
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-11.s
@@ -0,0 +1,12 @@
+## cfi_same_value when used with "not interesting" registers (from the
+## perspective of SFrame section, non SP/FP/RA registers are not
+## interesting) does not affect the asynchronicity of the SFrame stack
+## trace information. Such CFI directives can be skipped for SFrame
+## stack trace info generation.
+ .cfi_startproc
+ .long 0
+ .cfi_def_cfa_offset 16
+ .cfi_same_value 1
+ .cfi_same_value 2
+ .long 0
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d
new file mode 100644
index 00000000000..24d944a8757
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d
@@ -0,0 +1,17 @@
+#as: --gsframe
+#warning: skipping SFrame FDE; FP reg 6 in \.cfi\_same\_value
+#objdump: --sframe=.sframe
+#name: CFI_escape with multiple DWARF expr
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: NONE
+#? CFA fixed FP offset: \-?\d+
+#? CFA fixed RA offset: \-?\d+
+ Num FDEs: 0
+ Num FREs: 0
+
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s
new file mode 100644
index 00000000000..89b13b2028c
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s
@@ -0,0 +1,6 @@
+ .cfi_startproc
+ .long 0
+ .cfi_def_cfa_offset 16
+ .cfi_same_value 0x6
+ .long 0
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index ad5602fc373..8ca22d3c652 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -80,6 +80,7 @@ if { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \
run_dump_test "cfi-sframe-common-8"
run_dump_test "cfi-sframe-common-9"
run_dump_test "cfi-sframe-common-10"
+ run_dump_test "cfi-sframe-common-11"
run_dump_test "common-empty-1"
run_dump_test "common-empty-2"
@@ -96,6 +97,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-x86_64-empty-2"
run_dump_test "cfi-sframe-x86_64-empty-3"
run_dump_test "cfi-sframe-x86_64-empty-4"
+ run_dump_test "cfi-sframe-x86_64-empty-5"
set ASFLAGS "$old_ASFLAGS"
}
}
--
2.43.0
More information about the Binutils
mailing list