1 //===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
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
7 //===----------------------------------------------------------------------===//
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"
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"
41 using Instr
= ::llvm::cfi_verify::FileAnalysis::Instr
;
43 using ::testing::Field
;
46 namespace cfi_verify
{
48 class ELFTestFileAnalysis
: public FileAnalysis
{
50 ELFTestFileAnalysis(StringRef Trip
)
51 : FileAnalysis(Triple(Trip
), SubtargetFeatures()) {}
53 // Expose this method publicly for testing.
54 void parseSectionContents(ArrayRef
<uint8_t> SectionBytes
,
55 object::SectionedAddress Address
) {
56 FileAnalysis::parseSectionContents(SectionBytes
, Address
);
59 Error
initialiseDisassemblyMembers() {
60 return FileAnalysis::initialiseDisassemblyMembers();
64 class BasicFileAnalysisTest
: public ::testing::Test
{
66 BasicFileAnalysisTest(StringRef Trip
)
67 : SuccessfullyInitialised(false), Analysis(Trip
) {}
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;
76 << "Note: CFIVerifyTests are disabled due to lack of support "
82 bool SuccessfullyInitialised
;
83 ELFTestFileAnalysis Analysis
;
86 class BasicX86FileAnalysisTest
: public BasicFileAnalysisTest
{
88 BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
91 class BasicAArch64FileAnalysisTest
: public BasicFileAnalysisTest
{
93 BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
96 TEST_F(BasicX86FileAnalysisTest
, BasicDisassemblyTraversalTest
) {
97 if (!SuccessfullyInitialised
)
99 Analysis
.parseSectionContents(
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
108 0x41, 0x0e, // 21: rex.B (bad)
109 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
113 EXPECT_EQ(nullptr, Analysis
.getInstruction(0x0));
114 EXPECT_EQ(nullptr, Analysis
.getInstruction(0x1000));
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
);
123 const auto *NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
124 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
125 const auto *PrevInstrMeta
= InstrMeta
;
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
);
135 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
136 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
137 PrevInstrMeta
= InstrMeta
;
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
);
147 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
148 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
149 PrevInstrMeta
= InstrMeta
;
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
);
159 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
160 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
161 PrevInstrMeta
= InstrMeta
;
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
);
171 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
172 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
173 PrevInstrMeta
= InstrMeta
;
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
);
182 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
183 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
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
);
192 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
193 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
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
);
202 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
203 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
206 TEST_F(BasicX86FileAnalysisTest
, PrevAndNextFromBadInst
) {
207 if (!SuccessfullyInitialised
)
209 Analysis
.parseSectionContents(
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
);
223 GoodInstrMeta
= Analysis
.getNextInstructionSequential(BadInstrMeta
);
224 EXPECT_NE(nullptr, GoodInstrMeta
);
225 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta
->VMAddress
);
226 EXPECT_EQ(1u, GoodInstrMeta
->InstructionSize
);
229 TEST_F(BasicX86FileAnalysisTest
, CFITrapTest
) {
230 if (!SuccessfullyInitialised
)
232 Analysis
.parseSectionContents(
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
241 0x41, 0x0e, // 21: rex.B (bad)
242 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
243 0x0f, 0x0b // 28: ud2
247 EXPECT_FALSE(Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF)));
249 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 3)));
251 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 6)));
253 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 10)));
255 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 20)));
257 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 21)));
259 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 23)));
261 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 28)));
264 TEST_F(BasicX86FileAnalysisTest
, FallThroughTest
) {
265 if (!SuccessfullyInitialised
)
267 Analysis
.parseSectionContents(
270 0xb0, 0x00, // 1: mov $0x0, %al
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
283 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF)));
285 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 1)));
287 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 3)));
289 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 4)));
291 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 6)));
293 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 8)));
295 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 10)));
297 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 15)));
299 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 17)));
301 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 19)));
304 TEST_F(BasicX86FileAnalysisTest
, DefiniteNextInstructionTest
) {
305 if (!SuccessfullyInitialised
)
307 Analysis
.parseSectionContents(
310 0xb0, 0x00, // 1: mov $0x0, %al
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]
323 0xeb, 0xdd, // 34: jmp 1 [-35]
324 0xeb, 0xdd, // 36: jmp 3 [-35]
325 0xeb, 0xdc, // 38: jmp 4 [-36]
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
);
334 Current
= Analysis
.getInstruction(0xDEADBEEF + 1);
335 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
337 Current
= Analysis
.getInstruction(0xDEADBEEF + 3);
338 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
340 Current
= Analysis
.getInstruction(0xDEADBEEF + 4);
341 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
343 Current
= Analysis
.getInstruction(0xDEADBEEF + 6);
344 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
346 Current
= Analysis
.getInstruction(0xDEADBEEF + 8);
347 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
348 EXPECT_NE(nullptr, Next
);
349 EXPECT_EQ(0xDEADBEEF + 10, Next
->VMAddress
);
351 Current
= Analysis
.getInstruction(0xDEADBEEF + 10);
352 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
353 EXPECT_NE(nullptr, Next
);
354 EXPECT_EQ(0xDEADBEEF + 17, Next
->VMAddress
);
356 Current
= Analysis
.getInstruction(0xDEADBEEF + 12);
357 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
358 EXPECT_NE(nullptr, Next
);
359 EXPECT_EQ(0xDEADBEEF + 17, Next
->VMAddress
);
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
);
366 Current
= Analysis
.getInstruction(0xDEADBEEF + 22);
367 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
368 EXPECT_NE(nullptr, Next
);
369 EXPECT_EQ(0xDEADBEEF + 31, Next
->VMAddress
);
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
));
380 Current
= Analysis
.getInstruction(0xDEADBEEF + 34);
381 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
382 EXPECT_NE(nullptr, Next
);
383 EXPECT_EQ(0xDEADBEEF + 1, Next
->VMAddress
);
385 Current
= Analysis
.getInstruction(0xDEADBEEF + 36);
386 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
388 Current
= Analysis
.getInstruction(0xDEADBEEF + 38);
389 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
390 EXPECT_NE(nullptr, Next
);
391 EXPECT_EQ(0xDEADBEEF + 4, Next
->VMAddress
);
394 TEST_F(BasicX86FileAnalysisTest
, ControlFlowXRefsTest
) {
395 if (!SuccessfullyInitialised
)
397 Analysis
.parseSectionContents(
400 0xb0, 0x00, // 1: mov $0x0, %al
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]
413 0xeb, 0xdd, // 34: jmp 1 [-35]
414 0xeb, 0xdd, // 36: jmp 3 [-35]
415 0xeb, 0xdc, // 38: jmp 4 [-36]
418 const auto *InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF);
419 std::set
<const Instr
*> XRefs
=
420 Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
421 EXPECT_TRUE(XRefs
.empty());
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))));
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))));
436 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 4);
437 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
438 EXPECT_THAT(XRefs
, UnorderedElementsAre(
439 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 38))));
441 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 6);
442 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
444 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 8);
445 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
446 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
448 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 10);
449 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
450 EXPECT_THAT(XRefs
, UnorderedElementsAre(
451 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 8))));
453 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 12);
454 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
455 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
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))));
463 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 22);
464 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
465 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
467 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 27);
468 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
469 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
471 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 29);
472 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
473 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
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))));
481 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 33);
482 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
483 EXPECT_THAT(XRefs
, UnorderedElementsAre(
484 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 31))));
486 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 34);
487 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
488 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
490 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 36);
491 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
492 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
494 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 38);
495 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
496 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
499 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionInvalidTargets
) {
500 if (!SuccessfullyInitialised
)
502 Analysis
.parseSectionContents(
505 0x0f, 0x0b, // 1: ud2
506 0x75, 0x00, // 3: jne 5 [+0]
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
));
524 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicFallthroughToUd2
) {
525 if (!SuccessfullyInitialised
)
527 Analysis
.parseSectionContents(
529 0x75, 0x02, // 0: jne 4 [+2]
530 0x0f, 0x0b, // 2: ud2
531 0xff, 0x10, // 4: callq *(%rax)
535 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
536 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
537 Analysis
.validateCFIProtection(Result
));
540 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicJumpToUd2
) {
541 if (!SuccessfullyInitialised
)
543 Analysis
.parseSectionContents(
545 0x75, 0x02, // 0: jne 4 [+2]
546 0xff, 0x10, // 2: callq *(%rax)
547 0x0f, 0x0b, // 4: ud2
551 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 2, 0x0});
552 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
553 Analysis
.validateCFIProtection(Result
));
556 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathUd2
) {
557 if (!SuccessfullyInitialised
)
559 Analysis
.parseSectionContents(
561 0x75, 0x03, // 0: jne 5 [+3]
563 0xff, 0x10, // 3: callq *(%rax)
564 0x0f, 0x0b, // 5: ud2
565 0x75, 0xf9, // 7: jne 2 [-7]
566 0x0f, 0x0b, // 9: ud2
570 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 3, 0x0});
571 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
572 Analysis
.validateCFIProtection(Result
));
575 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathSingleUd2
) {
576 if (!SuccessfullyInitialised
)
578 Analysis
.parseSectionContents(
580 0x75, 0x05, // 0: jne 7 [+5]
582 0xff, 0x10, // 3: callq *(%rax)
583 0x75, 0xfb, // 5: jne 2 [-5]
584 0x0f, 0x0b, // 7: ud2
588 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 3, 0x0});
589 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
590 Analysis
.validateCFIProtection(Result
));
593 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitUpwards
) {
594 if (!SuccessfullyInitialised
)
596 Analysis
.parseSectionContents(
598 0x75, 0x06, // 0: jne 8 [+6]
603 0xff, 0x10, // 6: callq *(%rax)
604 0x0f, 0x0b, // 8: ud2
607 uint64_t PrevSearchLengthForConditionalBranch
=
608 SearchLengthForConditionalBranch
;
609 SearchLengthForConditionalBranch
= 2;
612 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 6, 0x0});
613 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
614 Analysis
.validateCFIProtection(Result
));
616 SearchLengthForConditionalBranch
= PrevSearchLengthForConditionalBranch
;
619 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitDownwards
) {
620 if (!SuccessfullyInitialised
)
622 Analysis
.parseSectionContents(
624 0x75, 0x02, // 0: jne 4 [+2]
625 0xff, 0x10, // 2: callq *(%rax)
630 0x0f, 0x0b, // 8: ud2
633 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
634 SearchLengthForUndef
= 2;
637 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 2, 0x0});
638 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH
,
639 Analysis
.validateCFIProtection(Result
));
641 SearchLengthForUndef
= PrevSearchLengthForUndef
;
644 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionGoodAndBadPaths
) {
645 if (!SuccessfullyInitialised
)
647 Analysis
.parseSectionContents(
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
656 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
657 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
658 Analysis
.validateCFIProtection(Result
));
661 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionWithUnconditionalJumpInFallthrough
) {
662 if (!SuccessfullyInitialised
)
664 Analysis
.parseSectionContents(
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
673 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
674 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
675 Analysis
.validateCFIProtection(Result
));
678 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionComplexExample
) {
679 if (!SuccessfullyInitialised
)
681 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
683 Analysis
.parseSectionContents(
685 0x75, 0x12, // 0: jne 20 [+18]
686 0xeb, 0x03, // 2: jmp 7 [+3]
687 0x75, 0x10, // 4: jne 22 [+16]
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]
697 0x0f, 0x0b, // 22: ud2
700 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
701 SearchLengthForUndef
= 5;
703 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 9, 0x0});
704 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
705 Analysis
.validateCFIProtection(Result
));
706 SearchLengthForUndef
= PrevSearchLengthForUndef
;
709 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTest
) {
710 if (!SuccessfullyInitialised
)
712 Analysis
.parseSectionContents(
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
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
;
730 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTestFarAway
) {
731 if (!SuccessfullyInitialised
)
733 Analysis
.parseSectionContents(
735 0x74, 0x73, // 0x7759eb: je 0x775a60
736 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
740 Analysis
.parseSectionContents(
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
750 Analysis
.parseSectionContents(
752 0x0f, 0x0b, // 0x775e0e: ud2
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
;
771 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit
) {
772 if (!SuccessfullyInitialised
)
774 Analysis
.parseSectionContents(
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)
783 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 10, 0x0});
784 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
785 Analysis
.validateCFIProtection(Result
));
788 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit2
) {
789 if (!SuccessfullyInitialised
)
791 Analysis
.parseSectionContents(
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)
800 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 8, 0x0});
801 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
802 Analysis
.validateCFIProtection(Result
));
805 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathImplicit
) {
806 if (!SuccessfullyInitialised
)
808 Analysis
.parseSectionContents(
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)
817 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 9, 0x0});
818 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
819 Analysis
.validateCFIProtection(Result
));
822 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberDualPathImplicit
) {
823 if (!SuccessfullyInitialised
)
825 Analysis
.parseSectionContents(
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
836 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
837 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
838 Analysis
.validateCFIProtection(Result
));
841 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicUnprotected
) {
842 if (!SuccessfullyInitialised
)
844 Analysis
.parseSectionContents(
846 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
850 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF, 0x0});
851 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
852 Analysis
.validateCFIProtection(Result
));
855 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicProtected
) {
856 if (!SuccessfullyInitialised
)
858 Analysis
.parseSectionContents(
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
866 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 8, 0x0});
867 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
868 Analysis
.validateCFIProtection(Result
));
871 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberBasic
) {
872 if (!SuccessfullyInitialised
)
874 Analysis
.parseSectionContents(
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
883 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
884 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
885 Analysis
.validateCFIProtection(Result
));
888 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberOneLoad
) {
889 if (!SuccessfullyInitialised
)
891 Analysis
.parseSectionContents(
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
900 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
901 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
902 Analysis
.validateCFIProtection(Result
));
905 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddGood
) {
906 if (!SuccessfullyInitialised
)
908 Analysis
.parseSectionContents(
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
918 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
919 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
920 Analysis
.validateCFIProtection(Result
));
923 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad
) {
924 if (!SuccessfullyInitialised
)
926 Analysis
.parseSectionContents(
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
936 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
937 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
938 Analysis
.validateCFIProtection(Result
));
941 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad2
) {
942 if (!SuccessfullyInitialised
)
944 Analysis
.parseSectionContents(
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
954 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
955 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
956 Analysis
.validateCFIProtection(Result
));
959 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberTwoLoads
) {
960 if (!SuccessfullyInitialised
)
962 Analysis
.parseSectionContents(
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
972 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
973 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
974 Analysis
.validateCFIProtection(Result
));
977 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedSecondLoad
) {
978 if (!SuccessfullyInitialised
)
980 Analysis
.parseSectionContents(
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
990 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
991 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
992 Analysis
.validateCFIProtection(Result
));
995 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedLoads
) {
996 if (!SuccessfullyInitialised
)
998 Analysis
.parseSectionContents(
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
1007 GraphResult Result
=
1008 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
1009 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
1010 Analysis
.validateCFIProtection(Result
));
1013 TEST_F(BasicAArch64FileAnalysisTest
, AArch64GoodAndBadPaths
) {
1014 if (!SuccessfullyInitialised
)
1016 Analysis
.parseSectionContents(
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
1024 GraphResult Result
=
1025 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
1026 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
1027 Analysis
.validateCFIProtection(Result
));
1030 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPaths
) {
1031 if (!SuccessfullyInitialised
)
1033 Analysis
.parseSectionContents(
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
1044 GraphResult Result
=
1045 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 20, 0x0});
1046 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
1047 Analysis
.validateCFIProtection(Result
));
1050 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad1
) {
1051 if (!SuccessfullyInitialised
)
1053 Analysis
.parseSectionContents(
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
1065 GraphResult Result
=
1066 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 24, 0x0});
1067 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1068 Analysis
.validateCFIProtection(Result
));
1071 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad2
) {
1072 if (!SuccessfullyInitialised
)
1074 Analysis
.parseSectionContents(
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
1086 GraphResult Result
=
1087 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 24, 0x0});
1088 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1089 Analysis
.validateCFIProtection(Result
));
1092 } // anonymous namespace
1093 } // end namespace cfi_verify
1094 } // end namespace llvm
1096 int main(int argc
, char **argv
) {
1097 ::testing::InitGoogleTest(&argc
, argv
);
1098 llvm::cl::ParseCommandLineOptions(argc
, argv
);
1100 llvm::InitializeAllTargetInfos();
1101 llvm::InitializeAllTargetMCs();
1102 llvm::InitializeAllAsmParsers();
1103 llvm::InitializeAllDisassemblers();
1105 return RUN_ALL_TESTS();