[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
[llvm-complete.git] / unittests / tools / llvm-cfi-verify / FileAnalysis.cpp
blobe38ac9264c8dfa18124e94d29f20f62ae52fe330
1 //===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
38 #include <cstdlib>
40 using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
41 using ::testing::Eq;
42 using ::testing::Field;
44 namespace llvm {
45 namespace cfi_verify {
46 namespace {
47 class ELFTestFileAnalysis : public FileAnalysis {
48 public:
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 {
64 public:
65 BasicFileAnalysisTest(StringRef Trip) : Analysis(Trip) {}
66 protected:
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;
73 outs()
74 << "Note: CFIVerifyTests are disabled due to lack of support "
75 "on this build.\n";
76 });
80 bool SuccessfullyInitialised;
81 ELFTestFileAnalysis Analysis;
84 class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {
85 public:
86 BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
89 class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
90 public:
91 BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
94 TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
95 if (!SuccessfullyInitialised)
96 return;
97 Analysis.parseSectionContents(
99 0x90, // 0: nop
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
105 0x2f, // 20: (bad)
106 0x41, 0x0e, // 21: rex.B (bad)
107 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
109 {0xDEADBEEF, 0x0});
111 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
112 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
114 // 0xDEADBEEF: nop
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)
206 return;
207 Analysis.parseSectionContents(
209 0x90, // 0: nop
210 0x2f, // 1: (bad)
211 0x90 // 2: nop
213 {0xDEADBEEF, 0x0});
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)
229 return;
230 Analysis.parseSectionContents(
232 0x90, // 0: nop
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
238 0x2f, // 20: (bad)
239 0x41, 0x0e, // 21: rex.B (bad)
240 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
241 0x0f, 0x0b // 28: ud2
243 {0xDEADBEEF, 0x0});
245 EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
246 EXPECT_FALSE(
247 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
248 EXPECT_FALSE(
249 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
250 EXPECT_FALSE(
251 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
252 EXPECT_FALSE(
253 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
254 EXPECT_FALSE(
255 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
256 EXPECT_FALSE(
257 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
258 EXPECT_TRUE(
259 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
262 TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
263 if (!SuccessfullyInitialised)
264 return;
265 Analysis.parseSectionContents(
267 0x90, // 0: nop
268 0xb0, 0x00, // 1: mov $0x0, %al
269 0x2f, // 3: (bad)
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
276 0xc3, // 19: retq
278 {0xDEADBEEF, 0x0});
280 EXPECT_TRUE(
281 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
282 EXPECT_TRUE(
283 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
284 EXPECT_FALSE(
285 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
286 EXPECT_FALSE(
287 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
288 EXPECT_FALSE(
289 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
290 EXPECT_FALSE(
291 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
292 EXPECT_FALSE(
293 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
294 EXPECT_FALSE(
295 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
296 EXPECT_TRUE(
297 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
298 EXPECT_FALSE(
299 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
302 TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
303 if (!SuccessfullyInitialised)
304 return;
305 Analysis.parseSectionContents(
307 0x90, // 0: nop
308 0xb0, 0x00, // 1: mov $0x0, %al
309 0x2f, // 3: (bad)
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]
320 0xc3, // 33: retq
321 0xeb, 0xdd, // 34: jmp 1 [-35]
322 0xeb, 0xdd, // 36: jmp 3 [-35]
323 0xeb, 0xdc, // 38: jmp 4 [-36]
325 {0xDEADBEEF, 0x0});
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)
394 return;
395 Analysis.parseSectionContents(
397 0x90, // 0: nop
398 0xb0, 0x00, // 1: mov $0x0, %al
399 0x2f, // 3: (bad)
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]
410 0xc3, // 33: retq
411 0xeb, 0xdd, // 34: jmp 1 [-35]
412 0xeb, 0xdd, // 36: jmp 3 [-35]
413 0xeb, 0xdc, // 38: jmp 4 [-36]
415 {0xDEADBEEF, 0x0});
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)
499 return;
500 Analysis.parseSectionContents(
502 0x90, // 0: nop
503 0x0f, 0x0b, // 1: ud2
504 0x75, 0x00, // 3: jne 5 [+0]
506 {0xDEADBEEF, 0x0});
507 GraphResult Result =
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)
524 return;
525 Analysis.parseSectionContents(
527 0x75, 0x02, // 0: jne 4 [+2]
528 0x0f, 0x0b, // 2: ud2
529 0xff, 0x10, // 4: callq *(%rax)
531 {0xDEADBEEF, 0x0});
532 GraphResult Result =
533 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
534 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
535 Analysis.validateCFIProtection(Result));
538 TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
539 if (!SuccessfullyInitialised)
540 return;
541 Analysis.parseSectionContents(
543 0x75, 0x02, // 0: jne 4 [+2]
544 0xff, 0x10, // 2: callq *(%rax)
545 0x0f, 0x0b, // 4: ud2
547 {0xDEADBEEF, 0x0});
548 GraphResult Result =
549 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
550 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
551 Analysis.validateCFIProtection(Result));
554 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
555 if (!SuccessfullyInitialised)
556 return;
557 Analysis.parseSectionContents(
559 0x75, 0x03, // 0: jne 5 [+3]
560 0x90, // 2: nop
561 0xff, 0x10, // 3: callq *(%rax)
562 0x0f, 0x0b, // 5: ud2
563 0x75, 0xf9, // 7: jne 2 [-7]
564 0x0f, 0x0b, // 9: ud2
566 {0xDEADBEEF, 0x0});
567 GraphResult Result =
568 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
569 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
570 Analysis.validateCFIProtection(Result));
573 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
574 if (!SuccessfullyInitialised)
575 return;
576 Analysis.parseSectionContents(
578 0x75, 0x05, // 0: jne 7 [+5]
579 0x90, // 2: nop
580 0xff, 0x10, // 3: callq *(%rax)
581 0x75, 0xfb, // 5: jne 2 [-5]
582 0x0f, 0x0b, // 7: ud2
584 {0xDEADBEEF, 0x0});
585 GraphResult Result =
586 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
587 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
588 Analysis.validateCFIProtection(Result));
591 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
592 if (!SuccessfullyInitialised)
593 return;
594 Analysis.parseSectionContents(
596 0x75, 0x06, // 0: jne 8 [+6]
597 0x90, // 2: nop
598 0x90, // 3: nop
599 0x90, // 4: nop
600 0x90, // 5: nop
601 0xff, 0x10, // 6: callq *(%rax)
602 0x0f, 0x0b, // 8: ud2
604 {0xDEADBEEF, 0x0});
605 uint64_t PrevSearchLengthForConditionalBranch =
606 SearchLengthForConditionalBranch;
607 SearchLengthForConditionalBranch = 2;
609 GraphResult Result =
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)
619 return;
620 Analysis.parseSectionContents(
622 0x75, 0x02, // 0: jne 4 [+2]
623 0xff, 0x10, // 2: callq *(%rax)
624 0x90, // 4: nop
625 0x90, // 5: nop
626 0x90, // 6: nop
627 0x90, // 7: nop
628 0x0f, 0x0b, // 8: ud2
630 {0xDEADBEEF, 0x0});
631 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
632 SearchLengthForUndef = 2;
634 GraphResult Result =
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)
644 return;
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
652 {0xDEADBEEF, 0x0});
653 GraphResult Result =
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)
661 return;
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
669 {0xDEADBEEF, 0x0});
670 GraphResult Result =
671 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
672 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
673 Analysis.validateCFIProtection(Result));
676 TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
677 if (!SuccessfullyInitialised)
678 return;
679 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
680 // graph.
681 Analysis.parseSectionContents(
683 0x75, 0x12, // 0: jne 20 [+18]
684 0xeb, 0x03, // 2: jmp 7 [+3]
685 0x75, 0x10, // 4: jne 22 [+16]
686 0x90, // 6: nop
687 0x90, // 7: nop
688 0x90, // 8: nop
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]
693 0x90, // 20: nop
694 0x90, // 21: nop
695 0x0f, 0x0b, // 22: ud2
697 {0xDEADBEEF, 0x0});
698 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
699 SearchLengthForUndef = 5;
700 GraphResult Result =
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
717 {0x688118, 0x0});
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
732 {0x7759eb, 0x0});
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
742 {0x775a56, 0x0});
744 Analysis.parseSectionContents(
746 0x0f, 0x0b, // 0x775e0e: ud2
748 {0x775e0e, 0x0});
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)
767 return;
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)
775 {0xDEADBEEF, 0x0});
776 GraphResult Result =
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)
784 return;
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)
792 {0xDEADBEEF, 0x0});
793 GraphResult Result =
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)
801 return;
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)
809 {0xDEADBEEF, 0x0});
810 GraphResult Result =
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)
818 return;
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
828 {0xDEADBEEF, 0x0});
829 GraphResult Result =
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)
837 return;
838 Analysis.parseSectionContents(
840 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
842 {0xDEADBEEF, 0x0});
843 GraphResult Result =
844 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
845 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
846 Analysis.validateCFIProtection(Result));
849 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
850 if (!SuccessfullyInitialised)
851 return;
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
858 {0xDEADBEEF, 0x0});
859 GraphResult Result =
860 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
861 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
862 Analysis.validateCFIProtection(Result));
865 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
866 if (!SuccessfullyInitialised)
867 return;
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
875 {0xDEADBEEF, 0x0});
876 GraphResult Result =
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)
884 return;
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
892 {0xDEADBEEF, 0x0});
893 GraphResult Result =
894 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
895 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
896 Analysis.validateCFIProtection(Result));
899 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
900 if (!SuccessfullyInitialised)
901 return;
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
910 {0xDEADBEEF, 0x0});
911 GraphResult Result =
912 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
913 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
914 Analysis.validateCFIProtection(Result));
917 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
918 if (!SuccessfullyInitialised)
919 return;
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
928 {0xDEADBEEF, 0x0});
929 GraphResult Result =
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)
937 return;
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
946 {0xDEADBEEF, 0x0});
947 GraphResult Result =
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)
955 return;
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
964 {0xDEADBEEF, 0x0});
965 GraphResult Result =
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)
973 return;
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
982 {0xDEADBEEF, 0x0});
983 GraphResult Result =
984 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
985 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
986 Analysis.validateCFIProtection(Result));
989 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
990 if (!SuccessfullyInitialised)
991 return;
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
1000 {0xDEADBEEF, 0x0});
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)
1009 return;
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
1017 {0xDEADBEEF, 0x0});
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)
1026 return;
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
1037 {0xDEADBEEF, 0x0});
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)
1046 return;
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
1058 {0xDEADBEEF, 0x0});
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)
1067 return;
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
1079 {0xDEADBEEF, 0x0});
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();