xref: /llvm-project/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp (revision 7fc871591f1399cd88ff301ed84fa67dc3bf7a6b)
1 //===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
10 #include "../tools/llvm-cfi-verify/lib/GraphBuilder.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 
14 #include "llvm/BinaryFormat/ELF.h"
15 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstPrinter.h"
21 #include "llvm/MC/MCInstrAnalysis.h"
22 #include "llvm/MC/MCInstrDesc.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCObjectFileInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Object/Binary.h"
29 #include "llvm/Object/COFF.h"
30 #include "llvm/Object/ELFObjectFile.h"
31 #include "llvm/Object/ObjectFile.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/Error.h"
35 #include "llvm/Support/MemoryBuffer.h"
36 #include "llvm/Support/TargetSelect.h"
37 #include "llvm/Support/raw_ostream.h"
38 
39 #include <cstdlib>
40 
41 using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
42 using ::testing::Eq;
43 using ::testing::Field;
44 
45 namespace llvm {
46 namespace cfi_verify {
47 namespace {
48 class ELFTestFileAnalysis : public FileAnalysis {
49 public:
50   ELFTestFileAnalysis(StringRef Trip)
51       : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}
52 
53   // Expose this method publicly for testing.
54   void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
55                             object::SectionedAddress Address) {
56     FileAnalysis::parseSectionContents(SectionBytes, Address);
57   }
58 
59   Error initialiseDisassemblyMembers() {
60     return FileAnalysis::initialiseDisassemblyMembers();
61   }
62 };
63 
64 class BasicFileAnalysisTest : public ::testing::Test {
65 public:
66   BasicFileAnalysisTest(StringRef Trip)
67       : SuccessfullyInitialised(false), Analysis(Trip) {}
68 protected:
69   void SetUp() override {
70     IgnoreDWARFFlag = true;
71     SuccessfullyInitialised = true;
72     if (auto Err = Analysis.initialiseDisassemblyMembers()) {
73       handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
74         SuccessfullyInitialised = false;
75         outs()
76             << "Note: CFIVerifyTests are disabled due to lack of support "
77                "on this build.\n";
78       });
79     }
80   }
81 
82   bool SuccessfullyInitialised;
83   ELFTestFileAnalysis Analysis;
84 };
85 
86 class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {
87 public:
88   BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
89 };
90 
91 class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
92 public:
93   BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
94 };
95 
96 TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
97   if (!SuccessfullyInitialised)
98     GTEST_SKIP();
99   Analysis.parseSectionContents(
100       {
101           0x90,                   // 0: nop
102           0xb0, 0x00,             // 1: mov $0x0, %al
103           0x48, 0x89, 0xe5,       // 3: mov %rsp, %rbp
104           0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
105           0x48, 0xbe, 0xc4, 0x07, 0x40,
106           0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
107           0x2f,                         // 20: (bad)
108           0x41, 0x0e,                   // 21: rex.B (bad)
109           0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
110       },
111       {0xDEADBEEF, 0x0});
112 
113   EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
114   EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
115 
116   // 0xDEADBEEF: nop
117   const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
118   EXPECT_NE(nullptr, InstrMeta);
119   EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
120   EXPECT_EQ(1u, InstrMeta->InstructionSize);
121   EXPECT_TRUE(InstrMeta->Valid);
122 
123   const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
124   EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
125   const auto *PrevInstrMeta = InstrMeta;
126 
127   // 0xDEADBEEF + 1: mov $0x0, %al
128   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
129   EXPECT_NE(nullptr, InstrMeta);
130   EXPECT_EQ(NextInstrMeta, InstrMeta);
131   EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
132   EXPECT_EQ(2u, InstrMeta->InstructionSize);
133   EXPECT_TRUE(InstrMeta->Valid);
134 
135   NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
136   EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
137   PrevInstrMeta = InstrMeta;
138 
139   // 0xDEADBEEF + 3: mov %rsp, %rbp
140   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
141   EXPECT_NE(nullptr, InstrMeta);
142   EXPECT_EQ(NextInstrMeta, InstrMeta);
143   EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
144   EXPECT_EQ(3u, InstrMeta->InstructionSize);
145   EXPECT_TRUE(InstrMeta->Valid);
146 
147   NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
148   EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
149   PrevInstrMeta = InstrMeta;
150 
151   // 0xDEADBEEF + 6: sub $0x18, %rsp
152   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
153   EXPECT_NE(nullptr, InstrMeta);
154   EXPECT_EQ(NextInstrMeta, InstrMeta);
155   EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
156   EXPECT_EQ(4u, InstrMeta->InstructionSize);
157   EXPECT_TRUE(InstrMeta->Valid);
158 
159   NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
160   EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
161   PrevInstrMeta = InstrMeta;
162 
163   // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
164   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
165   EXPECT_NE(nullptr, InstrMeta);
166   EXPECT_EQ(NextInstrMeta, InstrMeta);
167   EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
168   EXPECT_EQ(10u, InstrMeta->InstructionSize);
169   EXPECT_TRUE(InstrMeta->Valid);
170 
171   EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
172   EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
173   PrevInstrMeta = InstrMeta;
174 
175   // 0xDEADBEEF + 20: (bad)
176   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
177   EXPECT_NE(nullptr, InstrMeta);
178   EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
179   EXPECT_EQ(1u, InstrMeta->InstructionSize);
180   EXPECT_FALSE(InstrMeta->Valid);
181 
182   EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
183   EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
184 
185   // 0xDEADBEEF + 21: rex.B (bad)
186   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
187   EXPECT_NE(nullptr, InstrMeta);
188   EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
189   EXPECT_EQ(2u, InstrMeta->InstructionSize);
190   EXPECT_FALSE(InstrMeta->Valid);
191 
192   EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
193   EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
194 
195   // 0xDEADBEEF + 6: (bad) {%k1}
196   InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
197   EXPECT_NE(nullptr, InstrMeta);
198   EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
199   EXPECT_EQ(5u, InstrMeta->InstructionSize);
200   EXPECT_FALSE(InstrMeta->Valid);
201 
202   EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
203   EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
204 }
205 
206 TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {
207   if (!SuccessfullyInitialised)
208     GTEST_SKIP();
209   Analysis.parseSectionContents(
210       {
211           0x90, // 0: nop
212           0x2f, // 1: (bad)
213           0x90  // 2: nop
214       },
215       {0xDEADBEEF, 0x0});
216   const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
217   const auto *GoodInstrMeta =
218       Analysis.getPrevInstructionSequential(BadInstrMeta);
219   EXPECT_NE(nullptr, GoodInstrMeta);
220   EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
221   EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
222 
223   GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
224   EXPECT_NE(nullptr, GoodInstrMeta);
225   EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
226   EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
227 }
228 
229 TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {
230   if (!SuccessfullyInitialised)
231     GTEST_SKIP();
232   Analysis.parseSectionContents(
233       {
234           0x90,                   // 0: nop
235           0xb0, 0x00,             // 1: mov $0x0, %al
236           0x48, 0x89, 0xe5,       // 3: mov %rsp, %rbp
237           0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
238           0x48, 0xbe, 0xc4, 0x07, 0x40,
239           0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
240           0x2f,                         // 20: (bad)
241           0x41, 0x0e,                   // 21: rex.B (bad)
242           0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
243           0x0f, 0x0b                    // 28: ud2
244       },
245       {0xDEADBEEF, 0x0});
246 
247   EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
248   EXPECT_FALSE(
249       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
250   EXPECT_FALSE(
251       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
252   EXPECT_FALSE(
253       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
254   EXPECT_FALSE(
255       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
256   EXPECT_FALSE(
257       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
258   EXPECT_FALSE(
259       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
260   EXPECT_TRUE(
261       Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
262 }
263 
264 TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
265   if (!SuccessfullyInitialised)
266     GTEST_SKIP();
267   Analysis.parseSectionContents(
268       {
269           0x90,                         // 0: nop
270           0xb0, 0x00,                   // 1: mov $0x0, %al
271           0x2f,                         // 3: (bad)
272           0x0f, 0x0b,                   // 4: ud2
273           0xff, 0x20,                   // 6: jmpq *(%rax)
274           0xeb, 0x00,                   // 8: jmp +0
275           0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
276           0xff, 0x10,                   // 15: callq *(rax)
277           0x75, 0x00,                   // 17: jne +0
278           0xc3,                         // 19: retq
279       },
280       {0xDEADBEEF, 0x0});
281 
282   EXPECT_TRUE(
283       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
284   EXPECT_TRUE(
285       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
286   EXPECT_FALSE(
287       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
288   EXPECT_FALSE(
289       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
290   EXPECT_FALSE(
291       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
292   EXPECT_FALSE(
293       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
294   EXPECT_FALSE(
295       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
296   EXPECT_FALSE(
297       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
298   EXPECT_TRUE(
299       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
300   EXPECT_FALSE(
301       Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
302 }
303 
304 TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
305   if (!SuccessfullyInitialised)
306     GTEST_SKIP();
307   Analysis.parseSectionContents(
308       {
309           0x90,                         // 0: nop
310           0xb0, 0x00,                   // 1: mov $0x0, %al
311           0x2f,                         // 3: (bad)
312           0x0f, 0x0b,                   // 4: ud2
313           0xff, 0x20,                   // 6: jmpq *(%rax)
314           0xeb, 0x00,                   // 8: jmp 10 [+0]
315           0xeb, 0x05,                   // 10: jmp 17 [+5]
316           0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
317           0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
318           0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
319           0xff, 0x10,                   // 27: callq *(rax)
320           0x75, 0x00,                   // 29: jne 31 [+0]
321           0x75, 0xe0,                   // 31: jne 1 [-32]
322           0xc3,                         // 33: retq
323           0xeb, 0xdd,                   // 34: jmp 1 [-35]
324           0xeb, 0xdd,                   // 36: jmp 3 [-35]
325           0xeb, 0xdc,                   // 38: jmp 4 [-36]
326       },
327       {0xDEADBEEF, 0x0});
328 
329   const auto *Current = Analysis.getInstruction(0xDEADBEEF);
330   const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
331   EXPECT_NE(nullptr, Next);
332   EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
333 
334   Current = Analysis.getInstruction(0xDEADBEEF + 1);
335   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
336 
337   Current = Analysis.getInstruction(0xDEADBEEF + 3);
338   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
339 
340   Current = Analysis.getInstruction(0xDEADBEEF + 4);
341   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
342 
343   Current = Analysis.getInstruction(0xDEADBEEF + 6);
344   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
345 
346   Current = Analysis.getInstruction(0xDEADBEEF + 8);
347   Next = Analysis.getDefiniteNextInstruction(*Current);
348   EXPECT_NE(nullptr, Next);
349   EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
350 
351   Current = Analysis.getInstruction(0xDEADBEEF + 10);
352   Next = Analysis.getDefiniteNextInstruction(*Current);
353   EXPECT_NE(nullptr, Next);
354   EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
355 
356   Current = Analysis.getInstruction(0xDEADBEEF + 12);
357   Next = Analysis.getDefiniteNextInstruction(*Current);
358   EXPECT_NE(nullptr, Next);
359   EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
360 
361   Current = Analysis.getInstruction(0xDEADBEEF + 17);
362   // Note, definite next instruction address is out of range and should fail.
363   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
364   Next = Analysis.getDefiniteNextInstruction(*Current);
365 
366   Current = Analysis.getInstruction(0xDEADBEEF + 22);
367   Next = Analysis.getDefiniteNextInstruction(*Current);
368   EXPECT_NE(nullptr, Next);
369   EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
370 
371   Current = Analysis.getInstruction(0xDEADBEEF + 27);
372   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
373   Current = Analysis.getInstruction(0xDEADBEEF + 29);
374   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
375   Current = Analysis.getInstruction(0xDEADBEEF + 31);
376   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
377   Current = Analysis.getInstruction(0xDEADBEEF + 33);
378   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
379 
380   Current = Analysis.getInstruction(0xDEADBEEF + 34);
381   Next = Analysis.getDefiniteNextInstruction(*Current);
382   EXPECT_NE(nullptr, Next);
383   EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
384 
385   Current = Analysis.getInstruction(0xDEADBEEF + 36);
386   EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
387 
388   Current = Analysis.getInstruction(0xDEADBEEF + 38);
389   Next = Analysis.getDefiniteNextInstruction(*Current);
390   EXPECT_NE(nullptr, Next);
391   EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
392 }
393 
394 TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {
395   if (!SuccessfullyInitialised)
396     GTEST_SKIP();
397   Analysis.parseSectionContents(
398       {
399           0x90,                         // 0: nop
400           0xb0, 0x00,                   // 1: mov $0x0, %al
401           0x2f,                         // 3: (bad)
402           0x0f, 0x0b,                   // 4: ud2
403           0xff, 0x20,                   // 6: jmpq *(%rax)
404           0xeb, 0x00,                   // 8: jmp 10 [+0]
405           0xeb, 0x05,                   // 10: jmp 17 [+5]
406           0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
407           0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
408           0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
409           0xff, 0x10,                   // 27: callq *(rax)
410           0x75, 0x00,                   // 29: jne 31 [+0]
411           0x75, 0xe0,                   // 31: jne 1 [-32]
412           0xc3,                         // 33: retq
413           0xeb, 0xdd,                   // 34: jmp 1 [-35]
414           0xeb, 0xdd,                   // 36: jmp 3 [-35]
415           0xeb, 0xdc,                   // 38: jmp 4 [-36]
416       },
417       {0xDEADBEEF, 0x0});
418   const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
419   std::set<const Instr *> XRefs =
420       Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
421   EXPECT_TRUE(XRefs.empty());
422 
423   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
424   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
425   EXPECT_THAT(XRefs, UnorderedElementsAre(
426                          Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
427                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
428                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
429 
430   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
431   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
432   EXPECT_THAT(XRefs, UnorderedElementsAre(
433                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
434                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
435 
436   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
437   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
438   EXPECT_THAT(XRefs, UnorderedElementsAre(
439                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
440 
441   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
442   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
443 
444   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
445   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
446   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
447 
448   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
449   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
450   EXPECT_THAT(XRefs, UnorderedElementsAre(
451                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
452 
453   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
454   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
455   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
456 
457   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
458   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
459   EXPECT_THAT(XRefs, UnorderedElementsAre(
460                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
461                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
462 
463   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
464   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
465   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
466 
467   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
468   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
469   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
470 
471   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
472   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
473   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
474 
475   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
476   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
477   EXPECT_THAT(XRefs, UnorderedElementsAre(
478                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
479                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
480 
481   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
482   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
483   EXPECT_THAT(XRefs, UnorderedElementsAre(
484                          Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
485 
486   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
487   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
488   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
489 
490   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
491   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
492   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
493 
494   InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
495   XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
496   EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
497 }
498 
499 TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {
500   if (!SuccessfullyInitialised)
501     GTEST_SKIP();
502   Analysis.parseSectionContents(
503       {
504           0x90,       // 0: nop
505           0x0f, 0x0b, // 1: ud2
506           0x75, 0x00, // 3: jne 5 [+0]
507       },
508       {0xDEADBEEF, 0x0});
509   GraphResult Result =
510       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
511   EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
512             Analysis.validateCFIProtection(Result));
513   Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
514   EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
515             Analysis.validateCFIProtection(Result));
516   Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
517   EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
518             Analysis.validateCFIProtection(Result));
519   Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0});
520   EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,
521             Analysis.validateCFIProtection(Result));
522 }
523 
524 TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
525   if (!SuccessfullyInitialised)
526     GTEST_SKIP();
527   Analysis.parseSectionContents(
528       {
529           0x75, 0x02, // 0: jne 4 [+2]
530           0x0f, 0x0b, // 2: ud2
531           0xff, 0x10, // 4: callq *(%rax)
532       },
533       {0xDEADBEEF, 0x0});
534   GraphResult Result =
535       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
536   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
537             Analysis.validateCFIProtection(Result));
538 }
539 
540 TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
541   if (!SuccessfullyInitialised)
542     GTEST_SKIP();
543   Analysis.parseSectionContents(
544       {
545           0x75, 0x02, // 0: jne 4 [+2]
546           0xff, 0x10, // 2: callq *(%rax)
547           0x0f, 0x0b, // 4: ud2
548       },
549       {0xDEADBEEF, 0x0});
550   GraphResult Result =
551       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
552   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
553             Analysis.validateCFIProtection(Result));
554 }
555 
556 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
557   if (!SuccessfullyInitialised)
558     GTEST_SKIP();
559   Analysis.parseSectionContents(
560       {
561           0x75, 0x03, // 0: jne 5 [+3]
562           0x90,       // 2: nop
563           0xff, 0x10, // 3: callq *(%rax)
564           0x0f, 0x0b, // 5: ud2
565           0x75, 0xf9, // 7: jne 2 [-7]
566           0x0f, 0x0b, // 9: ud2
567       },
568       {0xDEADBEEF, 0x0});
569   GraphResult Result =
570       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
571   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
572             Analysis.validateCFIProtection(Result));
573 }
574 
575 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
576   if (!SuccessfullyInitialised)
577     GTEST_SKIP();
578   Analysis.parseSectionContents(
579       {
580           0x75, 0x05, // 0: jne 7 [+5]
581           0x90,       // 2: nop
582           0xff, 0x10, // 3: callq *(%rax)
583           0x75, 0xfb, // 5: jne 2 [-5]
584           0x0f, 0x0b, // 7: ud2
585       },
586       {0xDEADBEEF, 0x0});
587   GraphResult Result =
588       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
589   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
590             Analysis.validateCFIProtection(Result));
591 }
592 
593 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
594   if (!SuccessfullyInitialised)
595     GTEST_SKIP();
596   Analysis.parseSectionContents(
597       {
598           0x75, 0x06, // 0: jne 8 [+6]
599           0x90,       // 2: nop
600           0x90,       // 3: nop
601           0x90,       // 4: nop
602           0x90,       // 5: nop
603           0xff, 0x10, // 6: callq *(%rax)
604           0x0f, 0x0b, // 8: ud2
605       },
606       {0xDEADBEEF, 0x0});
607   uint64_t PrevSearchLengthForConditionalBranch =
608       SearchLengthForConditionalBranch;
609   SearchLengthForConditionalBranch = 2;
610 
611   GraphResult Result =
612       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
613   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
614             Analysis.validateCFIProtection(Result));
615 
616   SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
617 }
618 
619 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
620   if (!SuccessfullyInitialised)
621     GTEST_SKIP();
622   Analysis.parseSectionContents(
623       {
624           0x75, 0x02, // 0: jne 4 [+2]
625           0xff, 0x10, // 2: callq *(%rax)
626           0x90,       // 4: nop
627           0x90,       // 5: nop
628           0x90,       // 6: nop
629           0x90,       // 7: nop
630           0x0f, 0x0b, // 8: ud2
631       },
632       {0xDEADBEEF, 0x0});
633   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
634   SearchLengthForUndef = 2;
635 
636   GraphResult Result =
637       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
638   EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
639             Analysis.validateCFIProtection(Result));
640 
641   SearchLengthForUndef = PrevSearchLengthForUndef;
642 }
643 
644 TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {
645   if (!SuccessfullyInitialised)
646     GTEST_SKIP();
647   Analysis.parseSectionContents(
648       {
649           0xeb, 0x02, // 0: jmp 4 [+2]
650           0x75, 0x02, // 2: jne 6 [+2]
651           0xff, 0x10, // 4: callq *(%rax)
652           0x0f, 0x0b, // 6: ud2
653       },
654       {0xDEADBEEF, 0x0});
655   GraphResult Result =
656       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
657   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
658             Analysis.validateCFIProtection(Result));
659 }
660 
661 TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
662   if (!SuccessfullyInitialised)
663     GTEST_SKIP();
664   Analysis.parseSectionContents(
665       {
666           0x75, 0x04, // 0: jne 6 [+4]
667           0xeb, 0x00, // 2: jmp 4 [+0]
668           0xff, 0x10, // 4: callq *(%rax)
669           0x0f, 0x0b, // 6: ud2
670       },
671       {0xDEADBEEF, 0x0});
672   GraphResult Result =
673       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
674   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
675             Analysis.validateCFIProtection(Result));
676 }
677 
678 TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
679   if (!SuccessfullyInitialised)
680     GTEST_SKIP();
681   // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
682   // graph.
683   Analysis.parseSectionContents(
684       {
685           0x75, 0x12,                   // 0: jne 20 [+18]
686           0xeb, 0x03,                   // 2: jmp 7 [+3]
687           0x75, 0x10,                   // 4: jne 22 [+16]
688           0x90,                         // 6: nop
689           0x90,                         // 7: nop
690           0x90,                         // 8: nop
691           0xff, 0x10,                   // 9: callq *(%rax)
692           0xeb, 0xfc,                   // 11: jmp 9 [-4]
693           0x75, 0xfa,                   // 13: jne 9 [-6]
694           0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
695           0x90,                         // 20: nop
696           0x90,                         // 21: nop
697           0x0f, 0x0b,                   // 22: ud2
698       },
699       {0xDEADBEEF, 0x0});
700   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
701   SearchLengthForUndef = 5;
702   GraphResult Result =
703       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
704   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
705             Analysis.validateCFIProtection(Result));
706   SearchLengthForUndef = PrevSearchLengthForUndef;
707 }
708 
709 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
710   Analysis.parseSectionContents(
711       {
712           0x77, 0x0d,                   // 0x688118: ja 0x688127 [+12]
713           0x48, 0x89, 0xdf,             // 0x68811a: mov %rbx, %rdi
714           0xff, 0xd0,                   // 0x68811d: callq *%rax
715           0x48, 0x89, 0xdf,             // 0x68811f: mov %rbx, %rdi
716           0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
717           0x0f, 0x0b,                   // 0x688127: ud2
718       },
719       {0x688118, 0x0});
720   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
721   SearchLengthForUndef = 1;
722   GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});
723   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
724             Analysis.validateCFIProtection(Result));
725   SearchLengthForUndef = PrevSearchLengthForUndef;
726 }
727 
728 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
729   Analysis.parseSectionContents(
730       {
731           0x74, 0x73,                         // 0x7759eb: je 0x775a60
732           0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
733       },
734       {0x7759eb, 0x0});
735 
736   Analysis.parseSectionContents(
737       {
738           0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne    0x775e0e
739           0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add    $0xfffffffffffffff4,%rbx
740           0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov    0x10(%rsp),%rdi
741           0x48, 0x89, 0xde,             // 0x775a65: mov    %rbx,%rsi
742           0xff, 0xd1,                   // 0x775a68: callq  *%rcx
743       },
744       {0x775a56, 0x0});
745 
746   Analysis.parseSectionContents(
747       {
748           0x0f, 0x0b, // 0x775e0e: ud2
749       },
750       {0x775e0e, 0x0});
751   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
752   SearchLengthForUndef = 1;
753   GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
754   EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
755             Analysis.validateCFIProtection(Result));
756   SearchLengthForUndef = 2;
757   Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
758   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
759             Analysis.validateCFIProtection(Result));
760   SearchLengthForUndef = 3;
761   Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
762   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
763             Analysis.validateCFIProtection(Result));
764   SearchLengthForUndef = PrevSearchLengthForUndef;
765 }
766 
767 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
768   if (!SuccessfullyInitialised)
769     GTEST_SKIP();
770   Analysis.parseSectionContents(
771       {
772           0x75, 0x02,                         // 0: jne 4 [+2]
773           0x0f, 0x0b,                         // 2: ud2
774           0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
775           0xff, 0x10,                         // 10: callq *(%rax)
776       },
777       {0xDEADBEEF, 0x0});
778   GraphResult Result =
779       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});
780   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
781             Analysis.validateCFIProtection(Result));
782 }
783 
784 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
785   if (!SuccessfullyInitialised)
786     GTEST_SKIP();
787   Analysis.parseSectionContents(
788       {
789           0x75, 0x02,             // 0: jne 4 [+2]
790           0x0f, 0x0b,             // 2: ud2
791           0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
792           0xff, 0x10,             // 8: callq *(%rax)
793       },
794       {0xDEADBEEF, 0x0});
795   GraphResult Result =
796       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
797   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
798             Analysis.validateCFIProtection(Result));
799 }
800 
801 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
802   if (!SuccessfullyInitialised)
803     GTEST_SKIP();
804   Analysis.parseSectionContents(
805       {
806           0x75, 0x02,                   // 0: jne 4 [+2]
807           0x0f, 0x0b,                   // 2: ud2
808           0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
809           0xff, 0x10,                   // 9: callq *(%rax)
810       },
811       {0xDEADBEEF, 0x0});
812   GraphResult Result =
813       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
814   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
815             Analysis.validateCFIProtection(Result));
816 }
817 
818 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
819   if (!SuccessfullyInitialised)
820     GTEST_SKIP();
821   Analysis.parseSectionContents(
822       {
823           0x75, 0x04, // 0: jne 6 [+4]
824           0x0f, 0x31, // 2: rdtsc (note: affects eax)
825           0xff, 0x10, // 4: callq *(%rax)
826           0x0f, 0x0b, // 6: ud2
827           0x75, 0xf9, // 8: jne 2 [-7]
828           0x0f, 0x0b, // 10: ud2
829       },
830       {0xDEADBEEF, 0x0});
831   GraphResult Result =
832       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
833   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
834             Analysis.validateCFIProtection(Result));
835 }
836 
837 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
838   if (!SuccessfullyInitialised)
839     GTEST_SKIP();
840   Analysis.parseSectionContents(
841       {
842           0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
843       },
844       {0xDEADBEEF, 0x0});
845   GraphResult Result =
846       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
847   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
848             Analysis.validateCFIProtection(Result));
849 }
850 
851 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
852   if (!SuccessfullyInitialised)
853     GTEST_SKIP();
854   Analysis.parseSectionContents(
855       {
856           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
857           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
858           0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
859       },
860       {0xDEADBEEF, 0x0});
861   GraphResult Result =
862       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
863   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
864             Analysis.validateCFIProtection(Result));
865 }
866 
867 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
868   if (!SuccessfullyInitialised)
869     GTEST_SKIP();
870   Analysis.parseSectionContents(
871       {
872           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
873           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
874           0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
875           0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
876       },
877       {0xDEADBEEF, 0x0});
878   GraphResult Result =
879       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
880   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
881             Analysis.validateCFIProtection(Result));
882 }
883 
884 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
885   if (!SuccessfullyInitialised)
886     GTEST_SKIP();
887   Analysis.parseSectionContents(
888       {
889           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
890           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
891           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
892           0x20, 0x00, 0x1f, 0xd6, // 12: br x1
893       },
894       {0xDEADBEEF, 0x0});
895   GraphResult Result =
896       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
897   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
898             Analysis.validateCFIProtection(Result));
899 }
900 
901 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
902   if (!SuccessfullyInitialised)
903     GTEST_SKIP();
904   Analysis.parseSectionContents(
905       {
906           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
907           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
908           0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
909           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
910           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
911       },
912       {0xDEADBEEF, 0x0});
913   GraphResult Result =
914       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
915   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
916             Analysis.validateCFIProtection(Result));
917 }
918 
919 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
920   if (!SuccessfullyInitialised)
921     GTEST_SKIP();
922   Analysis.parseSectionContents(
923       {
924           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
925           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
926           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
927           0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
928           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
929       },
930       {0xDEADBEEF, 0x0});
931   GraphResult Result =
932       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
933   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
934             Analysis.validateCFIProtection(Result));
935 }
936 
937 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
938   if (!SuccessfullyInitialised)
939     GTEST_SKIP();
940   Analysis.parseSectionContents(
941       {
942           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
943           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
944           0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
945           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
946           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
947       },
948       {0xDEADBEEF, 0x0});
949   GraphResult Result =
950       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
951   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
952             Analysis.validateCFIProtection(Result));
953 }
954 
955 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
956   if (!SuccessfullyInitialised)
957     GTEST_SKIP();
958   Analysis.parseSectionContents(
959       {
960           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
961           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
962           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
963           0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
964           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
965       },
966       {0xDEADBEEF, 0x0});
967   GraphResult Result =
968       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
969   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
970             Analysis.validateCFIProtection(Result));
971 }
972 
973 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
974   if (!SuccessfullyInitialised)
975     GTEST_SKIP();
976   Analysis.parseSectionContents(
977       {
978           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
979           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
980           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
981           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
982           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
983       },
984       {0xDEADBEEF, 0x0});
985   GraphResult Result =
986       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
987   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
988             Analysis.validateCFIProtection(Result));
989 }
990 
991 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
992   if (!SuccessfullyInitialised)
993     GTEST_SKIP();
994   Analysis.parseSectionContents(
995       {
996           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
997           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
998           0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
999           0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
1000           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
1001       },
1002       {0xDEADBEEF, 0x0});
1003   GraphResult Result =
1004       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
1005   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
1006             Analysis.validateCFIProtection(Result));
1007 }
1008 
1009 TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
1010   if (!SuccessfullyInitialised)
1011     GTEST_SKIP();
1012   Analysis.parseSectionContents(
1013       {
1014           0x03, 0x00, 0x00, 0x14, // 0: b 12
1015           0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
1016           0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
1017           0x20, 0x00, 0x1f, 0xd6, // 12: br x1
1018       },
1019       {0xDEADBEEF, 0x0});
1020   GraphResult Result =
1021       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
1022   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
1023             Analysis.validateCFIProtection(Result));
1024 }
1025 
1026 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
1027   if (!SuccessfullyInitialised)
1028     GTEST_SKIP();
1029   Analysis.parseSectionContents(
1030       {
1031           0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
1032           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1033           0x03, 0x00, 0x00, 0x14, // 8: b 12
1034           0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
1035           0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1036           0x20, 0x00, 0x1f, 0xd6, // 20: br x1
1037           0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
1038       },
1039       {0xDEADBEEF, 0x0});
1040   GraphResult Result =
1041       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});
1042   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
1043             Analysis.validateCFIProtection(Result));
1044 }
1045 
1046 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
1047   if (!SuccessfullyInitialised)
1048     GTEST_SKIP();
1049   Analysis.parseSectionContents(
1050       {
1051           0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1052           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1053           0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
1054           0x03, 0x00, 0x00, 0x14, // 12: b 12
1055           0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
1056           0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1057           0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1058           0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1059       },
1060       {0xDEADBEEF, 0x0});
1061   GraphResult Result =
1062       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
1063   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
1064             Analysis.validateCFIProtection(Result));
1065 }
1066 
1067 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
1068   if (!SuccessfullyInitialised)
1069     GTEST_SKIP();
1070   Analysis.parseSectionContents(
1071       {
1072           0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1073           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1074           0x03, 0x00, 0x00, 0x14, // 8: b 12
1075           0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
1076           0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1077           0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1078           0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1079           0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1080       },
1081       {0xDEADBEEF, 0x0});
1082   GraphResult Result =
1083       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
1084   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
1085             Analysis.validateCFIProtection(Result));
1086 }
1087 
1088 } // anonymous namespace
1089 } // end namespace cfi_verify
1090 } // end namespace llvm
1091 
1092 int main(int argc, char **argv) {
1093   ::testing::InitGoogleTest(&argc, argv);
1094   llvm::cl::ParseCommandLineOptions(argc, argv);
1095 
1096   llvm::InitializeAllTargetInfos();
1097   llvm::InitializeAllTargetMCs();
1098   llvm::InitializeAllAsmParsers();
1099   llvm::InitializeAllDisassemblers();
1100 
1101   return RUN_ALL_TESTS();
1102 }
1103