]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: sframe: fix PR gas/33170
authorIndu Bhagat <indu.bhagat@oracle.com>
Thu, 17 Jul 2025 22:17:36 +0000 (15:17 -0700)
committerIndu Bhagat <indu.bhagat@oracle.com>
Wed, 23 Jul 2025 07:11:47 +0000 (00:11 -0700)
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.

gas/gen-sframe.c
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp

index 806ef5f9b5be3c4292977fb420b4c648e956d240..d082b974be3f55f7984886e8c1bd7e75cf0f3cb7 100644 (file)
@@ -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 (file)
index 0000000..85c358f
--- /dev/null
@@ -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 (file)
index 0000000..fa71984
--- /dev/null
@@ -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
index 00a3ecc067ce1027721a17b9fdb88fc36f4e9a13..82669cd04751250d7f56464d345427a2dc179f8f 100644 (file)
@@ -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"