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