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