xref: /llvm-project/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp (revision e6e69f3bd4b848da8c34e4418812c25fc8749950)
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:
ELFTestFileAnalysis(StringRef Trip)50   ELFTestFileAnalysis(StringRef Trip)
51       : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}
52 
53   // Expose this method publicly for testing.
parseSectionContents(ArrayRef<uint8_t> SectionBytes,object::SectionedAddress Address)54   void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
55                             object::SectionedAddress Address) {
56     FileAnalysis::parseSectionContents(SectionBytes, Address);
57   }
58 
initialiseDisassemblyMembers()59   Error initialiseDisassemblyMembers() {
60     return FileAnalysis::initialiseDisassemblyMembers();
61   }
62 };
63 
64 class BasicFileAnalysisTest : public ::testing::Test {
65 public:
BasicFileAnalysisTest(StringRef Trip)66   BasicFileAnalysisTest(StringRef Trip)
67       : SuccessfullyInitialised(false), Analysis(Trip) {}
68 protected:
SetUp()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:
BasicX86FileAnalysisTest()88   BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
89 };
90 
91 class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
92 public:
BasicAArch64FileAnalysisTest()93   BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
94 };
95 
TEST_F(BasicX86FileAnalysisTest,BasicDisassemblyTraversalTest)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 
TEST_F(BasicX86FileAnalysisTest,PrevAndNextFromBadInst)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 
TEST_F(BasicX86FileAnalysisTest,CFITrapTest)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 
TEST_F(BasicX86FileAnalysisTest,FallThroughTest)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 
TEST_F(BasicX86FileAnalysisTest,DefiniteNextInstructionTest)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 
TEST_F(BasicX86FileAnalysisTest,ControlFlowXRefsTest)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionInvalidTargets)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionBasicFallthroughToUd2)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionBasicJumpToUd2)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionDualPathUd2)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionDualPathSingleUd2)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionDualFailLimitUpwards)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionDualFailLimitDownwards)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionGoodAndBadPaths)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionWithUnconditionalJumpInFallthrough)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 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionComplexExample)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 
TEST_F(BasicX86FileAnalysisTest,UndefSearchLengthOneTest)709 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
710   if (!SuccessfullyInitialised)
711     GTEST_SKIP();
712   Analysis.parseSectionContents(
713       {
714           0x77, 0x0d,                   // 0x688118: ja 0x688127 [+12]
715           0x48, 0x89, 0xdf,             // 0x68811a: mov %rbx, %rdi
716           0xff, 0xd0,                   // 0x68811d: callq *%rax
717           0x48, 0x89, 0xdf,             // 0x68811f: mov %rbx, %rdi
718           0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
719           0x0f, 0x0b,                   // 0x688127: ud2
720       },
721       {0x688118, 0x0});
722   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
723   SearchLengthForUndef = 1;
724   GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});
725   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
726             Analysis.validateCFIProtection(Result));
727   SearchLengthForUndef = PrevSearchLengthForUndef;
728 }
729 
TEST_F(BasicX86FileAnalysisTest,UndefSearchLengthOneTestFarAway)730 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
731   if (!SuccessfullyInitialised)
732     GTEST_SKIP();
733   Analysis.parseSectionContents(
734       {
735           0x74, 0x73,                         // 0x7759eb: je 0x775a60
736           0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
737       },
738       {0x7759eb, 0x0});
739 
740   Analysis.parseSectionContents(
741       {
742           0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne    0x775e0e
743           0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add    $0xfffffffffffffff4,%rbx
744           0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov    0x10(%rsp),%rdi
745           0x48, 0x89, 0xde,             // 0x775a65: mov    %rbx,%rsi
746           0xff, 0xd1,                   // 0x775a68: callq  *%rcx
747       },
748       {0x775a56, 0x0});
749 
750   Analysis.parseSectionContents(
751       {
752           0x0f, 0x0b, // 0x775e0e: ud2
753       },
754       {0x775e0e, 0x0});
755   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
756   SearchLengthForUndef = 1;
757   GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
758   EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
759             Analysis.validateCFIProtection(Result));
760   SearchLengthForUndef = 2;
761   Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
762   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
763             Analysis.validateCFIProtection(Result));
764   SearchLengthForUndef = 3;
765   Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
766   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
767             Analysis.validateCFIProtection(Result));
768   SearchLengthForUndef = PrevSearchLengthForUndef;
769 }
770 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionClobberSinglePathExplicit)771 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
772   if (!SuccessfullyInitialised)
773     GTEST_SKIP();
774   Analysis.parseSectionContents(
775       {
776           0x75, 0x02,                         // 0: jne 4 [+2]
777           0x0f, 0x0b,                         // 2: ud2
778           0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
779           0xff, 0x10,                         // 10: callq *(%rax)
780       },
781       {0xDEADBEEF, 0x0});
782   GraphResult Result =
783       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});
784   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
785             Analysis.validateCFIProtection(Result));
786 }
787 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionClobberSinglePathExplicit2)788 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
789   if (!SuccessfullyInitialised)
790     GTEST_SKIP();
791   Analysis.parseSectionContents(
792       {
793           0x75, 0x02,             // 0: jne 4 [+2]
794           0x0f, 0x0b,             // 2: ud2
795           0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
796           0xff, 0x10,             // 8: callq *(%rax)
797       },
798       {0xDEADBEEF, 0x0});
799   GraphResult Result =
800       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
801   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
802             Analysis.validateCFIProtection(Result));
803 }
804 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionClobberSinglePathImplicit)805 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
806   if (!SuccessfullyInitialised)
807     GTEST_SKIP();
808   Analysis.parseSectionContents(
809       {
810           0x75, 0x02,                   // 0: jne 4 [+2]
811           0x0f, 0x0b,                   // 2: ud2
812           0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
813           0xff, 0x10,                   // 9: callq *(%rax)
814       },
815       {0xDEADBEEF, 0x0});
816   GraphResult Result =
817       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
818   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
819             Analysis.validateCFIProtection(Result));
820 }
821 
TEST_F(BasicX86FileAnalysisTest,CFIProtectionClobberDualPathImplicit)822 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
823   if (!SuccessfullyInitialised)
824     GTEST_SKIP();
825   Analysis.parseSectionContents(
826       {
827           0x75, 0x04, // 0: jne 6 [+4]
828           0x0f, 0x31, // 2: rdtsc (note: affects eax)
829           0xff, 0x10, // 4: callq *(%rax)
830           0x0f, 0x0b, // 6: ud2
831           0x75, 0xf9, // 8: jne 2 [-7]
832           0x0f, 0x0b, // 10: ud2
833       },
834       {0xDEADBEEF, 0x0});
835   GraphResult Result =
836       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
837   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
838             Analysis.validateCFIProtection(Result));
839 }
840 
TEST_F(BasicAArch64FileAnalysisTest,AArch64BasicUnprotected)841 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
842   if (!SuccessfullyInitialised)
843     GTEST_SKIP();
844   Analysis.parseSectionContents(
845       {
846           0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
847       },
848       {0xDEADBEEF, 0x0});
849   GraphResult Result =
850       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
851   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
852             Analysis.validateCFIProtection(Result));
853 }
854 
TEST_F(BasicAArch64FileAnalysisTest,AArch64BasicProtected)855 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
856   if (!SuccessfullyInitialised)
857     GTEST_SKIP();
858   Analysis.parseSectionContents(
859       {
860           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
861           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
862           0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
863       },
864       {0xDEADBEEF, 0x0});
865   GraphResult Result =
866       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
867   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
868             Analysis.validateCFIProtection(Result));
869 }
870 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberBasic)871 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
872   if (!SuccessfullyInitialised)
873     GTEST_SKIP();
874   Analysis.parseSectionContents(
875       {
876           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
877           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
878           0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
879           0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
880       },
881       {0xDEADBEEF, 0x0});
882   GraphResult Result =
883       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
884   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
885             Analysis.validateCFIProtection(Result));
886 }
887 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberOneLoad)888 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
889   if (!SuccessfullyInitialised)
890     GTEST_SKIP();
891   Analysis.parseSectionContents(
892       {
893           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
894           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
895           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
896           0x20, 0x00, 0x1f, 0xd6, // 12: br x1
897       },
898       {0xDEADBEEF, 0x0});
899   GraphResult Result =
900       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
901   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
902             Analysis.validateCFIProtection(Result));
903 }
904 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberLoadAddGood)905 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
906   if (!SuccessfullyInitialised)
907     GTEST_SKIP();
908   Analysis.parseSectionContents(
909       {
910           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
911           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
912           0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
913           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
914           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
915       },
916       {0xDEADBEEF, 0x0});
917   GraphResult Result =
918       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
919   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
920             Analysis.validateCFIProtection(Result));
921 }
922 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberLoadAddBad)923 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
924   if (!SuccessfullyInitialised)
925     GTEST_SKIP();
926   Analysis.parseSectionContents(
927       {
928           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
929           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
930           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
931           0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
932           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
933       },
934       {0xDEADBEEF, 0x0});
935   GraphResult Result =
936       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
937   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
938             Analysis.validateCFIProtection(Result));
939 }
940 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberLoadAddBad2)941 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
942   if (!SuccessfullyInitialised)
943     GTEST_SKIP();
944   Analysis.parseSectionContents(
945       {
946           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
947           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
948           0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
949           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
950           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
951       },
952       {0xDEADBEEF, 0x0});
953   GraphResult Result =
954       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
955   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
956             Analysis.validateCFIProtection(Result));
957 }
958 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberTwoLoads)959 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
960   if (!SuccessfullyInitialised)
961     GTEST_SKIP();
962   Analysis.parseSectionContents(
963       {
964           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
965           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
966           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
967           0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
968           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
969       },
970       {0xDEADBEEF, 0x0});
971   GraphResult Result =
972       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
973   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
974             Analysis.validateCFIProtection(Result));
975 }
976 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberUnrelatedSecondLoad)977 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
978   if (!SuccessfullyInitialised)
979     GTEST_SKIP();
980   Analysis.parseSectionContents(
981       {
982           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
983           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
984           0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
985           0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
986           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
987       },
988       {0xDEADBEEF, 0x0});
989   GraphResult Result =
990       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
991   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
992             Analysis.validateCFIProtection(Result));
993 }
994 
TEST_F(BasicAArch64FileAnalysisTest,AArch64ClobberUnrelatedLoads)995 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
996   if (!SuccessfullyInitialised)
997     GTEST_SKIP();
998   Analysis.parseSectionContents(
999       {
1000           0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
1001           0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
1002           0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
1003           0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
1004           0x20, 0x00, 0x1f, 0xd6, // 16: br x1
1005       },
1006       {0xDEADBEEF, 0x0});
1007   GraphResult Result =
1008       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
1009   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
1010             Analysis.validateCFIProtection(Result));
1011 }
1012 
TEST_F(BasicAArch64FileAnalysisTest,AArch64GoodAndBadPaths)1013 TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
1014   if (!SuccessfullyInitialised)
1015     GTEST_SKIP();
1016   Analysis.parseSectionContents(
1017       {
1018           0x03, 0x00, 0x00, 0x14, // 0: b 12
1019           0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
1020           0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
1021           0x20, 0x00, 0x1f, 0xd6, // 12: br x1
1022       },
1023       {0xDEADBEEF, 0x0});
1024   GraphResult Result =
1025       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
1026   EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
1027             Analysis.validateCFIProtection(Result));
1028 }
1029 
TEST_F(BasicAArch64FileAnalysisTest,AArch64TwoPaths)1030 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
1031   if (!SuccessfullyInitialised)
1032     GTEST_SKIP();
1033   Analysis.parseSectionContents(
1034       {
1035           0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
1036           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1037           0x03, 0x00, 0x00, 0x14, // 8: b 12
1038           0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
1039           0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1040           0x20, 0x00, 0x1f, 0xd6, // 20: br x1
1041           0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
1042       },
1043       {0xDEADBEEF, 0x0});
1044   GraphResult Result =
1045       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});
1046   EXPECT_EQ(CFIProtectionStatus::PROTECTED,
1047             Analysis.validateCFIProtection(Result));
1048 }
1049 
TEST_F(BasicAArch64FileAnalysisTest,AArch64TwoPathsBadLoad1)1050 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
1051   if (!SuccessfullyInitialised)
1052     GTEST_SKIP();
1053   Analysis.parseSectionContents(
1054       {
1055           0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1056           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1057           0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
1058           0x03, 0x00, 0x00, 0x14, // 12: b 12
1059           0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
1060           0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1061           0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1062           0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1063       },
1064       {0xDEADBEEF, 0x0});
1065   GraphResult Result =
1066       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
1067   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
1068             Analysis.validateCFIProtection(Result));
1069 }
1070 
TEST_F(BasicAArch64FileAnalysisTest,AArch64TwoPathsBadLoad2)1071 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
1072   if (!SuccessfullyInitialised)
1073     GTEST_SKIP();
1074   Analysis.parseSectionContents(
1075       {
1076           0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1077           0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1078           0x03, 0x00, 0x00, 0x14, // 8: b 12
1079           0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
1080           0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1081           0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1082           0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1083           0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1084       },
1085       {0xDEADBEEF, 0x0});
1086   GraphResult Result =
1087       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
1088   EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
1089             Analysis.validateCFIProtection(Result));
1090 }
1091 
1092 } // anonymous namespace
1093 } // end namespace cfi_verify
1094 } // end namespace llvm
1095 
main(int argc,char ** argv)1096 int main(int argc, char **argv) {
1097   ::testing::InitGoogleTest(&argc, argv);
1098   llvm::cl::ParseCommandLineOptions(argc, argv);
1099 
1100   llvm::InitializeAllTargetInfos();
1101   llvm::InitializeAllTargetMCs();
1102   llvm::InitializeAllAsmParsers();
1103   llvm::InitializeAllDisassemblers();
1104 
1105   return RUN_ALL_TESTS();
1106 }
1107