[llvm] r337007 - [cfi-verify] Support AArch64.

Joel Galenson via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 13 08:19:33 PDT 2018


Author: jgalenson
Date: Fri Jul 13 08:19:33 2018
New Revision: 337007

URL: http://llvm.org/viewvc/llvm-project?rev=337007&view=rev
Log:
[cfi-verify] Support AArch64.

This patch adds support for AArch64 to cfi-verify.

This required three changes to cfi-verify.  First, it generalizes checking if an instruction is a trap by adding a new isTrap flag to TableGen (and defining it for x86 and AArch64).  Second, the code that ensures that the operand register is not clobbered between the CFI check and the indirect call needs to allow a single dereference (in x86 this happens as part of the jump instruction).  Third, we needed to ensure that return instructions are not counted as indirect branches.  Technically, returns are indirect branches and can be covered by CFI, but LLVM's forward-edge CFI does not protect them, and x86 does not consider them, so we keep that behavior.

In addition, we had to improve AArch64's code to evaluate the branch target of a MCInst to handle calls where the destination is not the first operand (which it often is not).

Differential Revision: https://reviews.llvm.org/D48836

Added:
    llvm/trunk/test/tools/llvm-cfi-verify/AArch64/
    llvm/trunk/test/tools/llvm-cfi-verify/AArch64/protected-lineinfo.s
    llvm/trunk/test/tools/llvm-cfi-verify/AArch64/unprotected-lineinfo.s
Modified:
    llvm/trunk/include/llvm/MC/MCInstrDesc.h
    llvm/trunk/include/llvm/Target/Target.td
    llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
    llvm/trunk/lib/Target/X86/X86InstrSystem.td
    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
    llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp
    llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
    llvm/trunk/utils/TableGen/CodeGenInstruction.h
    llvm/trunk/utils/TableGen/InstrDocsEmitter.cpp
    llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp

Modified: llvm/trunk/include/llvm/MC/MCInstrDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCInstrDesc.h?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCInstrDesc.h (original)
+++ llvm/trunk/include/llvm/MC/MCInstrDesc.h Fri Jul 13 08:19:33 2018
@@ -149,7 +149,8 @@ enum Flag {
   ExtractSubreg,
   InsertSubreg,
   Convergent,
-  Add
+  Add,
+  Trap
 };
 }
 
@@ -245,6 +246,9 @@ public:
   /// Return true if the instruction is an add instruction.
   bool isAdd() const { return Flags & (1ULL << MCID::Add); }
 
+  /// Return true if this instruction is a trap.
+  bool isTrap() const { return Flags & (1ULL << MCID::Trap); }
+
   /// Return true if the instruction is a register to register move.
   bool isMoveReg() const { return Flags & (1ULL << MCID::MoveReg); }
 

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Fri Jul 13 08:19:33 2018
@@ -448,6 +448,7 @@ class Instruction {
   bit isBarrier    = 0;     // Can control flow fall through this instruction?
   bit isCall       = 0;     // Is this instruction a call instruction?
   bit isAdd        = 0;     // Is this instruction an add instruction?
+  bit isTrap       = 0;     // Is this instruction a trap instruction?
   bit canFoldAsLoad = 0;    // Can this be folded as a simple memory operand?
   bit mayLoad      = ?;     // Is it possible for this inst to read memory?
   bit mayStore     = ?;     // Is it possible for this inst to write memory?

Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td Fri Jul 13 08:19:33 2018
@@ -1442,7 +1442,9 @@ def : Pat<(AArch64call texternalsym:$fun
 //===----------------------------------------------------------------------===//
 // Exception generation instructions.
 //===----------------------------------------------------------------------===//
+let isTrap = 1 in {
 def BRK   : ExceptionGeneration<0b001, 0b00, "brk">;
+}
 def DCPS1 : ExceptionGeneration<0b101, 0b01, "dcps1">;
 def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">;
 def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">;

Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp Fri Jul 13 08:19:33 2018
@@ -140,14 +140,18 @@ public:
 
   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
                       uint64_t &Target) const override {
-    if (Inst.getNumOperands() == 0 ||
-        Info->get(Inst.getOpcode()).OpInfo[0].OperandType !=
-            MCOI::OPERAND_PCREL)
-      return false;
-
-    int64_t Imm = Inst.getOperand(0).getImm() * 4;
-    Target = Addr + Imm;
-    return true;
+    // Search for a PC-relative argument.
+    // This will handle instructions like bcc (where the first argument is the
+    // condition code) and cbz (where it is a register).
+    const auto &Desc = Info->get(Inst.getOpcode());
+    for (unsigned i = 0, e = Inst.getNumOperands(); i != e; i++) {
+      if (Desc.OpInfo[i].OperandType == MCOI::OPERAND_PCREL) {
+        int64_t Imm = Inst.getOperand(i).getImm() * 4;
+        Target = Addr + Imm;
+        return true;
+      }
+    }
+    return false;
   }
 };
 

Modified: llvm/trunk/lib/Target/X86/X86InstrSystem.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSystem.td?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrSystem.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrSystem.td Fri Jul 13 08:19:33 2018
@@ -22,7 +22,7 @@ let Defs = [RAX, RCX, RDX] in
 
 // CPU flow control instructions
 
-let mayLoad = 1, mayStore = 0, hasSideEffects = 1 in {
+let mayLoad = 1, mayStore = 0, hasSideEffects = 1, isTrap = 1 in {
   def TRAP    : I<0x0B, RawFrm, (outs), (ins), "ud2", [(trap)]>, TB;
   def UD2B    : I<0xB9, RawFrm, (outs), (ins), "ud2b", []>, TB;
 }

Added: llvm/trunk/test/tools/llvm-cfi-verify/AArch64/protected-lineinfo.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/AArch64/protected-lineinfo.s?rev=337007&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/AArch64/protected-lineinfo.s (added)
+++ llvm/trunk/test/tools/llvm-cfi-verify/AArch64/protected-lineinfo.s Fri Jul 13 08:19:33 2018
@@ -0,0 +1,183 @@
+# RUN: llvm-mc %s -filetype obj -triple aarch64-- -o %t.o
+# RUN: llvm-cfi-verify %t.o | FileCheck %s
+
+# CHECK-LABEL: {{^Instruction: .* \(PROTECTED\)}}
+# CHECK-NEXT: tiny.cc:9
+
+# CHECK: Expected Protected: 1 (100.00%)
+# CHECK: Unexpected Protected: 0 (0.00%)
+# CHECK: Expected Unprotected: 0 (0.00%)
+# CHECK: Unexpected Unprotected (BAD): 0 (0.00%)
+
+# Source (tiny.cc):
+#   int a() { return 42; }
+#   int b() { return 137; }
+#   int main(int argc, char** argv) {
+#     int(*ptr)();
+#     if (argc == 1)
+#       ptr = &a;
+#     else
+#       ptr = &b;
+#     return ptr();
+#   }
+	.text
+	.file	"ld-temp.o"
+	.p2align	2
+	.type	_Z1av.cfi, at function
+_Z1av.cfi:
+.Lfunc_begin0:
+	.file	1 "/tmp/tiny.cc"
+	.loc	1 1 0
+	.cfi_startproc
+	.loc	1 1 11 prologue_end
+	mov	w0, #42
+	ret
+.Ltmp0:
+.Lfunc_end0:
+	.size	_Z1av.cfi, .Lfunc_end0-_Z1av.cfi
+	.cfi_endproc
+
+	.p2align	2
+	.type	_Z1bv.cfi, at function
+_Z1bv.cfi:
+.Lfunc_begin1:
+	.loc	1 2 0
+	.cfi_startproc
+	.loc	1 2 11 prologue_end
+	mov	w0, #137
+	ret
+.Ltmp1:
+.Lfunc_end1:
+	.size	_Z1bv.cfi, .Lfunc_end1-_Z1bv.cfi
+	.cfi_endproc
+
+	.p2align	2
+	.type	main, at function
+main:
+.Lfunc_begin2:
+	.loc	1 3 0
+	.cfi_startproc
+	sub	sp, sp, #48
+	stp	x29, x30, [sp, #32]
+	add	x29, sp, #32
+	.cfi_def_cfa w29, 16
+	.cfi_offset w30, -8
+	.cfi_offset w29, -16
+	stur	wzr, [x29, #-4]
+	stur	w0, [x29, #-8]
+	str	x1, [sp, #16]
+.Ltmp2:
+	.loc	1 5 7 prologue_end
+	ldur	w8, [x29, #-8]
+	cmp	w8, #1
+	b.ne	.LBB2_2
+	.loc	1 0 7 is_stmt 0
+	adrp	x8, _Z1av
+	add	x8, x8, :lo12:_Z1av
+	.loc	1 6 9 is_stmt 1
+	str	x8, [sp, #8]
+	.loc	1 6 5 is_stmt 0
+	b	.LBB2_3
+.LBB2_2:
+	.loc	1 0 5
+	adrp	x8, _Z1bv
+	add	x8, x8, :lo12:_Z1bv
+	.loc	1 8 9 is_stmt 1
+	str	x8, [sp, #8]
+.LBB2_3:
+	.loc	1 0 9 is_stmt 0
+	adrp	x8, .L.cfi.jumptable
+	add	x9, x8, :lo12:.L.cfi.jumptable
+	.loc	1 9 10 is_stmt 1
+	ldr	x8, [sp, #8]
+	sub	x9, x8, x9
+	lsr	x10, x9, #2
+	orr	x9, x10, x9, lsl #62
+	cmp	x9, #1
+	b.ls	.LBB2_5
+	brk	#0x1
+.LBB2_5:
+	blr	x8
+	.loc	1 9 3 is_stmt 0
+	ldp	x29, x30, [sp, #32]
+	add	sp, sp, #48
+	ret
+.Ltmp3:
+.Lfunc_end2:
+	.size	main, .Lfunc_end2-main
+	.cfi_endproc
+
+	.p2align	2
+	.type	.L.cfi.jumptable, at function
+.L.cfi.jumptable:
+.Lfunc_begin3:
+	.cfi_startproc
+	//APP
+	b	_Z1av.cfi
+	b	_Z1bv.cfi
+
+	//NO_APP
+.Lfunc_end3:
+	.size	.L.cfi.jumptable, .Lfunc_end3-.L.cfi.jumptable
+	.cfi_endproc
+
+	.type	.L__unnamed_1, at object
+	.section	.rodata,"a", at progbits
+	.p2align	2
+.L__unnamed_1:
+	.size	.L__unnamed_1, 0
+
+	.section	.debug_str,"MS", at progbits,1
+.Linfo_string0:
+	.asciz	"clang version 7.0.0 (trunk 335774) (llvm/trunk 335775)"
+.Linfo_string1:
+	.asciz	"tiny.cc"
+.Linfo_string2:
+	.asciz	""
+	.section	.debug_abbrev,"", at progbits
+	.byte	1
+	.byte	17
+	.byte	0
+	.byte	37
+	.byte	14
+	.byte	19
+	.byte	5
+	.byte	3
+	.byte	14
+	.byte	16
+	.byte	23
+	.byte	27
+	.byte	14
+	.byte	17
+	.byte	1
+	.byte	18
+	.byte	6
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_info,"", at progbits
+.Lcu_begin0:
+	.word	38
+	.hword	4
+	.word	.debug_abbrev
+	.byte	8
+	.byte	1
+	.word	.Linfo_string0
+	.hword	4
+	.word	.Linfo_string1
+	.word	.Lline_table_start0
+	.word	.Linfo_string2
+	.xword	.Lfunc_begin0
+	.word	.Lfunc_end2-.Lfunc_begin0
+	.section	.debug_ranges,"", at progbits
+	.section	.debug_macinfo,"", at progbits
+	.byte	0
+
+	.type	_Z1av, at function
+.set _Z1av, .L.cfi.jumptable
+	.type	_Z1bv, at function
+.set _Z1bv, .L.cfi.jumptable+4
+	.ident	"clang version 7.0.0 (trunk 335774) (llvm/trunk 335775)"
+	.section	".note.GNU-stack","", at progbits
+	.section	.debug_line,"", at progbits
+.Lline_table_start0:

Added: llvm/trunk/test/tools/llvm-cfi-verify/AArch64/unprotected-lineinfo.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/AArch64/unprotected-lineinfo.s?rev=337007&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/AArch64/unprotected-lineinfo.s (added)
+++ llvm/trunk/test/tools/llvm-cfi-verify/AArch64/unprotected-lineinfo.s Fri Jul 13 08:19:33 2018
@@ -0,0 +1,169 @@
+# RUN: llvm-mc %s -filetype obj -triple aarch64-- -o %t.o
+# RUN: llvm-cfi-verify %t.o | FileCheck %s
+
+# CHECK-LABEL: {{^Instruction: .* \(FAIL_BAD_CONDITIONAL_BRANCH\)}}
+# CHECK-NEXT: tiny.cc:9
+
+# CHECK: Expected Protected: 0 (0.00%)
+# CHECK: Unexpected Protected: 0 (0.00%)
+# CHECK: Expected Unprotected: 0 (0.00%)
+# CHECK: Unexpected Unprotected (BAD): 1 (100.00%)
+
+# Source (tiny.cc):
+#   int a() { return 42; }
+#   int b() { return 137; }
+#   int main(int argc, char** argv) {
+#     int(*ptr)();
+#     if (argc == 1)
+#       ptr = &a;
+#     else
+#       ptr = &b;
+#     return ptr();
+#   }
+# Compile with:
+#    clang++ -target aarch64-- -gmlt tiny.cc -S -o tiny.s
+	.text
+	.file	"tiny.cc"
+	.globl	_Z1av
+	.p2align	2
+	.type	_Z1av, at function
+_Z1av:                                  // @_Z1av
+.Lfunc_begin0:
+	.file	1 "tiny.cc"
+	.loc	1 1 0                   // tiny.cc:1:0
+	.cfi_startproc
+// BB#0:
+	mov	w0, #42
+.Ltmp0:
+	.loc	1 1 11 prologue_end     // tiny.cc:1:11
+	ret
+.Ltmp1:
+.Lfunc_end0:
+	.size	_Z1av, .Lfunc_end0-_Z1av
+	.cfi_endproc
+
+	.globl	_Z1bv
+	.p2align	2
+	.type	_Z1bv, at function
+_Z1bv:                                  // @_Z1bv
+.Lfunc_begin1:
+	.loc	1 2 0                   // tiny.cc:2:0
+	.cfi_startproc
+// BB#0:
+	mov	w0, #137
+.Ltmp2:
+	.loc	1 2 11 prologue_end     // tiny.cc:2:11
+	ret
+.Ltmp3:
+.Lfunc_end1:
+	.size	_Z1bv, .Lfunc_end1-_Z1bv
+	.cfi_endproc
+
+	.globl	main
+	.p2align	2
+	.type	main, at function
+main:                                   // @main
+.Lfunc_begin2:
+	.loc	1 3 0                   // tiny.cc:3:0
+	.cfi_startproc
+// BB#0:
+	sub	sp, sp, #48             // =48
+	stp	x29, x30, [sp, #32]     // 8-byte Folded Spill
+	add	x29, sp, #32            // =32
+.Lcfi0:
+	.cfi_def_cfa w29, 16
+.Lcfi1:
+	.cfi_offset w30, -8
+.Lcfi2:
+	.cfi_offset w29, -16
+	stur	wzr, [x29, #-4]
+	stur	w0, [x29, #-8]
+	str	x1, [sp, #16]
+.Ltmp4:
+	.loc	1 5 7 prologue_end      // tiny.cc:5:7
+	ldur	w0, [x29, #-8]
+	cmp		w0, #1          // =1
+	b.ne	.LBB2_2
+// BB#1:
+	.loc	1 0 7 is_stmt 0         // tiny.cc:0:7
+	adrp	x8, _Z1av
+	add	x8, x8, :lo12:_Z1av
+	.loc	1 6 9 is_stmt 1         // tiny.cc:6:9
+	str	x8, [sp, #8]
+	.loc	1 6 5 is_stmt 0         // tiny.cc:6:5
+	b	.LBB2_3
+.LBB2_2:
+	.loc	1 0 5                   // tiny.cc:0:5
+	adrp	x8, _Z1bv
+	add	x8, x8, :lo12:_Z1bv
+	.loc	1 8 9 is_stmt 1         // tiny.cc:8:9
+	str	x8, [sp, #8]
+.LBB2_3:
+	.loc	1 9 10                  // tiny.cc:9:10
+	ldr	x8, [sp, #8]
+	blr	x8
+	.loc	1 9 3 is_stmt 0         // tiny.cc:9:3
+	ldp	x29, x30, [sp, #32]     // 8-byte Folded Reload
+	add	sp, sp, #48             // =48
+	ret
+.Ltmp5:
+.Lfunc_end2:
+	.size	main, .Lfunc_end2-main
+	.cfi_endproc
+
+	.section	.debug_str,"MS", at progbits,1
+.Linfo_string0:
+	.asciz	"clang version 4.0.1-10 (tags/RELEASE_401/final)" // string offset=0
+.Linfo_string1:
+	.asciz	"tiny.cc"               // string offset=48
+.Linfo_string2:
+	.asciz	"/tmp"                  // string offset=56
+	.section	.debug_loc,"", at progbits
+	.section	.debug_abbrev,"", at progbits
+.Lsection_abbrev:
+	.byte	1                       // Abbreviation Code
+	.byte	17                      // DW_TAG_compile_unit
+	.byte	0                       // DW_CHILDREN_no
+	.byte	37                      // DW_AT_producer
+	.byte	14                      // DW_FORM_strp
+	.byte	19                      // DW_AT_language
+	.byte	5                       // DW_FORM_data2
+	.byte	3                       // DW_AT_name
+	.byte	14                      // DW_FORM_strp
+	.byte	16                      // DW_AT_stmt_list
+	.byte	23                      // DW_FORM_sec_offset
+	.byte	27                      // DW_AT_comp_dir
+	.byte	14                      // DW_FORM_strp
+	.byte	17                      // DW_AT_low_pc
+	.byte	1                       // DW_FORM_addr
+	.byte	18                      // DW_AT_high_pc
+	.byte	6                       // DW_FORM_data4
+	.byte	0                       // EOM(1)
+	.byte	0                       // EOM(2)
+	.byte	0                       // EOM(3)
+	.section	.debug_info,"", at progbits
+.Lsection_info:
+.Lcu_begin0:
+	.word	38                      // Length of Unit
+	.hword	4                       // DWARF version number
+	.word	.Lsection_abbrev        // Offset Into Abbrev. Section
+	.byte	8                       // Address Size (in bytes)
+	.byte	1                       // Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+	.word	.Linfo_string0          // DW_AT_producer
+	.hword	4                       // DW_AT_language
+	.word	.Linfo_string1          // DW_AT_name
+	.word	.Lline_table_start0     // DW_AT_stmt_list
+	.word	.Linfo_string2          // DW_AT_comp_dir
+	.xword	.Lfunc_begin0           // DW_AT_low_pc
+	.word	.Lfunc_end2-.Lfunc_begin0 // DW_AT_high_pc
+	.section	.debug_ranges,"", at progbits
+.Ldebug_range:
+	.section	.debug_macinfo,"", at progbits
+.Ldebug_macinfo:
+.Lcu_macro_begin0:
+	.byte	0                       // End Of Macro List Mark
+
+	.ident	"clang version 4.0.1-10 (tags/RELEASE_401/final)"
+	.section	".note.GNU-stack","", at progbits
+	.section	.debug_line,"", at progbits
+.Lline_table_start0:

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp Fri Jul 13 08:19:33 2018
@@ -154,7 +154,8 @@ const Instr &FileAnalysis::getInstructio
 }
 
 bool FileAnalysis::isCFITrap(const Instr &InstrMeta) const {
-  return MII->getName(InstrMeta.Instruction.getOpcode()) == "TRAP";
+  const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
+  return InstrDesc.isTrap();
 }
 
 bool FileAnalysis::canFallThrough(const Instr &InstrMeta) const {
@@ -296,20 +297,38 @@ uint64_t FileAnalysis::indirectCFOperand
     else
       Node = Branch.Fallthrough;
 
-    while (Node != Graph.BaseAddress) {
+    // Some architectures (e.g., AArch64) cannot load in an indirect branch, so
+    // we allow them one load.
+    bool canLoad = !MII->get(IndirectCF.Instruction.getOpcode()).mayLoad();
+
+    // We walk backwards from the indirect CF.  It is the last node returned by
+    // Graph.flattenAddress, so we skip it since we already handled it.
+    DenseSet<unsigned> CurRegisterNumbers = RegisterNumbers;
+    std::vector<uint64_t> Nodes = Graph.flattenAddress(Node);
+    for (auto I = Nodes.rbegin() + 1, E = Nodes.rend(); I != E; ++I) {
+      Node = *I;
       const Instr &NodeInstr = getInstructionOrDie(Node);
       const auto &InstrDesc = MII->get(NodeInstr.Instruction.getOpcode());
 
-      for (unsigned RegNum : RegisterNumbers) {
+      for (auto RI = CurRegisterNumbers.begin(), RE = CurRegisterNumbers.end();
+           RI != RE; ++RI) {
+        unsigned RegNum = *RI;
         if (InstrDesc.hasDefOfPhysReg(NodeInstr.Instruction, RegNum,
-                                      *RegisterInfo))
-          return Node;
+                                      *RegisterInfo)) {
+          if (!canLoad || !InstrDesc.mayLoad())
+            return Node;
+          canLoad = false;
+          CurRegisterNumbers.erase(RI);
+          // Add the registers this load reads to those we check for clobbers.
+          for (unsigned i = InstrDesc.getNumDefs(),
+                        e = InstrDesc.getNumOperands(); i != e; i++) {
+            const auto Operand = NodeInstr.Instruction.getOperand(i);
+            if (Operand.isReg())
+              CurRegisterNumbers.insert(Operand.getReg());
+          }
+          break;
+        }
       }
-
-      const auto &KV = Graph.IntermediateNodes.find(Node);
-      assert((KV != Graph.IntermediateNodes.end()) &&
-             "Could not get next node.");
-      Node = KV->second;
     }
   }
 
@@ -456,6 +475,9 @@ void FileAnalysis::parseSectionContents(
     if (!usesRegisterOperand(InstrMeta))
       continue;
 
+    if (InstrDesc.isReturn())
+      continue;
+
     // Check if this instruction exists in the range of the DWARF metadata.
     if (!IgnoreDWARFFlag) {
       auto LineInfo =

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h Fri Jul 13 08:19:33 2018
@@ -149,10 +149,13 @@ public:
   CFIProtectionStatus validateCFIProtection(const GraphResult &Graph) const;
 
   // Returns the first place the operand register is clobbered between the CFI-
-  // check and the indirect CF instruction execution. If the register is not
-  // modified, returns the address of the indirect CF instruction. The result is
-  // undefined if the provided graph does not fall under either the
-  // FAIL_REGISTER_CLOBBERED or PROTECTED status (see CFIProtectionStatus).
+  // check and the indirect CF instruction execution. We do this by walking
+  // backwards from the indirect CF and ensuring there is at most one load
+  // involving the operand register (which is the indirect CF itself on x86).
+  // If the register is not modified, returns the address of the indirect CF
+  // instruction. The result is undefined if the provided graph does not fall
+  // under either the FAIL_REGISTER_CLOBBERED or PROTECTED status (see
+  // CFIProtectionStatus).
   uint64_t indirectCFOperandClobber(const GraphResult& Graph) const;
 
   // Prints an instruction to the provided stream using this object's pretty-

Modified: llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp Fri Jul 13 08:19:33 2018
@@ -45,10 +45,10 @@ using ::testing::Field;
 namespace llvm {
 namespace cfi_verify {
 namespace {
-class ELFx86TestFileAnalysis : public FileAnalysis {
+class ELFTestFileAnalysis : public FileAnalysis {
 public:
-  ELFx86TestFileAnalysis()
-      : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {}
+  ELFTestFileAnalysis(StringRef Trip)
+      : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}
 
   // Expose this method publicly for testing.
   void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
@@ -62,6 +62,8 @@ public:
 };
 
 class BasicFileAnalysisTest : public ::testing::Test {
+public:
+  BasicFileAnalysisTest(StringRef Trip) : Analysis(Trip) {}
 protected:
   virtual void SetUp() {
     IgnoreDWARFFlag = true;
@@ -70,17 +72,27 @@ protected:
       handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
         SuccessfullyInitialised = false;
         outs()
-            << "Note: CFIVerifyTests are disabled due to lack of x86 support "
+            << "Note: CFIVerifyTests are disabled due to lack of support "
                "on this build.\n";
       });
     }
   }
 
   bool SuccessfullyInitialised;
-  ELFx86TestFileAnalysis Analysis;
+  ELFTestFileAnalysis Analysis;
+};
+
+class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {
+public:
+  BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
+};
+
+class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
+public:
+  BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
 };
 
-TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
+TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -190,7 +202,7 @@ TEST_F(BasicFileAnalysisTest, BasicDisas
   EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
 }
 
-TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
+TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -213,7 +225,7 @@ TEST_F(BasicFileAnalysisTest, PrevAndNex
   EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
 }
 
-TEST_F(BasicFileAnalysisTest, CFITrapTest) {
+TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -248,7 +260,7 @@ TEST_F(BasicFileAnalysisTest, CFITrapTes
       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
 }
 
-TEST_F(BasicFileAnalysisTest, FallThroughTest) {
+TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -288,7 +300,7 @@ TEST_F(BasicFileAnalysisTest, FallThroug
       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
 }
 
-TEST_F(BasicFileAnalysisTest, DefiniteNextInstructionTest) {
+TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -378,7 +390,7 @@ TEST_F(BasicFileAnalysisTest, DefiniteNe
   EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
 }
 
-TEST_F(BasicFileAnalysisTest, ControlFlowXRefsTest) {
+TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -483,7 +495,7 @@ TEST_F(BasicFileAnalysisTest, ControlFlo
   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionInvalidTargets) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -507,7 +519,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -522,7 +534,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionBasicJumpToUd2) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -537,7 +549,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathUd2) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -555,7 +567,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathSingleUd2) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -572,7 +584,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -597,7 +609,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
   SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -621,7 +633,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
   SearchLengthForUndef = PrevSearchLengthForUndef;
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionGoodAndBadPaths) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -637,7 +649,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -653,7 +665,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionComplexExample) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
   if (!SuccessfullyInitialised)
     return;
   // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
@@ -683,7 +695,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
   SearchLengthForUndef = PrevSearchLengthForUndef;
 }
 
-TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTest) {
+TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
   Analysis.parseSectionContents(
       {
           0x77, 0x0d,                   // 0x688118: ja 0x688127 [+12]
@@ -702,7 +714,7 @@ TEST_F(BasicFileAnalysisTest, UndefSearc
   SearchLengthForUndef = PrevSearchLengthForUndef;
 }
 
-TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTestFarAway) {
+TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
   Analysis.parseSectionContents(
       {
           0x74, 0x73,                         // 0x7759eb: je 0x775a60
@@ -741,7 +753,7 @@ TEST_F(BasicFileAnalysisTest, UndefSearc
   SearchLengthForUndef = PrevSearchLengthForUndef;
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -757,7 +769,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -773,7 +785,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -789,7 +801,7 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
             Analysis.validateCFIProtection(Result));
 }
 
-TEST_F(BasicFileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
+TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
   if (!SuccessfullyInitialised)
     return;
   Analysis.parseSectionContents(
@@ -806,6 +818,243 @@ TEST_F(BasicFileAnalysisTest, CFIProtect
   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
             Analysis.validateCFIProtection(Result));
 }
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
+          0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 12: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
+          0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
+          0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
+          0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
+          0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
+          0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
+          0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
+          0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 16: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0x03, 0x00, 0x00, 0x14, // 0: b 12
+          0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
+          0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
+          0x20, 0x00, 0x1f, 0xd6, // 12: br x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
+          0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
+          0x03, 0x00, 0x00, 0x14, // 8: b 12
+          0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
+          0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 20: br x1
+          0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 20);
+  EXPECT_EQ(CFIProtectionStatus::PROTECTED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
+          0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
+          0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
+          0x03, 0x00, 0x00, 0x14, // 12: b 12
+          0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
+          0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 24: br x1
+          0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
+
+TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
+  if (!SuccessfullyInitialised)
+    return;
+  Analysis.parseSectionContents(
+      {
+          0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
+          0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
+          0x03, 0x00, 0x00, 0x14, // 8: b 12
+          0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
+          0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
+          0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
+          0x20, 0x00, 0x1f, 0xd6, // 24: br x1
+          0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
+      },
+      0xDEADBEEF);
+  GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24);
+  EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
+            Analysis.validateCFIProtection(Result));
+}
 
 } // anonymous namespace
 } // end namespace cfi_verify

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Fri Jul 13 08:19:33 2018
@@ -312,6 +312,7 @@ CodeGenInstruction::CodeGenInstruction(R
   isBarrier    = R->getValueAsBit("isBarrier");
   isCall       = R->getValueAsBit("isCall");
   isAdd        = R->getValueAsBit("isAdd");
+  isTrap       = R->getValueAsBit("isTrap");
   canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
   isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
   isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.h?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.h Fri Jul 13 08:19:33 2018
@@ -232,6 +232,7 @@ template <typename T> class ArrayRef;
     bool isBarrier : 1;
     bool isCall : 1;
     bool isAdd : 1;
+    bool isTrap : 1;
     bool canFoldAsLoad : 1;
     bool mayLoad : 1;
     bool mayLoad_Unset : 1;

Modified: llvm/trunk/utils/TableGen/InstrDocsEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrDocsEmitter.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/InstrDocsEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/InstrDocsEmitter.cpp Fri Jul 13 08:19:33 2018
@@ -109,6 +109,7 @@ void EmitInstrDocs(RecordKeeper &RK, raw
     FLAG(isBarrier)
     FLAG(isCall)
     FLAG(isAdd)
+    FLAG(isTrap)
     FLAG(canFoldAsLoad)
     FLAG(mayLoad)
     //FLAG(mayLoad_Unset) // Deliberately omitted.

Modified: llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp?rev=337007&r1=337006&r2=337007&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp Fri Jul 13 08:19:33 2018
@@ -576,6 +576,7 @@ void InstrInfoEmitter::emitRecord(const
   if (Inst.isMoveReg)          OS << "|(1ULL<<MCID::MoveReg)";
   if (Inst.isBitcast)          OS << "|(1ULL<<MCID::Bitcast)";
   if (Inst.isAdd)              OS << "|(1ULL<<MCID::Add)";
+  if (Inst.isTrap)             OS << "|(1ULL<<MCID::Trap)";
   if (Inst.isSelect)           OS << "|(1ULL<<MCID::Select)";
   if (Inst.isBarrier)          OS << "|(1ULL<<MCID::Barrier)";
   if (Inst.hasDelaySlot)       OS << "|(1ULL<<MCID::DelaySlot)";




More information about the llvm-commits mailing list