[PATCH, V3] gas: sframe: partially process DWARF unwind info in CFI_escape

Indu Bhagat indu.bhagat@oracle.com
Thu Feb 13 01:14:28 GMT 2025


CFI_escape is most commonly used to include DWARF expressions in the
unwind information.  One may also use CFI_escape to add OS-specific CFI
opcodes.  Up until now, SFrame generation process would skip generating
SFrame FDE at the mere sight of a CFI_escape opcode.

Fine tune the handling of CFI_escape for SFrame generation by explicitly
checking for few "harmless" (in context of SFrame generation)
CFI_escape DWARF info:
  - DW_CFA_expression affecting registers of no significance to SFrame
    stack trace info
  - DW_CFA_value_offset affecting registers of no significance to SFrame
    stack trace info

Expose the current cfi_escape_data structure in dw2gencfi.c to the
relevant header file to allow SFrame generation APIs to use it too.

Valid unwind info may be split across multiple .cfi_escape directives.
Conversely, it is also allowed to simply put multiple DWARF expressions
and/or operations in a single .cfi_escape directive.  Handling all of
these cases correctly will need parsing/processing that is not deemed
worth the effort in context of SFrame generation; We continue to skip
generating SFrame FDE for these cases and warn the user.

In future, SFrame stack trace may support non-SP/FP as base register
(albeit in limited form).  Add an explicit check in
sframe_xlate_do_escape_expr (to test against the current CFA register)
to ensure the functionality continues to work.

Use differentiated warning text in sframe_xlate_do_val_offset to avoid
confusion to the user as the same function is used for handling
.cfi_val_offset and .cfi_escape DW_CFA_val_offset,...

Also, add a common test with DWARF reg 12 which is non SP / FP on x86_64
and aarch64 (and s390x too).

gas/
	* gas/dw2gencfi.c (struct cfi_escape_data): Move from ...
	* gas/dw2gencfi.h (struct cfi_escape_data): ... to.
	* gas/gen-sframe.c (sframe_xlate_do_val_offset): Include string
	for .cfi_escape conditionally.
	(sframe_xlate_do_escape_expr): New definition.
	(sframe_xlate_do_escape_val_offset): Likewise.
	(sframe_xlate_do_cfi_escape): Likewise.
	(sframe_do_cfi_insn): Handle CFI_escape explicitly.

gas/testsuite/
	* gas/cfi-sframe/cfi-sframe.exp: Add new tests.
	* gas/cfi-sframe/cfi-sframe-common-9.d: New test.
	* gas/cfi-sframe/cfi-sframe-common-9.s: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-1.s: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-2.s: New test.

---

[Changes in V3]
 - Scaling of offset before invoking sframe_xlate_do_val_offset.
 - Adjust the commit log.
 - Squash the two commits in V2 into a single commit and adjust the
   warning text.
 - Use stack for temp cfi_insn. Use initialized init style.
 - Addressed other review comments.
 - Adjust code comments to reflect that not reading bytes as ULEB data
   is acceptable, given the other checks in place.  Other code comment
   adjustments reflecting the discussion during review.
 - Consistently check for X_op as O_constant where necessary.
 - Adjust code comments in the testcase.
[End of changes in V3]

[Changes in V2]
 - Use pointer-to-const when applicable for local vars.
 - Early exit if there is no cfi_escape expression.
 - Restructure functionality to accommodate the fact that a valid
   unwind info may be split across multiple .cfi_escape. If this is the
   case, the current implementation bails out.  Handling this case does
   not appear to be worth the effort.
 - Include checking with SFRAME_CFA_RA_REG because we need to detect the
   cases when .cfi_escape can affect RA.
 - Use if conditional instead of assert block.
[End of changes in V2]
---
 gas/dw2gencfi.c                               |   6 -
 gas/dw2gencfi.h                               |   6 +
 gas/gen-sframe.c                              | 207 +++++++++++++++++-
 .../gas/cfi-sframe/cfi-sframe-common-9.d      |  22 ++
 .../gas/cfi-sframe/cfi-sframe-common-9.s      |  18 ++
 .../cfi-sframe/cfi-sframe-x86_64-empty-1.d    |  17 ++
 .../cfi-sframe/cfi-sframe-x86_64-empty-1.s    |  11 +
 .../cfi-sframe/cfi-sframe-x86_64-empty-2.d    |  17 ++
 .../cfi-sframe/cfi-sframe-x86_64-empty-2.s    |  11 +
 gas/testsuite/gas/cfi-sframe/cfi-sframe.exp   |   3 +
 10 files changed, 305 insertions(+), 13 deletions(-)
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.d
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.s
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.s
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.s

diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 012af0ff33e..41e15cd1463 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -368,12 +368,6 @@ generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 }
 #endif
 
-struct cfi_escape_data
-{
-  struct cfi_escape_data *next;
-  expressionS exp;
-};
-
 struct cie_entry
 {
   struct cie_entry *next;
diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h
index 42eb3863a0a..9b0e5979c0d 100644
--- a/gas/dw2gencfi.h
+++ b/gas/dw2gencfi.h
@@ -93,6 +93,12 @@ extern void cfi_add_CFA_restore_state (void);
 #define MULTIPLE_FRAME_SECTIONS (SUPPORT_FRAME_LINKONCE || SUPPORT_COMPACT_EH \
 				 || TARGET_MULTIPLE_EH_FRAME_SECTIONS)
 
+struct cfi_escape_data
+{
+  struct cfi_escape_data *next;
+  expressionS exp;
+};
+
 struct cfi_insn_data
 {
   struct cfi_insn_data *next;
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 13478efab6b..52a707e82ca 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1117,11 +1117,15 @@ sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
 }
 
 /* Translate DW_CFA_val_offset into SFrame context.
-   Return SFRAME_XLATE_OK if success.  */
+   Return SFRAME_XLATE_OK if success.
+
+   When cfi_esc_p is true, the cfi_insn argument is hand-crafted using
+   CFI_escape data.  See sframe_xlate_do_escape_val_offset.  */
 
 static int
-sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
-			    struct cfi_insn_data *cfi_insn)
+sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
+			    const struct cfi_insn_data *cfi_insn,
+			    bool cfi_esc_p)
 {
   /* Previous value of register is CFA + offset.  However, if the specified
      register is not interesting (SP, FP, or RA reg), the current
@@ -1134,7 +1138,8 @@ sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
       /* Ignore SP reg, if offset matches assumed default rule.  */
       || (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG && cfi_insn->u.ri.offset != 0))
     {
-      as_warn (_("skipping SFrame FDE; %s register %u in .cfi_val_offset"),
+      as_warn (_("skipping SFrame FDE; %s with %s reg %u"),
+	       cfi_esc_p ? ".cfi_escape DW_CFA_val_offset" : ".cfi_val_offset",
 	       sframe_register_name (cfi_insn->u.ri.reg), cfi_insn->u.ri.reg);
       return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
     }
@@ -1310,6 +1315,192 @@ sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx,
   return SFRAME_XLATE_ERR_NOTREPRESENTED;  /* Not represented.  */
 }
 
+/* Handle DW_CFA_expression in .cfi_escape.
+
+   As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
+   only the simple-to-process but common cases, where skipping over the escape
+   expr data does not affect correctness of the SFrame stack trace data.  */
+
+static int
+sframe_xlate_do_escape_expr (const struct sframe_xlate_ctx *xlate_ctx,
+			     const struct cfi_insn_data *cfi_insn)
+{
+  const struct cfi_escape_data *e = cfi_insn->u.esc;
+  const struct sframe_row_entry *cur_fre = NULL;
+  int err = SFRAME_XLATE_OK;
+  unsigned int reg = 0;
+  unsigned int i = 0;
+
+  /* Check roughly for an expression
+     DW_CFA_expression: r1 (rdx) (DW_OP_bregN (reg): XXX).  */
+#define CFI_ESC_NUM_EXP 4
+  offsetT items[CFI_ESC_NUM_EXP] = {0};
+  while (e->next)
+    {
+      e = e->next;
+      if ((i == 2 && items[1] == 0) /* Zero length in DWARF expr.  */
+	  || i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant)
+	return SFRAME_XLATE_ERR_NOTREPRESENTED;
+      items[i] = e->exp.X_add_number;
+      i++;
+    }
+
+  if (i <= CFI_ESC_NUM_EXP - 1)
+    return SFRAME_XLATE_ERR_NOTREPRESENTED;
+
+  cur_fre = xlate_ctx->cur_fre;
+  /* reg operand to DW_CFA_expression is ULEB128.  For the purpose at hand,
+     however, the register value will be less than 127 (CFI_ESC_NUM_EXP set
+     to 4).  */
+  reg = items[0];
+#undef CFI_ESC_NUM_EXP
+
+  if (reg == SFRAME_CFA_SP_REG || reg == SFRAME_CFA_FP_REG
+#ifdef SFRAME_FRE_RA_TRACKING
+      || (sframe_ra_tracking_p () && reg == SFRAME_CFA_RA_REG)
+#endif
+      || reg == cur_fre->cfa_base_reg)
+    {
+      as_warn (_("skipping SFrame FDE; "
+		 ".cfi_escape DW_CFA_expression with %s reg %u"),
+	       sframe_register_name (reg), reg);
+      err = SFRAME_XLATE_ERR_NOTREPRESENTED;
+    }
+
+  return err;
+}
+
+/* Handle DW_CFA_val_offset in .cfi_escape.
+
+   As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
+   only the simple-to-process but common cases, where skipping over the escape
+   expr data does not affect correctness of the SFrame stack trace data.  */
+
+static int
+sframe_xlate_do_escape_val_offset (const struct sframe_xlate_ctx *xlate_ctx,
+				   const struct cfi_insn_data *cfi_insn)
+{
+  const struct cfi_escape_data *e = cfi_insn->u.esc;
+  int err = SFRAME_XLATE_OK;
+  unsigned int i = 0;
+  unsigned int reg;
+  offsetT offset;
+
+  /* Check for (DW_CFA_val_offset reg scaled_offset) sequence.  */
+#define CFI_ESC_NUM_EXP 2
+  offsetT items[CFI_ESC_NUM_EXP] = {0};
+  while (e->next)
+    {
+      e = e->next;
+      if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant)
+	return SFRAME_XLATE_ERR_NOTREPRESENTED;
+      items[i] = e->exp.X_add_number;
+      i++;
+    }
+  if (i <= CFI_ESC_NUM_EXP - 1)
+    return SFRAME_XLATE_ERR_NOTREPRESENTED;
+
+  /* Both arguments to DW_CFA_val_offset are ULEB128.  Especially with APX (on
+     x86) we're going to see DWARF register numbers above 127, for the extended
+     GPRs.  And large enough stack frames would also require multi-byte offset
+     representation.  However, since we limit our focus on cases when
+     CFI_ESC_NUM_EXP is 2, reading UELB can be skipped.  IOW, although not
+     ideal, SFrame FDE generation in case of an APX register in
+     DW_CFA_val_offset is being skipped (PS: this does _not_ mean incorrect
+     SFrame stack trace data).
+
+     Recall that the intent here is to check for simple and prevalent cases,
+     when feasible.  */
+
+  reg = items[0];
+  offset = items[1];
+#undef CFI_ESC_NUM_EXP
+
+  /* Invoke sframe_xlate_do_val_offset itself for checking.  */
+  struct cfi_insn_data temp = { .insn = DW_CFA_val_offset };
+  temp.u.ri.reg = reg;
+  temp.u.ri.offset = offset * DWARF2_CIE_DATA_ALIGNMENT;
+  err = sframe_xlate_do_val_offset (xlate_ctx, &temp, true);
+
+  return err;
+}
+
+/* Handle CFI_escape in SFrame context.
+
+   .cfi_escape CFI directive allows the user to add arbitrary bytes to the
+   unwind info.  DWARF expressions commonly follow after CFI_escape (fake CFI)
+   DWARF opcode.  One might also use CFI_escape to add OS-specific CFI opcodes
+   even.
+
+   Complex unwind info added using .cfi_escape directive _may_ be of no
+   consequence for SFrame when the affected registers are not SP, FP, RA or
+   CFA.  The challenge in confirming the afore-mentioned is that it needs full
+   parsing (and validation) of the bytes presented after .cfi_escape.  Here we
+   take a case-by-case approach towards skipping _some_ instances of
+   .cfi_escape: skip those that can be *easily* determined to be harmless in
+   the context of SFrame stack trace information.
+
+   This function partially processes bytes following .cfi_escape and returns
+   SFRAME_XLATE_OK if OK to skip.  */
+
+static int
+sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
+			    const struct cfi_insn_data *cfi_insn)
+{
+  const struct cfi_escape_data *e;
+  int err = SFRAME_XLATE_OK;
+  offsetT firstop;
+
+  e = cfi_insn->u.esc;
+
+  if (!e)
+    return SFRAME_XLATE_ERR_INVAL;
+
+  if (e->exp.X_op != O_constant)
+    return SFRAME_XLATE_ERR_NOTREPRESENTED;
+
+  firstop = e->exp.X_add_number;
+  switch (firstop)
+    {
+    case DW_CFA_nop:
+      /* One or more nops together are harmless for SFrame.  */
+      while (e->next)
+	{
+	  e = e->next;
+	  if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop)
+	    {
+	      err = SFRAME_XLATE_ERR_NOTREPRESENTED;
+	      break;
+	    }
+	}
+      break;
+
+    case DW_CFA_expression:
+      return sframe_xlate_do_escape_expr (xlate_ctx, cfi_insn);
+
+    case DW_CFA_val_offset:
+      return sframe_xlate_do_escape_val_offset (xlate_ctx, cfi_insn);
+
+    /* FIXME - Also add processing for DW_CFA_GNU_args_size in future?  */
+
+    default:
+      err = SFRAME_XLATE_ERR_NOTREPRESENTED;
+      break;
+    }
+
+  if (err == SFRAME_XLATE_ERR_NOTREPRESENTED)
+    {
+      /* In all other cases (e.g., DW_CFA_def_cfa_expression or other
+	 OS-specific CFI opcodes), skip inspecting the DWARF expression.
+	 This may impact the asynchronicity due to loss of coverage.
+	 Continue to warn the user and bail out.  */
+      as_warn (_("skipping SFrame FDE; .cfi_escape with op (%#lx)"),
+	       (unsigned long)firstop);
+    }
+
+  return err;
+}
+
 /* Returns the DWARF call frame instruction name or fake CFI name for the
    specified CFI opcode, or NULL if the value is not recognized.  */
 
@@ -1384,7 +1575,7 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
       err = sframe_xlate_do_offset (xlate_ctx, cfi_insn);
       break;
     case DW_CFA_val_offset:
-      err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn);
+      err = sframe_xlate_do_val_offset (xlate_ctx, cfi_insn, false);
       break;
     case DW_CFA_remember_state:
       err = sframe_xlate_do_remember_state (xlate_ctx);
@@ -1406,6 +1597,9 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
     case DW_CFA_register:
       err = sframe_xlate_do_register (xlate_ctx, cfi_insn);
       break;
+    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.  */
@@ -1413,8 +1607,7 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
     case DW_CFA_same_value:
       break;
     default:
-      /* Following skipped operations do, however, impact the asynchronicity:
-	  - CFI_escape.  */
+      /* Other skipped operations may, however, impact the asynchronicity.  */
       {
 	const char *cfi_name = sframe_get_cfi_name (op);
 
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.d
new file mode 100644
index 00000000000..80c92357073
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.d
@@ -0,0 +1,22 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_escape 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-9.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.s
new file mode 100644
index 00000000000..d0cb71e2e9a
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-9.s
@@ -0,0 +1,18 @@
+## CFI_escape may be used to encode DWARF expressions among other things.
+## Depending on the register applicable for the DWARF expression, skipping
+## SFrame FDE may be OK: SFrame stack trace information is relevant for SP, FP
+## and RA only.  In this test, CFI_escape is safe to skip (does not affect
+## correctness of SFrame data).  The register 0xc is non SP / FP on both
+## aarch64 and x86_64.
+	.cfi_startproc
+	.long 0
+	.cfi_def_cfa_offset 16
+# DW_CFA_expression,reg 0xc,length 2,DW_OP_breg6,SLEB(-8)
+	.cfi_escape 0x10,0xc,0x2,0x76,0x78
+# DW_CFA_nop
+	.cfi_escape 0x0
+	.cfi_escape 0x0,0x0,0x0,0x0
+# DW_CFA_val_offset,reg 0xc,ULEB scaled offset(32)
+	.cfi_escape 0x14,0xc,0x4
+	.long 0
+	.cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d
new file mode 100644
index 00000000000..01239944863
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d
@@ -0,0 +1,17 @@
+#as: --gsframe
+#warning: skipping SFrame FDE; \.cfi_escape DW\_CFA\_expression with SP reg 7
+#objdump: --sframe=.sframe
+#name: CFI_escape with register of significance to SFrame
+#...
+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-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.s
new file mode 100644
index 00000000000..cfb1a95d7c5
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-1.s
@@ -0,0 +1,11 @@
+## CFI_escape may be used to encode DWARF expressions among other things.
+## In this test, a DWARF expression involving a register of interest (REG_SP on
+## x86_64, which is also the CFA in the current FRE) is seen.  SFrame
+## generation, is skipped and a warning issued to the user.
+	.cfi_startproc
+	.long 0
+	.cfi_def_cfa_offset 16
+# DW_CFA_expression,reg 0x7,length 2,DW_OP_breg6,SLEB(-8)
+	.cfi_escape 0x10,0x7,0x2,0x76,0x78
+	.long 0
+	.cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d
new file mode 100644
index 00000000000..482803b65a2
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d
@@ -0,0 +1,17 @@
+#as: --gsframe
+#warning: skipping SFrame FDE; \.cfi\_escape DW\_CFA\_val\_offset with FP reg 6
+#objdump: --sframe=.sframe
+#name: CFI_escape with register of significance to SFrame II
+#...
+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-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.s
new file mode 100644
index 00000000000..90e108e96ad
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-2.s
@@ -0,0 +1,11 @@
+## CFI_escape may be used to encode DWARF expressions among other things.
+## In this test, a DWARF expression involving a register of interest (REG_SP on
+## x86_64, which is also the CFA in the current FRE) is seen.  SFrame
+## generation, is skipped and a warning issued to the user.
+	.cfi_startproc
+	.long 0
+	.cfi_def_cfa_offset 16
+# DW_CFA_val_offset,rbp,ULEB scaled offset(16)
+	.cfi_escape 0x14,0x6,0x2
+	.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 b119b9da73d..fdf7d9518cb 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -78,6 +78,7 @@ if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \
     run_dump_test "cfi-sframe-common-6"
     run_dump_test "cfi-sframe-common-7"
     run_dump_test "cfi-sframe-common-8"
+    run_dump_test "cfi-sframe-common-9"
 
     run_dump_test "common-empty-1"
     run_dump_test "common-empty-2"
@@ -89,6 +90,8 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
     if { [gas_x86_64_check] } then {
 	set ASFLAGS "$ASFLAGS --64"
 	run_dump_test "cfi-sframe-x86_64-1"
+	run_dump_test "cfi-sframe-x86_64-empty-1"
+	run_dump_test "cfi-sframe-x86_64-empty-2"
 	set ASFLAGS "$old_ASFLAGS"
     }
 }
-- 
2.43.0



More information about the Binutils mailing list