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/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"
40 using Instr
= ::llvm::cfi_verify::FileAnalysis::Instr
;
42 using ::testing::Field
;
45 namespace cfi_verify
{
47 class ELFTestFileAnalysis
: public FileAnalysis
{
49 ELFTestFileAnalysis(StringRef Trip
)
50 : FileAnalysis(Triple(Trip
), SubtargetFeatures()) {}
52 // Expose this method publicly for testing.
53 void parseSectionContents(ArrayRef
<uint8_t> SectionBytes
,
54 object::SectionedAddress Address
) {
55 FileAnalysis::parseSectionContents(SectionBytes
, Address
);
58 Error
initialiseDisassemblyMembers() {
59 return FileAnalysis::initialiseDisassemblyMembers();
63 class BasicFileAnalysisTest
: public ::testing::Test
{
65 BasicFileAnalysisTest(StringRef Trip
) : Analysis(Trip
) {}
67 virtual void SetUp() {
68 IgnoreDWARFFlag
= true;
69 SuccessfullyInitialised
= true;
70 if (auto Err
= Analysis
.initialiseDisassemblyMembers()) {
71 handleAllErrors(std::move(Err
), [&](const UnsupportedDisassembly
&E
) {
72 SuccessfullyInitialised
= false;
74 << "Note: CFIVerifyTests are disabled due to lack of support "
80 bool SuccessfullyInitialised
;
81 ELFTestFileAnalysis Analysis
;
84 class BasicX86FileAnalysisTest
: public BasicFileAnalysisTest
{
86 BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
89 class BasicAArch64FileAnalysisTest
: public BasicFileAnalysisTest
{
91 BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
94 TEST_F(BasicX86FileAnalysisTest
, BasicDisassemblyTraversalTest
) {
95 if (!SuccessfullyInitialised
)
97 Analysis
.parseSectionContents(
100 0xb0, 0x00, // 1: mov $0x0, %al
101 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
102 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
103 0x48, 0xbe, 0xc4, 0x07, 0x40,
104 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
106 0x41, 0x0e, // 21: rex.B (bad)
107 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
111 EXPECT_EQ(nullptr, Analysis
.getInstruction(0x0));
112 EXPECT_EQ(nullptr, Analysis
.getInstruction(0x1000));
115 const auto *InstrMeta
= Analysis
.getInstruction(0xDEADBEEF);
116 EXPECT_NE(nullptr, InstrMeta
);
117 EXPECT_EQ(0xDEADBEEF, InstrMeta
->VMAddress
);
118 EXPECT_EQ(1u, InstrMeta
->InstructionSize
);
119 EXPECT_TRUE(InstrMeta
->Valid
);
121 const auto *NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
122 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
123 const auto *PrevInstrMeta
= InstrMeta
;
125 // 0xDEADBEEF + 1: mov $0x0, %al
126 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 1);
127 EXPECT_NE(nullptr, InstrMeta
);
128 EXPECT_EQ(NextInstrMeta
, InstrMeta
);
129 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta
->VMAddress
);
130 EXPECT_EQ(2u, InstrMeta
->InstructionSize
);
131 EXPECT_TRUE(InstrMeta
->Valid
);
133 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
134 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
135 PrevInstrMeta
= InstrMeta
;
137 // 0xDEADBEEF + 3: mov %rsp, %rbp
138 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 3);
139 EXPECT_NE(nullptr, InstrMeta
);
140 EXPECT_EQ(NextInstrMeta
, InstrMeta
);
141 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta
->VMAddress
);
142 EXPECT_EQ(3u, InstrMeta
->InstructionSize
);
143 EXPECT_TRUE(InstrMeta
->Valid
);
145 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
146 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
147 PrevInstrMeta
= InstrMeta
;
149 // 0xDEADBEEF + 6: sub $0x18, %rsp
150 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 6);
151 EXPECT_NE(nullptr, InstrMeta
);
152 EXPECT_EQ(NextInstrMeta
, InstrMeta
);
153 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta
->VMAddress
);
154 EXPECT_EQ(4u, InstrMeta
->InstructionSize
);
155 EXPECT_TRUE(InstrMeta
->Valid
);
157 NextInstrMeta
= Analysis
.getNextInstructionSequential(*InstrMeta
);
158 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
159 PrevInstrMeta
= InstrMeta
;
161 // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
162 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 10);
163 EXPECT_NE(nullptr, InstrMeta
);
164 EXPECT_EQ(NextInstrMeta
, InstrMeta
);
165 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta
->VMAddress
);
166 EXPECT_EQ(10u, InstrMeta
->InstructionSize
);
167 EXPECT_TRUE(InstrMeta
->Valid
);
169 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
170 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
171 PrevInstrMeta
= InstrMeta
;
173 // 0xDEADBEEF + 20: (bad)
174 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 20);
175 EXPECT_NE(nullptr, InstrMeta
);
176 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta
->VMAddress
);
177 EXPECT_EQ(1u, InstrMeta
->InstructionSize
);
178 EXPECT_FALSE(InstrMeta
->Valid
);
180 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
181 EXPECT_EQ(PrevInstrMeta
, Analysis
.getPrevInstructionSequential(*InstrMeta
));
183 // 0xDEADBEEF + 21: rex.B (bad)
184 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 21);
185 EXPECT_NE(nullptr, InstrMeta
);
186 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta
->VMAddress
);
187 EXPECT_EQ(2u, InstrMeta
->InstructionSize
);
188 EXPECT_FALSE(InstrMeta
->Valid
);
190 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
191 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
193 // 0xDEADBEEF + 6: (bad) {%k1}
194 InstrMeta
= Analysis
.getInstruction(0xDEADBEEF + 23);
195 EXPECT_NE(nullptr, InstrMeta
);
196 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta
->VMAddress
);
197 EXPECT_EQ(5u, InstrMeta
->InstructionSize
);
198 EXPECT_FALSE(InstrMeta
->Valid
);
200 EXPECT_EQ(nullptr, Analysis
.getNextInstructionSequential(*InstrMeta
));
201 EXPECT_EQ(nullptr, Analysis
.getPrevInstructionSequential(*InstrMeta
));
204 TEST_F(BasicX86FileAnalysisTest
, PrevAndNextFromBadInst
) {
205 if (!SuccessfullyInitialised
)
207 Analysis
.parseSectionContents(
214 const auto &BadInstrMeta
= Analysis
.getInstructionOrDie(0xDEADBEEF + 1);
215 const auto *GoodInstrMeta
=
216 Analysis
.getPrevInstructionSequential(BadInstrMeta
);
217 EXPECT_NE(nullptr, GoodInstrMeta
);
218 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta
->VMAddress
);
219 EXPECT_EQ(1u, GoodInstrMeta
->InstructionSize
);
221 GoodInstrMeta
= Analysis
.getNextInstructionSequential(BadInstrMeta
);
222 EXPECT_NE(nullptr, GoodInstrMeta
);
223 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta
->VMAddress
);
224 EXPECT_EQ(1u, GoodInstrMeta
->InstructionSize
);
227 TEST_F(BasicX86FileAnalysisTest
, CFITrapTest
) {
228 if (!SuccessfullyInitialised
)
230 Analysis
.parseSectionContents(
233 0xb0, 0x00, // 1: mov $0x0, %al
234 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
235 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
236 0x48, 0xbe, 0xc4, 0x07, 0x40,
237 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
239 0x41, 0x0e, // 21: rex.B (bad)
240 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
241 0x0f, 0x0b // 28: ud2
245 EXPECT_FALSE(Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF)));
247 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 3)));
249 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 6)));
251 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 10)));
253 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 20)));
255 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 21)));
257 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 23)));
259 Analysis
.isCFITrap(Analysis
.getInstructionOrDie(0xDEADBEEF + 28)));
262 TEST_F(BasicX86FileAnalysisTest
, FallThroughTest
) {
263 if (!SuccessfullyInitialised
)
265 Analysis
.parseSectionContents(
268 0xb0, 0x00, // 1: mov $0x0, %al
270 0x0f, 0x0b, // 4: ud2
271 0xff, 0x20, // 6: jmpq *(%rax)
272 0xeb, 0x00, // 8: jmp +0
273 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
274 0xff, 0x10, // 15: callq *(rax)
275 0x75, 0x00, // 17: jne +0
281 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF)));
283 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 1)));
285 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 3)));
287 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 4)));
289 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 6)));
291 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 8)));
293 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 10)));
295 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 15)));
297 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 17)));
299 Analysis
.canFallThrough(Analysis
.getInstructionOrDie(0xDEADBEEF + 19)));
302 TEST_F(BasicX86FileAnalysisTest
, DefiniteNextInstructionTest
) {
303 if (!SuccessfullyInitialised
)
305 Analysis
.parseSectionContents(
308 0xb0, 0x00, // 1: mov $0x0, %al
310 0x0f, 0x0b, // 4: ud2
311 0xff, 0x20, // 6: jmpq *(%rax)
312 0xeb, 0x00, // 8: jmp 10 [+0]
313 0xeb, 0x05, // 10: jmp 17 [+5]
314 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
315 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
316 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
317 0xff, 0x10, // 27: callq *(rax)
318 0x75, 0x00, // 29: jne 31 [+0]
319 0x75, 0xe0, // 31: jne 1 [-32]
321 0xeb, 0xdd, // 34: jmp 1 [-35]
322 0xeb, 0xdd, // 36: jmp 3 [-35]
323 0xeb, 0xdc, // 38: jmp 4 [-36]
327 const auto *Current
= Analysis
.getInstruction(0xDEADBEEF);
328 const auto *Next
= Analysis
.getDefiniteNextInstruction(*Current
);
329 EXPECT_NE(nullptr, Next
);
330 EXPECT_EQ(0xDEADBEEF + 1, Next
->VMAddress
);
332 Current
= Analysis
.getInstruction(0xDEADBEEF + 1);
333 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
335 Current
= Analysis
.getInstruction(0xDEADBEEF + 3);
336 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
338 Current
= Analysis
.getInstruction(0xDEADBEEF + 4);
339 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
341 Current
= Analysis
.getInstruction(0xDEADBEEF + 6);
342 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
344 Current
= Analysis
.getInstruction(0xDEADBEEF + 8);
345 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
346 EXPECT_NE(nullptr, Next
);
347 EXPECT_EQ(0xDEADBEEF + 10, Next
->VMAddress
);
349 Current
= Analysis
.getInstruction(0xDEADBEEF + 10);
350 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
351 EXPECT_NE(nullptr, Next
);
352 EXPECT_EQ(0xDEADBEEF + 17, Next
->VMAddress
);
354 Current
= Analysis
.getInstruction(0xDEADBEEF + 12);
355 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
356 EXPECT_NE(nullptr, Next
);
357 EXPECT_EQ(0xDEADBEEF + 17, Next
->VMAddress
);
359 Current
= Analysis
.getInstruction(0xDEADBEEF + 17);
360 // Note, definite next instruction address is out of range and should fail.
361 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
362 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
364 Current
= Analysis
.getInstruction(0xDEADBEEF + 22);
365 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
366 EXPECT_NE(nullptr, Next
);
367 EXPECT_EQ(0xDEADBEEF + 31, Next
->VMAddress
);
369 Current
= Analysis
.getInstruction(0xDEADBEEF + 27);
370 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
371 Current
= Analysis
.getInstruction(0xDEADBEEF + 29);
372 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
373 Current
= Analysis
.getInstruction(0xDEADBEEF + 31);
374 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
375 Current
= Analysis
.getInstruction(0xDEADBEEF + 33);
376 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
378 Current
= Analysis
.getInstruction(0xDEADBEEF + 34);
379 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
380 EXPECT_NE(nullptr, Next
);
381 EXPECT_EQ(0xDEADBEEF + 1, Next
->VMAddress
);
383 Current
= Analysis
.getInstruction(0xDEADBEEF + 36);
384 EXPECT_EQ(nullptr, Analysis
.getDefiniteNextInstruction(*Current
));
386 Current
= Analysis
.getInstruction(0xDEADBEEF + 38);
387 Next
= Analysis
.getDefiniteNextInstruction(*Current
);
388 EXPECT_NE(nullptr, Next
);
389 EXPECT_EQ(0xDEADBEEF + 4, Next
->VMAddress
);
392 TEST_F(BasicX86FileAnalysisTest
, ControlFlowXRefsTest
) {
393 if (!SuccessfullyInitialised
)
395 Analysis
.parseSectionContents(
398 0xb0, 0x00, // 1: mov $0x0, %al
400 0x0f, 0x0b, // 4: ud2
401 0xff, 0x20, // 6: jmpq *(%rax)
402 0xeb, 0x00, // 8: jmp 10 [+0]
403 0xeb, 0x05, // 10: jmp 17 [+5]
404 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
405 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
406 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
407 0xff, 0x10, // 27: callq *(rax)
408 0x75, 0x00, // 29: jne 31 [+0]
409 0x75, 0xe0, // 31: jne 1 [-32]
411 0xeb, 0xdd, // 34: jmp 1 [-35]
412 0xeb, 0xdd, // 36: jmp 3 [-35]
413 0xeb, 0xdc, // 38: jmp 4 [-36]
416 const auto *InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF);
417 std::set
<const Instr
*> XRefs
=
418 Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
419 EXPECT_TRUE(XRefs
.empty());
421 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 1);
422 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
423 EXPECT_THAT(XRefs
, UnorderedElementsAre(
424 Field(&Instr::VMAddress
, Eq(0xDEADBEEF)),
425 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 31)),
426 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 34))));
428 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 3);
429 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
430 EXPECT_THAT(XRefs
, UnorderedElementsAre(
431 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 1)),
432 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 36))));
434 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 4);
435 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
436 EXPECT_THAT(XRefs
, UnorderedElementsAre(
437 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 38))));
439 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 6);
440 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
442 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 8);
443 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
444 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
446 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 10);
447 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
448 EXPECT_THAT(XRefs
, UnorderedElementsAre(
449 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 8))));
451 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 12);
452 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
453 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
455 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 17);
456 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
457 EXPECT_THAT(XRefs
, UnorderedElementsAre(
458 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 10)),
459 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 12))));
461 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 22);
462 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
463 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
465 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 27);
466 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
467 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
469 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 29);
470 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
471 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
473 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 31);
474 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
475 EXPECT_THAT(XRefs
, UnorderedElementsAre(
476 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 22)),
477 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 29))));
479 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 33);
480 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
481 EXPECT_THAT(XRefs
, UnorderedElementsAre(
482 Field(&Instr::VMAddress
, Eq(0xDEADBEEF + 31))));
484 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 34);
485 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
486 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
488 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 36);
489 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
490 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
492 InstrMetaPtr
= &Analysis
.getInstructionOrDie(0xDEADBEEF + 38);
493 XRefs
= Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
);
494 EXPECT_TRUE(Analysis
.getDirectControlFlowXRefs(*InstrMetaPtr
).empty());
497 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionInvalidTargets
) {
498 if (!SuccessfullyInitialised
)
500 Analysis
.parseSectionContents(
503 0x0f, 0x0b, // 1: ud2
504 0x75, 0x00, // 3: jne 5 [+0]
508 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF, 0x0});
509 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
510 Analysis
.validateCFIProtection(Result
));
511 Result
= GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 1, 0x0});
512 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
513 Analysis
.validateCFIProtection(Result
));
514 Result
= GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 3, 0x0});
515 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
516 Analysis
.validateCFIProtection(Result
));
517 Result
= GraphBuilder::buildFlowGraph(Analysis
, {0x12345678, 0x0});
518 EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION
,
519 Analysis
.validateCFIProtection(Result
));
522 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicFallthroughToUd2
) {
523 if (!SuccessfullyInitialised
)
525 Analysis
.parseSectionContents(
527 0x75, 0x02, // 0: jne 4 [+2]
528 0x0f, 0x0b, // 2: ud2
529 0xff, 0x10, // 4: callq *(%rax)
533 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
534 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
535 Analysis
.validateCFIProtection(Result
));
538 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicJumpToUd2
) {
539 if (!SuccessfullyInitialised
)
541 Analysis
.parseSectionContents(
543 0x75, 0x02, // 0: jne 4 [+2]
544 0xff, 0x10, // 2: callq *(%rax)
545 0x0f, 0x0b, // 4: ud2
549 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 2, 0x0});
550 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
551 Analysis
.validateCFIProtection(Result
));
554 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathUd2
) {
555 if (!SuccessfullyInitialised
)
557 Analysis
.parseSectionContents(
559 0x75, 0x03, // 0: jne 5 [+3]
561 0xff, 0x10, // 3: callq *(%rax)
562 0x0f, 0x0b, // 5: ud2
563 0x75, 0xf9, // 7: jne 2 [-7]
564 0x0f, 0x0b, // 9: ud2
568 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 3, 0x0});
569 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
570 Analysis
.validateCFIProtection(Result
));
573 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathSingleUd2
) {
574 if (!SuccessfullyInitialised
)
576 Analysis
.parseSectionContents(
578 0x75, 0x05, // 0: jne 7 [+5]
580 0xff, 0x10, // 3: callq *(%rax)
581 0x75, 0xfb, // 5: jne 2 [-5]
582 0x0f, 0x0b, // 7: ud2
586 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 3, 0x0});
587 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
588 Analysis
.validateCFIProtection(Result
));
591 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitUpwards
) {
592 if (!SuccessfullyInitialised
)
594 Analysis
.parseSectionContents(
596 0x75, 0x06, // 0: jne 8 [+6]
601 0xff, 0x10, // 6: callq *(%rax)
602 0x0f, 0x0b, // 8: ud2
605 uint64_t PrevSearchLengthForConditionalBranch
=
606 SearchLengthForConditionalBranch
;
607 SearchLengthForConditionalBranch
= 2;
610 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 6, 0x0});
611 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
612 Analysis
.validateCFIProtection(Result
));
614 SearchLengthForConditionalBranch
= PrevSearchLengthForConditionalBranch
;
617 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitDownwards
) {
618 if (!SuccessfullyInitialised
)
620 Analysis
.parseSectionContents(
622 0x75, 0x02, // 0: jne 4 [+2]
623 0xff, 0x10, // 2: callq *(%rax)
628 0x0f, 0x0b, // 8: ud2
631 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
632 SearchLengthForUndef
= 2;
635 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 2, 0x0});
636 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH
,
637 Analysis
.validateCFIProtection(Result
));
639 SearchLengthForUndef
= PrevSearchLengthForUndef
;
642 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionGoodAndBadPaths
) {
643 if (!SuccessfullyInitialised
)
645 Analysis
.parseSectionContents(
647 0xeb, 0x02, // 0: jmp 4 [+2]
648 0x75, 0x02, // 2: jne 6 [+2]
649 0xff, 0x10, // 4: callq *(%rax)
650 0x0f, 0x0b, // 6: ud2
654 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
655 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
656 Analysis
.validateCFIProtection(Result
));
659 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionWithUnconditionalJumpInFallthrough
) {
660 if (!SuccessfullyInitialised
)
662 Analysis
.parseSectionContents(
664 0x75, 0x04, // 0: jne 6 [+4]
665 0xeb, 0x00, // 2: jmp 4 [+0]
666 0xff, 0x10, // 4: callq *(%rax)
667 0x0f, 0x0b, // 6: ud2
671 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
672 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
673 Analysis
.validateCFIProtection(Result
));
676 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionComplexExample
) {
677 if (!SuccessfullyInitialised
)
679 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
681 Analysis
.parseSectionContents(
683 0x75, 0x12, // 0: jne 20 [+18]
684 0xeb, 0x03, // 2: jmp 7 [+3]
685 0x75, 0x10, // 4: jne 22 [+16]
689 0xff, 0x10, // 9: callq *(%rax)
690 0xeb, 0xfc, // 11: jmp 9 [-4]
691 0x75, 0xfa, // 13: jne 9 [-6]
692 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
695 0x0f, 0x0b, // 22: ud2
698 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
699 SearchLengthForUndef
= 5;
701 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 9, 0x0});
702 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
703 Analysis
.validateCFIProtection(Result
));
704 SearchLengthForUndef
= PrevSearchLengthForUndef
;
707 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTest
) {
708 Analysis
.parseSectionContents(
710 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
711 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
712 0xff, 0xd0, // 0x68811d: callq *%rax
713 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
714 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
715 0x0f, 0x0b, // 0x688127: ud2
718 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
719 SearchLengthForUndef
= 1;
720 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, {0x68811d, 0x0});
721 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
722 Analysis
.validateCFIProtection(Result
));
723 SearchLengthForUndef
= PrevSearchLengthForUndef
;
726 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTestFarAway
) {
727 Analysis
.parseSectionContents(
729 0x74, 0x73, // 0x7759eb: je 0x775a60
730 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
734 Analysis
.parseSectionContents(
736 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
737 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
738 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
739 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
740 0xff, 0xd1, // 0x775a68: callq *%rcx
744 Analysis
.parseSectionContents(
746 0x0f, 0x0b, // 0x775e0e: ud2
749 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
750 SearchLengthForUndef
= 1;
751 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, {0x775a68, 0x0});
752 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH
,
753 Analysis
.validateCFIProtection(Result
));
754 SearchLengthForUndef
= 2;
755 Result
= GraphBuilder::buildFlowGraph(Analysis
, {0x775a68, 0x0});
756 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
757 Analysis
.validateCFIProtection(Result
));
758 SearchLengthForUndef
= 3;
759 Result
= GraphBuilder::buildFlowGraph(Analysis
, {0x775a68, 0x0});
760 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
761 Analysis
.validateCFIProtection(Result
));
762 SearchLengthForUndef
= PrevSearchLengthForUndef
;
765 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit
) {
766 if (!SuccessfullyInitialised
)
768 Analysis
.parseSectionContents(
770 0x75, 0x02, // 0: jne 4 [+2]
771 0x0f, 0x0b, // 2: ud2
772 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
773 0xff, 0x10, // 10: callq *(%rax)
777 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 10, 0x0});
778 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
779 Analysis
.validateCFIProtection(Result
));
782 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit2
) {
783 if (!SuccessfullyInitialised
)
785 Analysis
.parseSectionContents(
787 0x75, 0x02, // 0: jne 4 [+2]
788 0x0f, 0x0b, // 2: ud2
789 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
790 0xff, 0x10, // 8: callq *(%rax)
794 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 8, 0x0});
795 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
796 Analysis
.validateCFIProtection(Result
));
799 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathImplicit
) {
800 if (!SuccessfullyInitialised
)
802 Analysis
.parseSectionContents(
804 0x75, 0x02, // 0: jne 4 [+2]
805 0x0f, 0x0b, // 2: ud2
806 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
807 0xff, 0x10, // 9: callq *(%rax)
811 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 9, 0x0});
812 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
813 Analysis
.validateCFIProtection(Result
));
816 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberDualPathImplicit
) {
817 if (!SuccessfullyInitialised
)
819 Analysis
.parseSectionContents(
821 0x75, 0x04, // 0: jne 6 [+4]
822 0x0f, 0x31, // 2: rdtsc (note: affects eax)
823 0xff, 0x10, // 4: callq *(%rax)
824 0x0f, 0x0b, // 6: ud2
825 0x75, 0xf9, // 8: jne 2 [-7]
826 0x0f, 0x0b, // 10: ud2
830 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 4, 0x0});
831 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
832 Analysis
.validateCFIProtection(Result
));
835 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicUnprotected
) {
836 if (!SuccessfullyInitialised
)
838 Analysis
.parseSectionContents(
840 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
844 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF, 0x0});
845 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
846 Analysis
.validateCFIProtection(Result
));
849 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicProtected
) {
850 if (!SuccessfullyInitialised
)
852 Analysis
.parseSectionContents(
854 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
855 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
856 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
860 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 8, 0x0});
861 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
862 Analysis
.validateCFIProtection(Result
));
865 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberBasic
) {
866 if (!SuccessfullyInitialised
)
868 Analysis
.parseSectionContents(
870 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
871 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
872 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
873 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
877 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
878 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
879 Analysis
.validateCFIProtection(Result
));
882 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberOneLoad
) {
883 if (!SuccessfullyInitialised
)
885 Analysis
.parseSectionContents(
887 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
888 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
889 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
890 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
894 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
895 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
896 Analysis
.validateCFIProtection(Result
));
899 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddGood
) {
900 if (!SuccessfullyInitialised
)
902 Analysis
.parseSectionContents(
904 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
905 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
906 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
907 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
908 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
912 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
913 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
914 Analysis
.validateCFIProtection(Result
));
917 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad
) {
918 if (!SuccessfullyInitialised
)
920 Analysis
.parseSectionContents(
922 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
923 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
924 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
925 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
926 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
930 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
931 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
932 Analysis
.validateCFIProtection(Result
));
935 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad2
) {
936 if (!SuccessfullyInitialised
)
938 Analysis
.parseSectionContents(
940 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
941 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
942 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
943 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
944 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
948 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
949 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
950 Analysis
.validateCFIProtection(Result
));
953 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberTwoLoads
) {
954 if (!SuccessfullyInitialised
)
956 Analysis
.parseSectionContents(
958 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
959 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
960 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
961 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
962 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
966 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
967 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
968 Analysis
.validateCFIProtection(Result
));
971 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedSecondLoad
) {
972 if (!SuccessfullyInitialised
)
974 Analysis
.parseSectionContents(
976 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
977 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
978 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
979 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
980 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
984 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
985 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
986 Analysis
.validateCFIProtection(Result
));
989 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedLoads
) {
990 if (!SuccessfullyInitialised
)
992 Analysis
.parseSectionContents(
994 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
995 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
996 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
997 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
998 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
1001 GraphResult Result
=
1002 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 16, 0x0});
1003 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
1004 Analysis
.validateCFIProtection(Result
));
1007 TEST_F(BasicAArch64FileAnalysisTest
, AArch64GoodAndBadPaths
) {
1008 if (!SuccessfullyInitialised
)
1010 Analysis
.parseSectionContents(
1012 0x03, 0x00, 0x00, 0x14, // 0: b 12
1013 0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
1014 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
1015 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
1018 GraphResult Result
=
1019 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 12, 0x0});
1020 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
1021 Analysis
.validateCFIProtection(Result
));
1024 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPaths
) {
1025 if (!SuccessfullyInitialised
)
1027 Analysis
.parseSectionContents(
1029 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
1030 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1031 0x03, 0x00, 0x00, 0x14, // 8: b 12
1032 0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
1033 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1034 0x20, 0x00, 0x1f, 0xd6, // 20: br x1
1035 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
1038 GraphResult Result
=
1039 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 20, 0x0});
1040 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
1041 Analysis
.validateCFIProtection(Result
));
1044 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad1
) {
1045 if (!SuccessfullyInitialised
)
1047 Analysis
.parseSectionContents(
1049 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1050 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1051 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
1052 0x03, 0x00, 0x00, 0x14, // 12: b 12
1053 0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
1054 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1055 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1056 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1059 GraphResult Result
=
1060 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 24, 0x0});
1061 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1062 Analysis
.validateCFIProtection(Result
));
1065 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad2
) {
1066 if (!SuccessfullyInitialised
)
1068 Analysis
.parseSectionContents(
1070 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1071 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1072 0x03, 0x00, 0x00, 0x14, // 8: b 12
1073 0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
1074 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1075 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1076 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1077 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1080 GraphResult Result
=
1081 GraphBuilder::buildFlowGraph(Analysis
, {0xDEADBEEF + 24, 0x0});
1082 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1083 Analysis
.validateCFIProtection(Result
));
1086 } // anonymous namespace
1087 } // end namespace cfi_verify
1088 } // end namespace llvm
1090 int main(int argc
, char **argv
) {
1091 ::testing::InitGoogleTest(&argc
, argv
);
1092 llvm::cl::ParseCommandLineOptions(argc
, argv
);
1094 llvm::InitializeAllTargetInfos();
1095 llvm::InitializeAllTargetMCs();
1096 llvm::InitializeAllAsmParsers();
1097 llvm::InitializeAllDisassemblers();
1099 return RUN_ALL_TESTS();