aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndu Bhagat <indu.bhagat@oracle.com>2025-07-17 15:17:36 -0700
committerIndu Bhagat <indu.bhagat@oracle.com>2025-07-23 00:11:47 -0700
commit83eeaf917873a550656faf9a38cd14e0f4c521b1 (patch)
treeb5cb73c9fe7d1efea926bad564a2e72ceaf6f42f
parent58fe9ce1d6c3a67e47d192ce153cc1edf2884a87 (diff)
downloadbinutils-83eeaf917873a550656faf9a38cd14e0f4c521b1.zip
binutils-83eeaf917873a550656faf9a38cd14e0f4c521b1.tar.gz
binutils-83eeaf917873a550656faf9a38cd14e0f4c521b1.tar.bz2
gas: sframe: fix PR gas/33170
SFrame generation code assumes that since DW_CFA_restore means restoration of the state of the register to the one at the beginning of the function, there must be a state to restore to (hence the gas_assert (cie_fre)). This assumption needs adjustment. DW_CFA_restore may be present in the very beginning of a (e.g., cold) function, with no initialized state for SFrame functions to restore to. gas/ PR gas/33170 * gas/gen-sframe.c (sframe_xlate_do_restore): Use current FRE if CIE FRE is not yet setup. gas/testsuite/ PR gas/33170 * gas/cfi-sframe/cfi-sframe.exp: New test. * gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d: New test. * gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s: New test.
-rw-r--r--gas/gen-sframe.c15
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d19
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s40
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe.exp1
4 files changed, 71 insertions, 4 deletions
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 806ef5f..d082b97 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1286,11 +1286,18 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
list of FREs for the specific function. */
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
+ /* PR gas/33170. It is valid to have a:
+ .cfi_restore N
+ even at the entry of a function; in which case cie_fre is not yet setup.
+ Point cie_fre to cur_fre, and let the machinery proceed to update
+ merge_candidate as usual. */
+ if (cie_fre == NULL)
+ cie_fre = cur_fre;
+
/* Change the rule for the indicated register to the rule assigned to
- it by the initial_instructions in the CIE. */
- gas_assert (cie_fre);
- /* SFrame FREs track only CFA and FP / RA for backtracing purposes;
- skip the other .cfi_restore directives. */
+ it by the initial_instructions in the CIE. SFrame FREs track only CFA
+ and FP / RA for backtracing purposes; skip the other .cfi_restore
+ directives. */
if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
{
gas_assert (cur_fre);
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d
new file mode 100644
index 0000000..85c358f
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d
@@ -0,0 +1,19 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame generation on x86_64 pr31170
+#...
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ CFA fixed RA offset: \-8
+ Num FDEs: 1
+ Num FREs: 2
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 50 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +fp\+16 +c\-16 +f +
+ 0+002d +fp\+16 +c\-16 +f +
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s
new file mode 100644
index 0000000..fa71984
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s
@@ -0,0 +1,40 @@
+# PR gas/33170
+# Ennsure graceful handling.
+ .section .text.unlikely
+ .cfi_startproc
+ .type XZ.cold, @function
+XZ.cold:
+.L1:
+ .cfi_def_cfa 6, 16
+ .cfi_offset 3, -56
+ .cfi_offset 6, -16
+ .cfi_offset 12, -48
+ .cfi_offset 13, -40
+ .cfi_offset 14, -32
+ .cfi_offset 15, -24
+.L2:
+ .cfi_restore 12
+ .cfi_restore 13
+ movl $56, %esi
+ movq %r14, %rdi
+ call _Z@PLT
+ movq %r12, -32(%rbp)
+ movq %r13, -24(%rbp)
+ movq %r14, -16(%rbp)
+ movq %r15, -8(%rbp)
+ .cfi_offset 12, -48
+ .cfi_offset 13, -40
+ .cfi_offset 14, -32
+ .cfi_offset 15, -24
+ jne .L3
+ movq %rbx, %rdi
+ call bar@PLT
+.L3:
+ movq -32(%rbp), %r12
+ .cfi_remember_state
+ .cfi_restore 12
+ jmp .L4
+.L4:
+ .cfi_restore_state
+ call _ZF@PLT
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 00a3ecc..82669cd 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -58,6 +58,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
set ASFLAGS "$ASFLAGS --64"
run_dump_test "cfi-sframe-x86_64-1"
run_dump_test "cfi-sframe-x86_64-2"
+ run_dump_test "cfi-sframe-x86_64-pr33170"
run_dump_test "cfi-sframe-x86_64-empty-1"
run_dump_test "cfi-sframe-x86_64-empty-2"
run_dump_test "cfi-sframe-x86_64-empty-3"