]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: sframe: handle .cfi_undefined
authorIndu Bhagat <indu.bhagat@oracle.com>
Mon, 19 May 2025 07:05:17 +0000 (00:05 -0700)
committerIndu Bhagat <indu.bhagat@oracle.com>
Mon, 19 May 2025 07:05:17 +0000 (00:05 -0700)
Fix PR gas/32952 - sframe: incorrect handling of .cfi_undefined in gas

In context of SFrame generation, it is incorrect to simply ignore all
.cfi_undefined.  We may ignore only those .cfi_undefined which are for
registers of no interest (similar to whats done for other CFI
directives).

gas/
        * gen-sframe.c (sframe_xlate_do_cfi_undefined): New definition.
        (sframe_do_cfi_insn): Handle .cfi_undefined.
gas/testsuite/
        * gas/cfi-sframe/cfi-sframe.exp: Add new tests.
        * gas/cfi-sframe/cfi-sframe-common-10.d: New test.
        * gas/cfi-sframe/cfi-sframe-common-10.s: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s: New test.

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

index aedeb3603a09eec4071859696d39ec1476c75878..a29c959db1c31bb92e255561a186b730bda3bf77 100644 (file)
@@ -1508,6 +1508,32 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
   return err;
 }
 
+/* Translate DW_CFA_undefined into SFrame context.
+
+   DW_CFA_undefined op indicates that from now on, the previous value of
+   register can’t be restored anymore.  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_undefined.
+
+   Return SFRAME_XLATE_OK if success.  */
+
+static int
+sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
+                              const struct cfi_insn_data *cfi_insn)
+{
+  if (cfi_insn->u.r == SFRAME_CFA_FP_REG
+      || cfi_insn->u.r == SFRAME_CFA_RA_REG
+      || cfi_insn->u.r == SFRAME_CFA_SP_REG)
+    {
+      as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"),
+              sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
+      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.  */
 
@@ -1611,6 +1637,8 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
        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:
       break;
     default:
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.d
new file mode 100644 (file)
index 0000000..106e05d
--- /dev/null
@@ -0,0 +1,22 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_undefined 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-10.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.s
new file mode 100644 (file)
index 0000000..7761eda
--- /dev/null
@@ -0,0 +1,12 @@
+## cfi_undefined 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_undefined 1
+       .cfi_undefined 2
+       .long 0
+       .cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d
new file mode 100644 (file)
index 0000000..43f09e0
--- /dev/null
@@ -0,0 +1,17 @@
+#as: --gsframe
+#warning: SP reg 7 in \.cfi\_undefined
+#objdump: --sframe=.sframe
+#name: DW_CFA_undefined with register SP
+#...
+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-4.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s
new file mode 100644 (file)
index 0000000..fae3bbf
--- /dev/null
@@ -0,0 +1,6 @@
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 16
+       .cfi_undefined 7
+       .long 0
+       .cfi_endproc
index b353e27ce56a94273e402526e2821acbe982c5d2..ad5602fc373971f69484b8f0525e1e08f4d2a916 100644 (file)
@@ -79,6 +79,7 @@ if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \
     run_dump_test "cfi-sframe-common-7"
     run_dump_test "cfi-sframe-common-8"
     run_dump_test "cfi-sframe-common-9"
+    run_dump_test "cfi-sframe-common-10"
 
     run_dump_test "common-empty-1"
     run_dump_test "common-empty-2"
@@ -94,6 +95,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
        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"
+       run_dump_test "cfi-sframe-x86_64-empty-4"
        set ASFLAGS "$old_ASFLAGS"
     }
 }