public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Indu Bhagat <indu.bhagat@oracle.com>
To: binutils@sourceware.org
Cc: Indu Bhagat <indu.bhagat@oracle.com>
Subject: [PATCH 2/2] gas: scfi: bugfixes for SCFI state propagation
Date: Thu, 28 Mar 2024 16:43:43 -0700	[thread overview]
Message-ID: <20240328234343.3397845-3-indu.bhagat@oracle.com> (raw)
In-Reply-To: <20240328234343.3397845-1-indu.bhagat@oracle.com>

There are two state propagation functions in SCFI machinery - forward
and backward flow.  The patch addresses two issues:
  - In forward_flow_scfi_state (), the state being compared in forward flow
    must be that at the exit of a prev bb and that at the entry of the
    next bb.  The variable holding the state to be compared was
    previously (erroneously) stale.
  - In cmp_scfi_state (), the assumption that two different control
    flows, leading to the same basic block, cannot have a mismatched
    notion of CFA base register, is not true.  Remove the assertion and
    instead return err if mismatch.

Fixing these issues helps correctly synthesize CFI, when previously
SCFI was erroring out for an otherwise valid input asm.

gas/
	* scfi.c (cmp_scfi_state): Remove assertion and return mismatch
	in return value as applicable.
	(forward_flow_scfi_state): Update state object to be the same as
	the exit state of the prev bb before comparing.
gas/testsuite/
	* gas/scfi/x86_64/scfi-x86-64.exp: Add new test.
	* gas/scfi/x86_64/scfi-cfg-5.d: New test.
	* gas/scfi/x86_64/scfi-cfg-5.l: New test.
	* gas/scfi/x86_64/scfi-cfg-5.s: New test.
---
 gas/scfi.c                                    | 20 ++++++----
 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.d    | 39 +++++++++++++++++++
 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.l    |  2 +
 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.s    | 32 +++++++++++++++
 gas/testsuite/gas/scfi/x86_64/scfi-x86-64.exp |  2 +
 5 files changed, 87 insertions(+), 8 deletions(-)
 create mode 100644 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.d
 create mode 100644 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.l
 create mode 100644 gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.s

diff --git a/gas/scfi.c b/gas/scfi.c
index 37cc85cfed7..929ea8a73e1 100644
--- a/gas/scfi.c
+++ b/gas/scfi.c
@@ -155,7 +155,7 @@ cmp_scfi_state (scfi_stateS *state1, scfi_stateS *state2)
   int ret;
 
   if (!state1 || !state2)
-    ret = 1;
+    return 1;
 
   /* Skip comparing the scratch[] value of registers.  The user visible
      unwind information is derived from the regs[] from the SCFI state.  */
@@ -164,10 +164,12 @@ cmp_scfi_state (scfi_stateS *state1, scfi_stateS *state2)
 
   /* For user functions which perform dynamic stack allocation, after switching
      t REG_FP based CFA tracking, it is perfectly possible to have stack usage
-     in some control flows.  However, double-checking that all control flows
-     have the same idea of CFA tracking before this wont hurt.  */
-  gas_assert (state1->regs[REG_CFA].base == state2->regs[REG_CFA].base);
-  if (state1->regs[REG_CFA].base == REG_SP)
+     in some control flows.  Further, the different control flows may even not
+     have the same idea of CFA tracking (likely later necessitating generation
+     of .cfi_remember_state / .cfi_restore_state pair).  */
+  ret |= state1->regs[REG_CFA].base != state2->regs[REG_CFA].base;
+
+  if (!ret && state1->regs[REG_CFA].base == REG_SP)
     ret |= state1->stack_size != state2->stack_size;
 
   ret |= state1->traceable_p != state2->traceable_p;
@@ -911,11 +913,11 @@ gen_scfi_ops (ginsnS *ginsn, scfi_stateS *state)
   return ret;
 }
 
-/* Recursively perform forward flow of the (unwind information) SCFI state
+/* Recursively perform forward flow of the (unwind information) SCFI STATE
    starting at basic block GBB.
 
-   The forward flow process propagates the SCFI state at exit of a basic block
-   to the successor basic block.
+   The core of forward flow process takes the SCFI state at the entry of a bb
+   and updates it incrementally as per the semantics of each ginsn in the bb.
 
    Returns error code, if any.  */
 
@@ -961,6 +963,8 @@ forward_flow_scfi_state (gcfgS *gcfg, gbbS *gbb, scfi_stateS *state)
       bb_for_each_edge(gbb, gedge)
 	{
 	  gbb = gedge->dst_bb;
+	  /* Ensure that the state is the one from the exit of the prev bb.  */
+	  memcpy (state, prev_bb->exit_state, sizeof (scfi_stateS));
 	  if (gbb->visited)
 	    {
 	      ret = cmp_scfi_state (gbb->entry_state, state);
diff --git a/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.d b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.d
new file mode 100644
index 00000000000..5a0a2e1f927
--- /dev/null
+++ b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.d
@@ -0,0 +1,39 @@
+#as: --scfi=experimental -W
+#as:
+#objdump: -Wf
+#name: Synthesize CFI in presence of control flow 5
+#...
+Contents of the .eh_frame section:
+
+00000000 0+0014 0+0000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: -8
+  Return address column: 16
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+  DW_CFA_offset: r16 \(rip\) at cfa-8
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+0018 0+002c 0000001c FDE cie=00000000 pc=0+0000..0+0017
+  DW_CFA_advance_loc: 1 to 0+0001
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_offset: r6 \(rbp\) at cfa-16
+  DW_CFA_advance_loc: 3 to 0+0004
+  DW_CFA_def_cfa_register: r6 \(rbp\)
+  DW_CFA_advance_loc: 5 to 0+0009
+  DW_CFA_remember_state
+  DW_CFA_advance_loc: 6 to 0+000f
+  DW_CFA_def_cfa_register: r7 \(rsp\)
+  DW_CFA_restore: r6 \(rbp\)
+  DW_CFA_def_cfa_offset: 8
+  DW_CFA_advance_loc: 1 to 0+0010
+  DW_CFA_restore_state
+  DW_CFA_advance_loc: 6 to 0+0016
+  DW_CFA_def_cfa_register: r7 \(rsp\)
+  DW_CFA_restore: r6 \(rbp\)
+  DW_CFA_def_cfa_offset: 8
+
+#pass
diff --git a/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.l b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.l
new file mode 100644
index 00000000000..abca835a642
--- /dev/null
+++ b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.l
@@ -0,0 +1,2 @@
+.*Assembler messages:
+.*5: Warning: SCFI ignores most user-specified CFI directives
diff --git a/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.s b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.s
new file mode 100644
index 00000000000..80b081ffe07
--- /dev/null
+++ b/gas/testsuite/gas/scfi/x86_64/scfi-cfg-5.s
@@ -0,0 +1,32 @@
+	.text
+	.globl foo
+	.type foo, @function
+foo:
+	.cfi_startproc
+	push  %rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbp, -16
+	mov   %rsp, %rbp
+	.cfi_def_cfa_register %rbp
+	cmpl  $-1, %eax
+	jne .L1
+.L2:
+	.cfi_remember_state
+	call bar
+	pop  %rbp
+	.cfi_def_cfa_register %rsp
+	.cfi_restore %rbp
+	.cfi_def_cfa_offset 8
+	ret
+
+.L1:
+	.cfi_restore_state
+	testq %rax, %rax
+	je .L2
+	pop %rbp
+	.cfi_def_cfa_register %rsp
+	.cfi_restore %rbp
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+	.size foo,.-foo
diff --git a/gas/testsuite/gas/scfi/x86_64/scfi-x86-64.exp b/gas/testsuite/gas/scfi/x86_64/scfi-x86-64.exp
index 63f0d7e4700..a91dc9df9e5 100644
--- a/gas/testsuite/gas/scfi/x86_64/scfi-x86-64.exp
+++ b/gas/testsuite/gas/scfi/x86_64/scfi-x86-64.exp
@@ -82,6 +82,8 @@ if  { ([istarget "x86_64-*-*"] && ![istarget "x86_64-*-linux*-gnux32"]) } then {
     run_list_test "scfi-cfg-3" "--scfi=experimental --warn"
     run_dump_test "scfi-cfg-4"
     run_list_test "scfi-cfg-4" "--scfi=experimental --warn"
+    run_dump_test "scfi-cfg-5"
+    run_list_test "scfi-cfg-5" "--scfi=experimental --warn"
     run_dump_test "scfi-asm-marker-1"
     run_list_test "scfi-asm-marker-1" "--scfi=experimental --warn"
     run_dump_test "scfi-asm-marker-2"
-- 
2.43.0


  parent reply	other threads:[~2024-03-28 23:43 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-28 23:43 [PATCH 0/2] Fix two issues in gcfg and scfi Indu Bhagat
2024-03-28 23:43 ` [PATCH 1/2] gas: gcfg: add_bb_at_ginsn must return root_bb Indu Bhagat
2024-03-28 23:43 ` Indu Bhagat [this message]
2024-04-09  0:29 ` [PATCH 0/2] Fix two issues in gcfg and scfi Indu Bhagat
2024-04-10 10:13   ` Nick Clifton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240328234343.3397845-3-indu.bhagat@oracle.com \
    --to=indu.bhagat@oracle.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).