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 uint64_t SectionAddress
) {
55 FileAnalysis::parseSectionContents(SectionBytes
, SectionAddress
);
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]
507 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF);
508 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
509 Analysis
.validateCFIProtection(Result
));
510 Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 1);
511 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
512 Analysis
.validateCFIProtection(Result
));
513 Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 3);
514 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF
,
515 Analysis
.validateCFIProtection(Result
));
516 Result
= GraphBuilder::buildFlowGraph(Analysis
, 0x12345678);
517 EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION
,
518 Analysis
.validateCFIProtection(Result
));
521 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicFallthroughToUd2
) {
522 if (!SuccessfullyInitialised
)
524 Analysis
.parseSectionContents(
526 0x75, 0x02, // 0: jne 4 [+2]
527 0x0f, 0x0b, // 2: ud2
528 0xff, 0x10, // 4: callq *(%rax)
531 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 4);
532 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
533 Analysis
.validateCFIProtection(Result
));
536 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionBasicJumpToUd2
) {
537 if (!SuccessfullyInitialised
)
539 Analysis
.parseSectionContents(
541 0x75, 0x02, // 0: jne 4 [+2]
542 0xff, 0x10, // 2: callq *(%rax)
543 0x0f, 0x0b, // 4: ud2
546 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 2);
547 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
548 Analysis
.validateCFIProtection(Result
));
551 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathUd2
) {
552 if (!SuccessfullyInitialised
)
554 Analysis
.parseSectionContents(
556 0x75, 0x03, // 0: jne 5 [+3]
558 0xff, 0x10, // 3: callq *(%rax)
559 0x0f, 0x0b, // 5: ud2
560 0x75, 0xf9, // 7: jne 2 [-7]
561 0x0f, 0x0b, // 9: ud2
564 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 3);
565 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
566 Analysis
.validateCFIProtection(Result
));
569 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualPathSingleUd2
) {
570 if (!SuccessfullyInitialised
)
572 Analysis
.parseSectionContents(
574 0x75, 0x05, // 0: jne 7 [+5]
576 0xff, 0x10, // 3: callq *(%rax)
577 0x75, 0xfb, // 5: jne 2 [-5]
578 0x0f, 0x0b, // 7: ud2
581 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 3);
582 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
583 Analysis
.validateCFIProtection(Result
));
586 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitUpwards
) {
587 if (!SuccessfullyInitialised
)
589 Analysis
.parseSectionContents(
591 0x75, 0x06, // 0: jne 8 [+6]
596 0xff, 0x10, // 6: callq *(%rax)
597 0x0f, 0x0b, // 8: ud2
600 uint64_t PrevSearchLengthForConditionalBranch
=
601 SearchLengthForConditionalBranch
;
602 SearchLengthForConditionalBranch
= 2;
604 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 6);
605 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
606 Analysis
.validateCFIProtection(Result
));
608 SearchLengthForConditionalBranch
= PrevSearchLengthForConditionalBranch
;
611 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionDualFailLimitDownwards
) {
612 if (!SuccessfullyInitialised
)
614 Analysis
.parseSectionContents(
616 0x75, 0x02, // 0: jne 4 [+2]
617 0xff, 0x10, // 2: callq *(%rax)
622 0x0f, 0x0b, // 8: ud2
625 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
626 SearchLengthForUndef
= 2;
628 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 2);
629 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH
,
630 Analysis
.validateCFIProtection(Result
));
632 SearchLengthForUndef
= PrevSearchLengthForUndef
;
635 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionGoodAndBadPaths
) {
636 if (!SuccessfullyInitialised
)
638 Analysis
.parseSectionContents(
640 0xeb, 0x02, // 0: jmp 4 [+2]
641 0x75, 0x02, // 2: jne 6 [+2]
642 0xff, 0x10, // 4: callq *(%rax)
643 0x0f, 0x0b, // 6: ud2
646 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 4);
647 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
648 Analysis
.validateCFIProtection(Result
));
651 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionWithUnconditionalJumpInFallthrough
) {
652 if (!SuccessfullyInitialised
)
654 Analysis
.parseSectionContents(
656 0x75, 0x04, // 0: jne 6 [+4]
657 0xeb, 0x00, // 2: jmp 4 [+0]
658 0xff, 0x10, // 4: callq *(%rax)
659 0x0f, 0x0b, // 6: ud2
662 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 4);
663 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
664 Analysis
.validateCFIProtection(Result
));
667 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionComplexExample
) {
668 if (!SuccessfullyInitialised
)
670 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
672 Analysis
.parseSectionContents(
674 0x75, 0x12, // 0: jne 20 [+18]
675 0xeb, 0x03, // 2: jmp 7 [+3]
676 0x75, 0x10, // 4: jne 22 [+16]
680 0xff, 0x10, // 9: callq *(%rax)
681 0xeb, 0xfc, // 11: jmp 9 [-4]
682 0x75, 0xfa, // 13: jne 9 [-6]
683 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
686 0x0f, 0x0b, // 22: ud2
689 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
690 SearchLengthForUndef
= 5;
691 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 9);
692 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
693 Analysis
.validateCFIProtection(Result
));
694 SearchLengthForUndef
= PrevSearchLengthForUndef
;
697 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTest
) {
698 Analysis
.parseSectionContents(
700 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
701 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
702 0xff, 0xd0, // 0x68811d: callq *%rax
703 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
704 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
705 0x0f, 0x0b, // 0x688127: ud2
708 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
709 SearchLengthForUndef
= 1;
710 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0x68811d);
711 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
712 Analysis
.validateCFIProtection(Result
));
713 SearchLengthForUndef
= PrevSearchLengthForUndef
;
716 TEST_F(BasicX86FileAnalysisTest
, UndefSearchLengthOneTestFarAway
) {
717 Analysis
.parseSectionContents(
719 0x74, 0x73, // 0x7759eb: je 0x775a60
720 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
724 Analysis
.parseSectionContents(
726 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
727 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
728 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
729 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
730 0xff, 0xd1, // 0x775a68: callq *%rcx
734 Analysis
.parseSectionContents(
736 0x0f, 0x0b, // 0x775e0e: ud2
739 uint64_t PrevSearchLengthForUndef
= SearchLengthForUndef
;
740 SearchLengthForUndef
= 1;
741 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0x775a68);
742 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH
,
743 Analysis
.validateCFIProtection(Result
));
744 SearchLengthForUndef
= 2;
745 Result
= GraphBuilder::buildFlowGraph(Analysis
, 0x775a68);
746 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
747 Analysis
.validateCFIProtection(Result
));
748 SearchLengthForUndef
= 3;
749 Result
= GraphBuilder::buildFlowGraph(Analysis
, 0x775a68);
750 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
751 Analysis
.validateCFIProtection(Result
));
752 SearchLengthForUndef
= PrevSearchLengthForUndef
;
755 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit
) {
756 if (!SuccessfullyInitialised
)
758 Analysis
.parseSectionContents(
760 0x75, 0x02, // 0: jne 4 [+2]
761 0x0f, 0x0b, // 2: ud2
762 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
763 0xff, 0x10, // 10: callq *(%rax)
766 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 10);
767 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
768 Analysis
.validateCFIProtection(Result
));
771 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathExplicit2
) {
772 if (!SuccessfullyInitialised
)
774 Analysis
.parseSectionContents(
776 0x75, 0x02, // 0: jne 4 [+2]
777 0x0f, 0x0b, // 2: ud2
778 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
779 0xff, 0x10, // 8: callq *(%rax)
782 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 8);
783 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
784 Analysis
.validateCFIProtection(Result
));
787 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberSinglePathImplicit
) {
788 if (!SuccessfullyInitialised
)
790 Analysis
.parseSectionContents(
792 0x75, 0x02, // 0: jne 4 [+2]
793 0x0f, 0x0b, // 2: ud2
794 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
795 0xff, 0x10, // 9: callq *(%rax)
798 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 9);
799 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
800 Analysis
.validateCFIProtection(Result
));
803 TEST_F(BasicX86FileAnalysisTest
, CFIProtectionClobberDualPathImplicit
) {
804 if (!SuccessfullyInitialised
)
806 Analysis
.parseSectionContents(
808 0x75, 0x04, // 0: jne 6 [+4]
809 0x0f, 0x31, // 2: rdtsc (note: affects eax)
810 0xff, 0x10, // 4: callq *(%rax)
811 0x0f, 0x0b, // 6: ud2
812 0x75, 0xf9, // 8: jne 2 [-7]
813 0x0f, 0x0b, // 10: ud2
816 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 4);
817 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
818 Analysis
.validateCFIProtection(Result
));
821 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicUnprotected
) {
822 if (!SuccessfullyInitialised
)
824 Analysis
.parseSectionContents(
826 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
829 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF);
830 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
831 Analysis
.validateCFIProtection(Result
));
834 TEST_F(BasicAArch64FileAnalysisTest
, AArch64BasicProtected
) {
835 if (!SuccessfullyInitialised
)
837 Analysis
.parseSectionContents(
839 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
840 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
841 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
844 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 8);
845 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
846 Analysis
.validateCFIProtection(Result
));
849 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberBasic
) {
850 if (!SuccessfullyInitialised
)
852 Analysis
.parseSectionContents(
854 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
855 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
856 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
857 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
860 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 12);
861 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
862 Analysis
.validateCFIProtection(Result
));
865 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberOneLoad
) {
866 if (!SuccessfullyInitialised
)
868 Analysis
.parseSectionContents(
870 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
871 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
872 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
873 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
876 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 12);
877 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
878 Analysis
.validateCFIProtection(Result
));
881 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddGood
) {
882 if (!SuccessfullyInitialised
)
884 Analysis
.parseSectionContents(
886 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
887 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
888 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
889 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
890 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
893 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
894 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
895 Analysis
.validateCFIProtection(Result
));
898 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad
) {
899 if (!SuccessfullyInitialised
)
901 Analysis
.parseSectionContents(
903 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
904 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
905 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
906 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
907 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
910 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
911 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
912 Analysis
.validateCFIProtection(Result
));
915 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberLoadAddBad2
) {
916 if (!SuccessfullyInitialised
)
918 Analysis
.parseSectionContents(
920 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
921 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
922 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
923 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
924 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
927 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
928 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
929 Analysis
.validateCFIProtection(Result
));
932 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberTwoLoads
) {
933 if (!SuccessfullyInitialised
)
935 Analysis
.parseSectionContents(
937 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
938 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
939 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
940 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
941 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
944 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
945 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
946 Analysis
.validateCFIProtection(Result
));
949 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedSecondLoad
) {
950 if (!SuccessfullyInitialised
)
952 Analysis
.parseSectionContents(
954 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
955 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
956 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
957 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
958 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
961 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
962 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
963 Analysis
.validateCFIProtection(Result
));
966 TEST_F(BasicAArch64FileAnalysisTest
, AArch64ClobberUnrelatedLoads
) {
967 if (!SuccessfullyInitialised
)
969 Analysis
.parseSectionContents(
971 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
972 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
973 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
974 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
975 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
978 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 16);
979 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
980 Analysis
.validateCFIProtection(Result
));
983 TEST_F(BasicAArch64FileAnalysisTest
, AArch64GoodAndBadPaths
) {
984 if (!SuccessfullyInitialised
)
986 Analysis
.parseSectionContents(
988 0x03, 0x00, 0x00, 0x14, // 0: b 12
989 0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
990 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
991 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
994 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 12);
995 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS
,
996 Analysis
.validateCFIProtection(Result
));
999 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPaths
) {
1000 if (!SuccessfullyInitialised
)
1002 Analysis
.parseSectionContents(
1004 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
1005 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1006 0x03, 0x00, 0x00, 0x14, // 8: b 12
1007 0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
1008 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1009 0x20, 0x00, 0x1f, 0xd6, // 20: br x1
1010 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
1013 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 20);
1014 EXPECT_EQ(CFIProtectionStatus::PROTECTED
,
1015 Analysis
.validateCFIProtection(Result
));
1018 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad1
) {
1019 if (!SuccessfullyInitialised
)
1021 Analysis
.parseSectionContents(
1023 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1024 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1025 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
1026 0x03, 0x00, 0x00, 0x14, // 12: b 12
1027 0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
1028 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1029 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1030 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1033 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 24);
1034 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1035 Analysis
.validateCFIProtection(Result
));
1038 TEST_F(BasicAArch64FileAnalysisTest
, AArch64TwoPathsBadLoad2
) {
1039 if (!SuccessfullyInitialised
)
1041 Analysis
.parseSectionContents(
1043 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
1044 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
1045 0x03, 0x00, 0x00, 0x14, // 8: b 12
1046 0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
1047 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
1048 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
1049 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
1050 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
1053 GraphResult Result
= GraphBuilder::buildFlowGraph(Analysis
, 0xDEADBEEF + 24);
1054 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED
,
1055 Analysis
.validateCFIProtection(Result
));
1058 } // anonymous namespace
1059 } // end namespace cfi_verify
1060 } // end namespace llvm
1062 int main(int argc
, char **argv
) {
1063 ::testing::InitGoogleTest(&argc
, argv
);
1064 llvm::cl::ParseCommandLineOptions(argc
, argv
);
1066 llvm::InitializeAllTargetInfos();
1067 llvm::InitializeAllTargetMCs();
1068 llvm::InitializeAllAsmParsers();
1069 llvm::InitializeAllDisassemblers();
1071 return RUN_ALL_TESTS();