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