new file mode 100644
@@ -0,0 +1,11 @@
+Notes on how the SCFI testsuite is organized:
+
+The SCFI testsuite has target dependent components because most meaningul tests
+will need an input which is assembly code.
+
+At this time, support for x86_64 is added.
+
+When adding more tests, please keep CFI annotations updated in the .s files,
+even though the testcases are run with --scfi command line option (this means
+that the CFI annotations are not processed by GAS). Adding CFI directives
+makes the testcases clearer in terms of the expected unwind data.
new file mode 100644
@@ -0,0 +1,25 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for add insn
+#...
+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: [01][abc]
+ 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+0014 0+001c FDE cie=0+0000 pc=0+0000..0+0005
+ DW_CFA_advance_loc: 4 to 0+0004
+ DW_CFA_def_cfa_offset: 0
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,13 @@
+# Testcase for add instruction.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ addq $8, %rsp
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,36 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for add insn
+#...
+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: [01][abc]
+ 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+0024 0+001c FDE cie=0+0000 pc=0+0000..0+001d
+ 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: 2 to 0+0006
+ DW_CFA_offset: r12 \(r12\) at cfa-24
+ DW_CFA_advance_loc: 21 to 0+001b
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_advance_loc: 1 to 0+001c
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,43 @@
+ .section .rodata
+ .type simd_cmp_op, @object
+ .size simd_cmp_op, 8
+simd_cmp_op:
+ .long 2
+ .zero 4
+
+# Testcase for add instruction.
+# add reg, reg instruction
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r12
+ .cfi_offset 12, -24
+ mov %rsp, %r12
+# Stack manipulation is permitted if the base register for
+# tracking CFA has been changed to FP.
+ addq %rdx, %rsp
+ addq %rsp, %rax
+# Other kind of add instructions should not error out in the
+# x86_64 -> ginsn translator
+ addq $simd_cmp_op+8, %rdx
+ mov %r12, %rsp
+# Popping a callee-saved register.
+# RSP must be traceable.
+ pop %r12
+ .cfi_restore 12
+ leave
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,31 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for SP/FP based CFA switching
+#...
+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: [01][abc]
+ 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+001c 0+001c FDE cie=0+0000 pc=0+0000..0+000c
+ 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: 6 to 0+000a
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_advance_loc: 1 to 0+000b
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+
+#pass
new file mode 100644
@@ -0,0 +1,22 @@
+# Testcase for switching between sp/fp based CFA.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ addq %rax, %rdi
+ mov %rbp, %rsp
+ .cfi_def_cfa_register 7
+ pop %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,40 @@
+#as: --scfi
+#objdump: -Wf
+#name: SCFI for callee-saved registers
+#...
+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: [01][abc]
+ 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+0002c 0+0001c FDE cie=0+0000 pc=0+0000..0+0007
+ DW_CFA_advance_loc: 1 to 0+0001
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 1 to 0+0002
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_offset: r3 \(rbx\) at cfa-24
+ DW_CFA_advance_loc: 1 to 0+0003
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_offset: r6 \(rbp\) at cfa-32
+ DW_CFA_advance_loc: 1 to 0+0004
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 1 to 0+0005
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 1 to 0+0006
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,26 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rax
+ .cfi_def_cfa_offset 16
+ push %rbx
+ .cfi_def_cfa_offset 24
+ .cfi_offset 3, -24
+ pushq %rbp
+ .cfi_def_cfa_offset 32
+ .cfi_offset 6, -32
+ popq %rbp
+ .cfi_def_cfa_offset 24
+ .cfi_restore 6
+ popq %rbx
+ .cfi_def_cfa_offset 16
+ .cfi_restore 3
+ popq %rax
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,41 @@
+#as: --scfi
+#objdump: -Wf
+#name: SCFI for callee-saved registers 2
+#...
+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: [01][abc]
+ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+ DW_CFA_offset: r16 \(rip\) at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+
+00000018 0+002c 0000001c FDE cie=00000000 pc=0+0000..0+0017
+ DW_CFA_advance_loc: 2 to 0+0002
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r12 \(r12\) at cfa-16
+ DW_CFA_advance_loc: 2 to 0+0004
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_offset: r13 \(r13\) at cfa-24
+ DW_CFA_advance_loc: 9 to 0+000d
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_advance_loc: 1 to 0+000e
+ DW_CFA_def_cfa_offset: 40
+ DW_CFA_advance_loc: 4 to 0+0012
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 2 to 0+0014
+ DW_CFA_restore: r13 \(r13\)
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 2 to 0+0016
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,42 @@
+# Testcase for save reg ops for callee-saved registers
+# These latter two pushq's of callee-saved regs must NOT generate
+# .cfi_offset.
+
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %r12
+ .cfi_def_cfa_offset 16
+ .cfi_offset 12, -16
+ pushq %r13
+ .cfi_def_cfa_offset 24
+ .cfi_offset 13, -24
+# The function may use callee-saved registers for its use, and may even
+# chose to spill them to stack if necessary.
+ addq %rax, %r13
+ subq $8, %r13
+# These two pushq's of callee-saved regs must NOT generate
+# .cfi_offset.
+ pushq %r13
+ .cfi_def_cfa_offset 32
+ pushq %rax
+ .cfi_def_cfa_offset 40
+# Adjust the REG_SP to get rid of local stack usage.
+ addq $16, %rsp
+ .cfi_def_cfa_offset 24
+# The SCFI machinery keeps track of where the callee-saved registers
+# are on the stack. It generates a restore operation if the stack
+# offsets match.
+ popq %r13
+ .cfi_restore 13
+ .cfi_def_cfa_offset 16
+ popq %r12
+ .cfi_restore 12
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,42 @@
+#as: -W --scfi
+#objdump: -Wf
+#name: SCFI for callee-saved registers 3
+#...
+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: [01][abc]
+ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+ DW_CFA_offset: r16 \(rip\) at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+
+00000018 0+002c 0000001c FDE cie=00000000 pc=0+0000..0+0016
+ DW_CFA_advance_loc: 2 to 0+0002
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r12 \(r12\) at cfa-16
+ DW_CFA_advance_loc: 2 to 0+0004
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_offset: r13 \(r13\) at cfa-24
+ DW_CFA_advance_loc: 9 to 0+000d
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_advance_loc: 1 to 0+000e
+ DW_CFA_def_cfa_offset: 40
+ DW_CFA_advance_loc: 1 to 0+000f
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_advance_loc: 2 to 0+0011
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 2 to 0+0013
+ DW_CFA_restore: r13 \(r13\)
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 2 to 0+0015
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+
+#pass
new file mode 100644
@@ -0,0 +1,40 @@
+# Testcase for save reg ops for callee-saved registers
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %r12
+ .cfi_def_cfa_offset 16
+ .cfi_offset 12, -16
+ pushq %r13
+ .cfi_def_cfa_offset 24
+ .cfi_offset 13, -24
+# The program may use callee-saved registers for its use, and may even
+# chose to spill them to stack if necessary.
+ addq %rax, %r13
+ subq $8, %r13
+# These two pushq's of callee-saved regs must NOT generate
+# .cfi_offset.
+ pushq %r13
+ .cfi_def_cfa_offset 32
+ pushq %rax
+ .cfi_def_cfa_offset 40
+ popq %rax
+ .cfi_def_cfa_offset 32
+ popq %r13
+ .cfi_def_cfa_offset 24
+# The SCFI machinery keeps track of where the callee-saved registers
+# are on the stack. It generates a restore operation if the stack
+# offsets match.
+ popq %r13
+ .cfi_restore 13
+ .cfi_def_cfa_offset 16
+ popq %r12
+ .cfi_restore 12
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,40 @@
+#as: -W --scfi
+#objdump: -Wf
+#name: SCFI for callee-saved registers 4
+#...
+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: [01][abc]
+ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+ DW_CFA_offset: r16 \(rip\) at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+
+00000018 0+002c 0000001c FDE cie=00000000 pc=0+0000..0+005e
+ DW_CFA_advance_loc: 5 to 0+0005
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r6 \(rbp\) at cfa-16
+ DW_CFA_advance_loc: 3 to 0+0008
+ DW_CFA_def_cfa_register: r6 \(rbp\)
+ DW_CFA_advance_loc: 2 to 0+000a
+ DW_CFA_offset: r12 \(r12\) at cfa-24
+ DW_CFA_advance_loc: 1 to 0+000b
+ DW_CFA_offset: r3 \(rbx\) at cfa-32
+ DW_CFA_advance_loc1: 79 to 0+005a
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_advance_loc: 2 to 0+005c
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_advance_loc: 1 to 0+005d
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,55 @@
+ .type byte_insert_op1, @function
+byte_insert_op1:
+.LFB10:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r12
+ .cfi_offset 12, -24
+ pushq %rbx
+ .cfi_offset 3, -32
+ subq $24, %rsp
+ movl %edi, -20(%rbp)
+ movq %rsi, -32(%rbp)
+ movl %edx, -24(%rbp)
+ movq %rcx, -40(%rbp)
+# The program may use callee-saved registers for its use, and may even
+# chose to read them from stack if necessary. The following use should
+# not be treated as reg restore for SCFI purposes (because rbx has been
+# saved to -16(%rbp).
+ movq -40(%rbp), %rbx
+ movq -40(%rbp), %rax
+ leaq 3(%rax), %r12
+ jmp .L563
+.L564:
+ subq $1, %rbx
+ subq $1, %r12
+ movzbl (%rbx), %eax
+ movb %al, (%r12)
+.L563:
+ cmpq -32(%rbp), %rbx
+ jne .L564
+ movl -24(%rbp), %edx
+ movq -32(%rbp), %rcx
+ movl -20(%rbp), %eax
+ movq %rcx, %rsi
+ movl %eax, %edi
+ call byte_store_op1
+ nop
+ addq $24, %rsp
+ popq %rbx
+ .cfi_restore 3
+ popq %r12
+ .cfi_restore 12
+ popq %rbp
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE10:
+ .size byte_insert_op1, .-byte_insert_op1
new file mode 100644
@@ -0,0 +1,36 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI in presence of control flow 1
+#...
+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: [01][abc]
+ 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+0024 0000001c FDE cie=00000000 pc=0+0000..0+003a
+ DW_CFA_advance_loc: 1 to 0+0001
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r3 \(rbx\) at cfa-16
+ DW_CFA_advance_loc: 37 to 0+0026
+ DW_CFA_remember_state
+ DW_CFA_advance_loc: 1 to 0+0027
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_advance_loc: 1 to 0+0028
+ DW_CFA_restore_state
+ DW_CFA_advance_loc: 9 to 0+0031
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,47 @@
+# Testcase with one dominator bb and two exit bbs
+# Something like for: return ferror (f) || fclose (f) != 0;
+ .text
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+ .string "w"
+.LC1:
+ .string "conftest.out"
+ .section .text.startup,"ax",@progbits
+ .p2align 4
+ .globl main
+ .type main, @function
+main:
+.LFB11:
+ .cfi_startproc
+ pushq %rbx
+ .cfi_def_cfa_offset 16
+ .cfi_offset 3, -16
+ movl $.LC0, %esi
+ movl $.LC1, %edi
+ call fopen
+ movq %rax, %rdi
+ movq %rax, %rbx
+ call ferror
+ movl %eax, %edx
+ movl $1, %eax
+ testl %edx, %edx
+ je .L7
+ .cfi_remember_state
+ popq %rbx
+ .cfi_restore 3
+ .cfi_def_cfa_offset 8
+ ret
+.L7:
+ .cfi_restore_state
+ movq %rbx, %rdi
+ call fclose
+ popq %rbx
+ .cfi_restore 3
+ .cfi_def_cfa_offset 8
+ testl %eax, %eax
+ setne %al
+ movzbl %al, %eax
+ ret
+ .cfi_endproc
+.LFE11:
+ .size main, .-main
new file mode 100644
@@ -0,0 +1,28 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI in presence of control flow 2
+#...
+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: [01][abc]
+ 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+0001c 0+001c FDE cie=00000000 pc=0000000000000000..0000000000000016
+ 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_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,21 @@
+# Testcase for CFG creation of ginsns
+# This testcase has no return instruction at the end.
+ .text
+ .globl main
+ .type main, @function
+main:
+.LFB7:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ call foo
+ shrl $31, %eax
+ movzbl %al, %eax
+ movl %eax, %edi
+ call exit
+ .cfi_endproc
+.LFE7:
+ .size main, .-main
new file mode 100644
@@ -0,0 +1,5 @@
+#as: --scfi -W
+#objdump: -Wf
+#name: Synthesize CFI for add insn
+
+#pass
new file mode 100644
@@ -0,0 +1,20 @@
+# Testcase with a variety of "change of flow instructions"
+#
+# Must be run with -W so it remains warning free.
+#
+# This test does not have much going on wrt synthesis of CFI;
+# it just aims to ensure x8_64 -> ginsn decoding must behave
+# gracefully for these "change of flow instructions"
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ addq %rdx, %rax
+ notrack jmp *%rax
+ call *%r8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,3 @@
+.*Assembler messages:
+.*14: Error: SCFI: usage of REG_FP as scratch not supported
+.*22: Warning: SCFI: forward pass failed for func 'foo'
new file mode 100644
@@ -0,0 +1,23 @@
+# Testcase for REG_FP based CFA
+# and using REG_FP as scratch.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+# The following add causes REG_FP to become untraceable
+ addq %rax, %rbp
+ .cfi_def_cfa_register 7
+ pop %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,3 @@
+.*Assembler messages:
+.*21: Warning: SCFI: asymetrical register restore
+.*22: Warning: SCFI: asymetrical register restore
new file mode 100644
@@ -0,0 +1,28 @@
+# Testcase for a diagnostic around assymetrical restore
+.type foo, @function
+foo:
+.LFB10:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r12
+ pushq %rbx
+ subq $24, %rsp
+ .cfi_offset 12, -24
+ .cfi_offset 3, -32
+ addq $24, %rsp
+# Note that the order of r12 and rbx restore does not match
+# order of the corresponding save(s).
+# The SCFI machinery warns the user.
+ popq %r12
+ popq %rbx
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE10:
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,23 @@
+#as: --scfi --gsframe
+#objdump: --sframe
+#name: SCFI for dynamic alloc stack
+#...
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: NONE
+ Num FDEs: 1
+ Num FREs: 4
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 87 bytes
+ STARTPC + CFA + FP + RA
+ 0+0000 + sp\+8 + u + u
+ 0+0001 + sp\+16 + c-16 + u
+ 0+0004 + fp\+16 + c-16 + u
+ 0+0056 + sp\+8 + u + u
+
+#pass
new file mode 100644
@@ -0,0 +1,50 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r13
+ pushq %r12
+ pushq %rbx
+ subq $8, %rsp
+ .cfi_offset 13, -24
+ .cfi_offset 12, -32
+ .cfi_offset 3, -40
+ call read_user
+ testl %eax, %eax
+ jle .L2
+ cltq
+ xorl %ebx, %ebx
+ leaq 0(,%rax,4), %r13
+ .p2align 4,,10
+ .p2align 3
+.L3:
+ leaq 15(%rbx), %rax
+ movq %rsp, %r12
+ addq $4, %rbx
+ andq $-16, %rax
+ subq %rax, %rsp
+ movq %rsp, %rdi
+ call foo
+ movq %r12, %rsp
+ cmpq %r13, %rbx
+ jne .L3
+.L2:
+ leaq -24(%rbp), %rsp
+ xorl %eax, %eax
+ popq %rbx
+ popq %r12
+ popq %r13
+ popq %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_register 7
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,2 @@
+.*Assembler messages:
+.*28: Warning: SCFI: asymetrical register restore
new file mode 100644
@@ -0,0 +1,55 @@
+# Testcase for a diagnostic around assymetrical restore
+# Testcase inspired by byte_insert_op1 in libiberty
+# False positive for the diagnostic
+.type foo, @function
+foo:
+.LFB10:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r12
+ pushq %rbx
+ subq $24, %rsp
+ .cfi_offset 12, -24
+ .cfi_offset 3, -32
+ movl %edi, -20(%rbp)
+ movq %rsi, -32(%rbp)
+ movl %edx, -24(%rbp)
+ movq %rcx, -40(%rbp)
+# The assembler cannot differentiate that the following
+# mov to %rbx is not a true restore operation, but simply
+# %rbx register usage as a scratch reg of some sort.
+# The assembler merely warns of a possible assymetric restore operation
+# In this case, its noise for the user unfortunately.
+ movq -40(%rbp), %rbx
+ movq -40(%rbp), %rax
+ leaq 3(%rax), %r12
+ jmp .L563
+.L564:
+ subq $1, %rbx
+ subq $1, %r12
+ movzbl (%rbx), %eax
+ movb %al, (%r12)
+.L563:
+ cmpq -32(%rbp), %rbx
+ jne .L564
+ movl -24(%rbp), %edx
+ movq -32(%rbp), %rcx
+ movl -20(%rbp), %eax
+ movq %rcx, %rsi
+ movl %eax, %edi
+ call byte_store_op1
+ nop
+ addq $24, %rsp
+ popq %rbx
+ popq %r12
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE10:
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,26 @@
+#as: --scfi
+#objdump: -Wf
+#name: Ignore user specified CFI directives
+#...
+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: [01][abc]
+ 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+0014 0+001c FDE cie=0+0000 pc=0+0000..0+0002
+ DW_CFA_advance_loc: 1 to 0+0001
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r6 \(rbp\) at cfa-16
+ DW_CFA_nop
+ DW_CFA_nop
+
+#pass
new file mode 100644
@@ -0,0 +1,13 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,51 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for indirect mem op to stack
+#...
+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: [01][abc]
+ 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+0034 0+001c FDE cie=00000000 pc=0+0000..0+005b
+ DW_CFA_advance_loc: 4 to 0+0004
+ DW_CFA_def_cfa_offset: 64
+ DW_CFA_advance_loc: 4 to 0+0008
+ DW_CFA_offset: r3 \(rbx\) at cfa-64
+ DW_CFA_advance_loc: 5 to 0+000d
+ DW_CFA_offset: r6 \(rbp\) at cfa-56
+ DW_CFA_advance_loc: 5 to 0+0012
+ DW_CFA_offset: r12 \(r12\) at cfa-48
+ DW_CFA_advance_loc: 5 to 0+0017
+ DW_CFA_offset: r13 \(r13\) at cfa-40
+ DW_CFA_advance_loc: 5 to 0+001c
+ DW_CFA_offset: r14 \(r14\) at cfa-32
+ DW_CFA_advance_loc: 5 to 0+0021
+ DW_CFA_offset: r15 \(r15\) at cfa-24
+ DW_CFA_advance_loc: 29 to 0+003e
+ DW_CFA_restore: r15 \(r15\)
+ DW_CFA_advance_loc: 5 to 0+0043
+ DW_CFA_restore: r14 \(r14\)
+ DW_CFA_advance_loc: 5 to 0+0048
+ DW_CFA_restore: r13 \(r13\)
+ DW_CFA_advance_loc: 5 to 0+004d
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_advance_loc: 5 to 0+0052
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_advance_loc: 4 to 0+0056
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_advance_loc: 4 to 0+005a
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,48 @@
+# An example of static stack allocation by hand
+ .type foo, @function
+foo:
+ .cfi_startproc
+ /* Allocate space for 7 registers. */
+ subq $56,%rsp
+ .cfi_adjust_cfa_offset 56
+ movq %rbx,(%rsp)
+ .cfi_rel_offset 3, 0
+ movq %rbp,8(%rsp)
+ .cfi_rel_offset 6, 8
+ movq %r12,16(%rsp)
+ .cfi_rel_offset 12, 16
+ movq %r13,24(%rsp)
+ .cfi_rel_offset 13, 24
+ movq %r14,32(%rsp)
+ .cfi_rel_offset 14, 32
+ movq %r15,40(%rsp)
+ .cfi_rel_offset 15, 40
+ movq %r9,48(%rsp)
+
+ /* Setup parameter for __foo_internal. */
+ /* selfpc is the return address on the stack. */
+ movq 56(%rsp),%rsi
+ /* Get frompc via the frame pointer. */
+ movq 8(%rbp),%rdi
+ call __foo_internal
+ /* Pop the saved registers. Please note that `foo' has no
+ return value. */
+ movq 48(%rsp),%r9
+
+ movq 40(%rsp),%r15
+ .cfi_restore 15
+ movq 32(%rsp),%r14
+ .cfi_restore 14
+ movq 24(%rsp),%r13
+ .cfi_restore 13
+ movq 16(%rsp),%r12
+ .cfi_restore 12
+ movq 8(%rsp),%rbp
+ .cfi_restore 6
+ movq (%rsp),%rbx
+ .cfi_restore 3
+ addq $56,%rsp
+ .cfi_adjust_cfa_offset -56
+ ret
+ .cfi_endproc
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,41 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for indirect mem op to stack
+#...
+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: [01][abc]
+ 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 0+001c FDE cie=00000000 pc=0+0000..0+0026
+ 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: 8 to 0+000c
+ DW_CFA_offset: r3 \(rbx\) at cfa-32
+ DW_CFA_advance_loc: 4 to 0+0010
+ DW_CFA_offset: r12 \(r12\) at cfa-24
+ DW_CFA_advance_loc: 9 to 0+0019
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_advance_loc: 4 to 0+001d
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_advance_loc: 7 to 0+0024
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_advance_loc: 1 to 0+0025
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,38 @@
+# Testcase for movq instructions
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+
+ subq $16,%rsp
+
+# store rbx at %rsp; rsp = rbp - 16;
+ movq %rbx, -16(%rbp)
+ .cfi_rel_offset 3, -16
+# store r12 at %rsp + 8; rsp = rbp -16;
+ movq %r12, -8(%rbp)
+ .cfi_rel_offset 12, -8
+
+ call bar
+
+ movq -16(%rbp), %rbx
+ .cfi_restore 3
+ movq -8(%rbp), %r12
+ .cfi_restore 12
+
+ addq $16,%rsp
+
+ mov %rbp, %rsp
+ .cfi_def_cfa_register 7
+ pop %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,41 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for indirect mem op to stack
+#...
+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: [01][abc]
+ 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 0+001c FDE cie=00000000 pc=0+0000..0+0028
+ 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: 8 to 0+000c
+ DW_CFA_offset: r3 \(rbx\) at cfa-32
+ DW_CFA_advance_loc: 5 to 0+0011
+ DW_CFA_offset: r12 \(r12\) at cfa-24
+ DW_CFA_advance_loc: 9 to 0+001a
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_advance_loc: 5 to 0+001f
+ DW_CFA_restore: r12 \(r12\)
+ DW_CFA_advance_loc: 7 to 0+0026
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_advance_loc: 1 to 0+0027
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,38 @@
+# Testcase for movq instructions
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+
+ subq $16,%rsp
+
+# store rbx at %rsp; rsp = rbp - 16; rsp = CFA - 32
+ movq %rbx, (%rsp)
+ .cfi_rel_offset 3, -16
+# store r12 at %rsp + 8; rsp = CFA - 32
+ movq %r12, 8(%rsp)
+ .cfi_rel_offset 12, -8
+
+ call bar
+
+ movq (%rsp), %rbx
+ .cfi_restore 3
+ movq 8(%rsp), %r12
+ .cfi_restore 12
+
+ addq $16,%rsp
+
+ mov %rbp, %rsp
+ .cfi_def_cfa_register 7
+ pop %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,37 @@
+#as: --scfi -O2
+#objdump: -Wf
+#name: Synthesize CFI for various lea instructions (-O2)
+#...
+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: [01][abc]
+ 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+0024 0+001c FDE cie=00000000 pc=0+0000..0+0029
+ 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: 2 to 0+0006
+ DW_CFA_offset: r13 \(r13\) at cfa-24
+ DW_CFA_advance_loc: 33 to 0+0027
+ DW_CFA_restore: r13 \(r13\)
+ DW_CFA_advance_loc: 1 to 0+0028
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,40 @@
+## Testcase with a variety of lea.
+## This test is run with -O2 by default to check
+## SCFI in wake of certain target optimizations.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+# This lea gets transformed to mov %rsp, %rbp when -O2.
+# The SCFI machinery must see it as such.
+ lea (%rsp), %rbp
+ .cfi_def_cfa_register 6
+ push %r13
+ .cfi_offset 13, -24
+ subq $8, %rsp
+ testl %eax, %eax
+ jle .L2
+.L3:
+ movq %rsp, %r12
+ lea -0x2(%r13),%rax
+ lea 0x8(%r12,%rdx,4),%r8
+ movq %r12, %rsp
+ jne .L3
+.L2:
+ leaq -8(%rbp), %rsp
+ xorl %eax, %eax
+ popq %r13
+ .cfi_restore 13
+ popq %rbp
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,36 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for leave insn
+#...
+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: [01][abc]
+ 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+0024 0+001c FDE cie=0+0000 pc=0+0000..0+000a
+ 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: 1 to 0+0005
+ DW_CFA_offset: r3 \(rbx\) at cfa-24
+ DW_CFA_advance_loc: 3 to 0+0008
+ DW_CFA_restore: r3 \(rbx\)
+ DW_CFA_advance_loc: 1 to 0+0009
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,26 @@
+# Testcase for leave insn
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ push %rbx
+ .cfi_offset 3, -24
+ push %rdi
+ pop %rdi
+ pop %rbx
+ .cfi_restore 3
+ leave
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,35 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for pushq insns
+#...
+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: [01][abc]
+ 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+0024 0+001c FDE cie=0+0000 pc=0+0000..0+000c
+ DW_CFA_advance_loc: 1 to 0+0001
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 3 to 0+0004
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 2 to 0+0006
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_advance_loc: 2 to 0+0008
+ DW_CFA_def_cfa_offset: 40
+ DW_CFA_advance_loc: 2 to 0+0000a
+ DW_CFA_def_cfa_offset: 48
+ DW_CFA_advance_loc: 1 to 0+0000b
+ DW_CFA_def_cfa_offset: 56
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,24 @@
+## Testcase with a variety of pushq.
+## all push insns valid in 64-bit mode must be processed for SCFI.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rax
+ .cfi_def_cfa_offset 16
+ pushq 16(%rax)
+ .cfi_def_cfa_offset 24
+ pushq $36
+ .cfi_def_cfa_offset 32
+ pushq %fs
+ .cfi_def_cfa_offset 40
+ pushq %gs
+ .cfi_def_cfa_offset 48
+ pushf
+ .cfi_def_cfa_offset 56
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,31 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for self-aligning func
+#...
+Contents of the .eh_frame section:
+
+0+0000 0+0014 0+0000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -8
+ Return address column: 16
+ Augmentation data: [01][abc]
+ 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+001c 0000001c FDE cie=00000000 pc=0+0000..0+002f
+ 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: 42 to 0+002e
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+
+#pass
new file mode 100644
@@ -0,0 +1,36 @@
+# If it is known that the caller of self_aligning_foo may have had
+# the stack pointer unaligned to 16-bytes boundary, such self-aligning
+# functions may be used by asm programmers.
+ .globl self_aligning_foo
+ .type self_aligning_foo, @function
+self_aligning_foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+# The following 'and' op aligns the stack pointer.
+# At the same time, it causes REG_SP to become non-traceable
+# for SCFI purposes. But no warning is issued as no further stack
+# size tracking is needed for SCFI purposes.
+ andq $-16, %rsp
+ subq $32, %rsp
+ movl %edi, 12(%rsp)
+ movl %esi, 8(%rsp)
+ movl $0, %eax
+ call vector_using_function
+ movaps %xmm0, 16(%rsp)
+ movl 12(%rsp), %edx
+ movl 8(%rsp), %eax
+ addl %edx, %eax
+ leave
+# GCC typically generates a '.cfi_def_cfa 7, 8' for leave
+# insn. The SCFI however, will generate the following:
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size self_aligning_foo, .-self_aligning_foo
new file mode 100644
@@ -0,0 +1,26 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for push to stack
+#...
+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: [01][abc]
+ 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+0014 0+001c FDE cie=0+0000 pc=0+0000..0+0002
+ DW_CFA_advance_loc: 1 to 0+0001
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r6 \(rbp\) at cfa-16
+ DW_CFA_nop
+ DW_CFA_nop
+
+#pass
new file mode 100644
@@ -0,0 +1,9 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ pushq %rbp
+ ret
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,30 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for push to stack
+#...
+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: [01][abc]
+ 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+0001c 0+0001c FDE cie=0+0000 pc=0+0000..0+0003
+ 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: 1 to 0+0002
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,16 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ popq %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,25 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for sub insn
+#...
+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: [01][abc]
+ 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+0014 0+001c FDE cie=0+0000 pc=0+0000..0+0008
+ DW_CFA_advance_loc: 7 to 0+0007
+ DW_CFA_def_cfa_offset: 120016
+ DW_CFA_nop
+#...
+
+#pass
new file mode 100644
@@ -0,0 +1,12 @@
+# Testcase for sub instruction.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ subq $120008, %rsp
+ .cfi_def_cfa_offset 120016
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,31 @@
+#as: --scfi
+#objdump: -Wf
+#name: Synthesize CFI for sub insn
+#...
+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: [01][abc]
+ 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+001c 0+001c FDE cie=0+0000 pc=0+0000..0+000c
+ 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: 7 to 0+000b
+ DW_CFA_def_cfa_register: r7 \(rsp\)
+ DW_CFA_restore: r6 \(rbp\)
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_nop
+
+#pass
new file mode 100644
@@ -0,0 +1,23 @@
+# Testcase for sub reg, reg instruction.
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq %rax, %rsp
+# SCFI: Stack-pointer manipulation after switching
+# to RBP based tracking is OK.
+ addq %rax, %rsp
+ leave
+ .cfi_def_cfa_register 7
+ .cfi_restore 6
+ .cfi_def_cfa_offset 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
new file mode 100644
@@ -0,0 +1,2 @@
+Assembler messages:
+Fatal error: Synthesizing CFI is not supported for this ABI
new file mode 100644
@@ -0,0 +1,10 @@
+# Testcase run with --m32 (Not supported).
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ pushq %rbp
+ ret
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,3 @@
+.*Assembler messages:
+.*8: Error: SCFI: unsupported stack manipulation pattern
+.*13: Warning: SCFI: forward pass failed for func 'foo'
new file mode 100644
@@ -0,0 +1,14 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ addq %rdx, %rax
+# Stack manipulation without switching to RBP
+# based tracking is not supported for SCFI.
+ addq %rax, %rsp
+ push %rdi
+ leave
+ ret
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,2 @@
+.*Assembler messages:
+.*52: Warning: Untraceable control flow for func 'foo'
new file mode 100644
@@ -0,0 +1,53 @@
+# Testcase with an indirect jump
+# Indirect jumps, when present, make the list of ginsn an invalid
+# candidate for CFG creation. Hence, no SCFI can be generated either.
+#
+# The testcase is rather long to showcase a simple concept. The reason of
+# such a long testcase is to discuss if it is important to deal with these
+# patterns. It may be possible to deal with this, if we allow some special
+# directives for helping the assembler with the indirect jump (jump table).
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl %edi, -4(%rbp)
+ cmpl $5, -4(%rbp)
+ ja .L2
+ movl -4(%rbp), %eax
+ movq .L4(,%rax,8), %rax
+ jmp *%rax
+.L4:
+ .quad .L9
+ .quad .L8
+ .quad .L7
+ .quad .L6
+ .quad .L5
+ .quad .L3
+.L9:
+ movl $43, %eax
+ jmp .L1
+.L8:
+ movl $42, %eax
+ jmp .L1
+.L7:
+ movl $45, %eax
+ jmp .L1
+.L6:
+ movl $47, %eax
+ jmp .L1
+.L5:
+ movl $37, %eax
+ jmp .L1
+.L3:
+ movl $63, %eax
+ jmp .L1
+.L2:
+.L1:
+ popq %rbp
+ ret
+ .cfi_endproc
+.LFE0:
+ .size foo, .-foo
+
new file mode 100644
@@ -0,0 +1,3 @@
+.*Assembler messages:
+.*19: Error: SCFI: unsupported stack manipulation pattern
+.*75: Warning: SCFI: forward pass failed for func 'drap_foo'
new file mode 100644
@@ -0,0 +1,75 @@
+# Testcase with Dynamically Realigned Argument Pointer (DRAP)
+# register usage.
+#
+# There are two reasons why this cannot be supported with the current
+# SCFI machinery
+# 1. Not allowed: REG_CFA is r10 based for the few insns after
+# 'leaq 8(%rsp), %r10'.
+# 2. Untraceable stack size after 'andq $-16, %rsp'
+# Both of these shortcomings may be worked out. FIXME DISCUSS Keep the rather
+# long testcase until then.
+ .text
+ .globl drap_foo
+ .type drap_foo, @function
+drap_foo:
+.LFB0:
+ .cfi_startproc
+ leaq 8(%rsp), %r10
+ .cfi_def_cfa 10, 0
+ andq $-16, %rsp
+ pushq -8(%r10)
+ .cfi_def_cfa 7, 8
+ pushq %rbp
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r10
+ .cfi_offset 15, -24
+ .cfi_offset 14, -32
+ .cfi_offset 13, -40
+ .cfi_offset 12, -48
+ pushq %rbx
+ .cfi_offset 3, -64
+ subq $32, %rsp
+ movq $0, (%rdx)
+ cmpq $0, (%rdi)
+ movq $0, -56(%rbp)
+ je .L21
+ movq %rdi, %rbx
+ movq %rsi, %rdi
+ movq %rsi, %r12
+ call func2@PLT
+ movq (%rbx), %rdi
+ leaq -56(%rbp), %rdx
+ movslq %eax, %rsi
+ call func1@PLT
+ testl %eax, %eax
+ je .L21
+ movq -56(%rbp), %r13
+.L21:
+ addq $32, %rsp
+ xorl %eax, %eax
+ popq %rbx
+ .cfi_restore 3
+ popq %r10
+ popq %r12
+ .cfi_restore 12
+ popq %r13
+ .cfi_restore 13
+ popq %r14
+ .cfi_restore 14
+ popq %r15
+ .cfi_restore 15
+ popq %rbp
+ .cfi_restore 6
+ .cfi_def_cfa_register 7
+ .cfi_def_cfa_offset 8
+ leaq -8(%r10), %rsp
+ ret
+ .cfi_endproc
+.LFE0:
+ .size drap_foo, .-drap_foo
new file mode 100644
@@ -0,0 +1,59 @@
+# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+if { ![is_elf_format] } then {
+ return
+}
+
+# common tests
+if { ([istarget "x86_64-*-*"]) } then {
+
+ global ASFLAGS
+ set old_ASFLAGS "$ASFLAGS"
+
+ run_list_test "scfi-diag-1" "--scfi"
+ run_list_test "scfi-fp-diag-2" "--scfi"
+ run_list_test "scfi-diag-2" "--scfi"
+
+ run_list_test "scfi-unsupported-1" "--32 --scfi"
+ run_list_test "scfi-unsupported-2" "--scfi"
+ run_list_test "scfi-unsupported-drap-1" "--scfi"
+ run_list_test "scfi-unsupported-cfg-1" "--scfi"
+
+ run_dump_test "scfi-add-1"
+ run_dump_test "scfi-add-2"
+ run_dump_test "scfi-cfg-1"
+ run_dump_test "scfi-cfg-2"
+ run_dump_test "scfi-cofi-1"
+ run_dump_test "scfi-sub-1"
+ run_dump_test "scfi-sub-2"
+ run_dump_test "scfi-ignore-1"
+ run_dump_test "scfi-simple-1"
+ run_dump_test "scfi-simple-2"
+ run_dump_test "scfi-pushq-1"
+ run_dump_test "scfi-lea-1"
+ run_dump_test "scfi-leave-1"
+ run_dump_test "scfi-bp-sp-1"
+ run_dump_test "scfi-callee-saved-1"
+ run_dump_test "scfi-callee-saved-2"
+ run_dump_test "scfi-callee-saved-3"
+ run_dump_test "scfi-callee-saved-4"
+ run_dump_test "scfi-dyn-stack-1"
+ run_dump_test "scfi-indirect-mov-1"
+ run_dump_test "scfi-indirect-mov-2"
+ run_dump_test "scfi-indirect-mov-3"
+ run_dump_test "scfi-selfalign-func-1"
+}