Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / unittests / tools / llvm-cfi-verify / FileAnalysis.cpp
blob58fdbe5c7ad502c84934b5d13e85ae97f0fe5a05
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 uint64_t SectionAddress) {
55 FileAnalysis::parseSectionContents(SectionBytes, SectionAddress);
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);
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);
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);
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);
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);
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);
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);
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)
523 return;
524 Analysis.parseSectionContents(
526 0x75, 0x02, // 0: jne 4 [+2]
527 0x0f, 0x0b, // 2: ud2
528 0xff, 0x10, // 4: callq *(%rax)
530 0xDEADBEEF);
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)
538 return;
539 Analysis.parseSectionContents(
541 0x75, 0x02, // 0: jne 4 [+2]
542 0xff, 0x10, // 2: callq *(%rax)
543 0x0f, 0x0b, // 4: ud2
545 0xDEADBEEF);
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)
553 return;
554 Analysis.parseSectionContents(
556 0x75, 0x03, // 0: jne 5 [+3]
557 0x90, // 2: nop
558 0xff, 0x10, // 3: callq *(%rax)
559 0x0f, 0x0b, // 5: ud2
560 0x75, 0xf9, // 7: jne 2 [-7]
561 0x0f, 0x0b, // 9: ud2
563 0xDEADBEEF);
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)
571 return;
572 Analysis.parseSectionContents(
574 0x75, 0x05, // 0: jne 7 [+5]
575 0x90, // 2: nop
576 0xff, 0x10, // 3: callq *(%rax)
577 0x75, 0xfb, // 5: jne 2 [-5]
578 0x0f, 0x0b, // 7: ud2
580 0xDEADBEEF);
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)
588 return;
589 Analysis.parseSectionContents(
591 0x75, 0x06, // 0: jne 8 [+6]
592 0x90, // 2: nop
593 0x90, // 3: nop
594 0x90, // 4: nop
595 0x90, // 5: nop
596 0xff, 0x10, // 6: callq *(%rax)
597 0x0f, 0x0b, // 8: ud2
599 0xDEADBEEF);
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)
613 return;
614 Analysis.parseSectionContents(
616 0x75, 0x02, // 0: jne 4 [+2]
617 0xff, 0x10, // 2: callq *(%rax)
618 0x90, // 4: nop
619 0x90, // 5: nop
620 0x90, // 6: nop
621 0x90, // 7: nop
622 0x0f, 0x0b, // 8: ud2
624 0xDEADBEEF);
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)
637 return;
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
645 0xDEADBEEF);
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)
653 return;
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
661 0xDEADBEEF);
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)
669 return;
670 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
671 // graph.
672 Analysis.parseSectionContents(
674 0x75, 0x12, // 0: jne 20 [+18]
675 0xeb, 0x03, // 2: jmp 7 [+3]
676 0x75, 0x10, // 4: jne 22 [+16]
677 0x90, // 6: nop
678 0x90, // 7: nop
679 0x90, // 8: nop
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]
684 0x90, // 20: nop
685 0x90, // 21: nop
686 0x0f, 0x0b, // 22: ud2
688 0xDEADBEEF);
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
707 0x688118);
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
722 0x7759eb);
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
732 0x775a56);
734 Analysis.parseSectionContents(
736 0x0f, 0x0b, // 0x775e0e: ud2
738 0x775e0e);
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)
757 return;
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)
765 0xDEADBEEF);
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)
773 return;
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)
781 0xDEADBEEF);
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)
789 return;
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)
797 0xDEADBEEF);
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)
805 return;
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
815 0xDEADBEEF);
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)
823 return;
824 Analysis.parseSectionContents(
826 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
828 0xDEADBEEF);
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)
836 return;
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
843 0xDEADBEEF);
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)
851 return;
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
859 0xDEADBEEF);
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)
867 return;
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
875 0xDEADBEEF);
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)
883 return;
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
892 0xDEADBEEF);
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)
900 return;
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
909 0xDEADBEEF);
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)
917 return;
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
926 0xDEADBEEF);
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)
934 return;
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
943 0xDEADBEEF);
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)
951 return;
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
960 0xDEADBEEF);
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)
968 return;
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
977 0xDEADBEEF);
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)
985 return;
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
993 0xDEADBEEF);
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)
1001 return;
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
1012 0xDEADBEEF);
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)
1020 return;
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
1032 0xDEADBEEF);
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)
1040 return;
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
1052 0xDEADBEEF);
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();