blob: 27275d6e231286d0704d825d83013c7f9be6cce6 [file] [log] [blame]
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +00001//===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
Mitch Phillips5ff01cd2017-10-25 21:21:16 +000011#include "../tools/llvm-cfi-verify/lib/GraphBuilder.h"
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000012#include "gmock/gmock.h"
13#include "gtest/gtest.h"
14
15#include "llvm/BinaryFormat/ELF.h"
16#include "llvm/MC/MCAsmInfo.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCDisassembler/MCDisassembler.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstPrinter.h"
21#include "llvm/MC/MCInstrAnalysis.h"
22#include "llvm/MC/MCInstrDesc.h"
23#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/MC/MCObjectFileInfo.h"
25#include "llvm/MC/MCRegisterInfo.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/Object/Binary.h"
28#include "llvm/Object/COFF.h"
29#include "llvm/Object/ELFObjectFile.h"
30#include "llvm/Object/ObjectFile.h"
31#include "llvm/Support/Casting.h"
32#include "llvm/Support/CommandLine.h"
33#include "llvm/Support/Error.h"
34#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/TargetRegistry.h"
36#include "llvm/Support/TargetSelect.h"
37#include "llvm/Support/raw_ostream.h"
38
39#include <cstdlib>
40
41using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
42using ::testing::Eq;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +000043using ::testing::Field;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000044
45namespace llvm {
46namespace cfi_verify {
47namespace {
48class ELFx86TestFileAnalysis : public FileAnalysis {
49public:
50 ELFx86TestFileAnalysis()
51 : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {}
52
53 // Expose this method publicly for testing.
54 void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
55 uint64_t SectionAddress) {
56 FileAnalysis::parseSectionContents(SectionBytes, SectionAddress);
57 }
58
59 Error initialiseDisassemblyMembers() {
60 return FileAnalysis::initialiseDisassemblyMembers();
61 }
62};
63
64class BasicFileAnalysisTest : public ::testing::Test {
65protected:
66 virtual void SetUp() {
Mitch Phillipsc15bdf52017-11-03 20:54:26 +000067 IgnoreDWARFFlag = true;
Mitch Phillipsd9af3832017-10-23 20:54:01 +000068 SuccessfullyInitialised = true;
69 if (auto Err = Analysis.initialiseDisassemblyMembers()) {
70 handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
71 SuccessfullyInitialised = false;
72 outs()
73 << "Note: CFIVerifyTests are disabled due to lack of x86 support "
74 "on this build.\n";
75 });
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000076 }
77 }
78
Mitch Phillipsd9af3832017-10-23 20:54:01 +000079 bool SuccessfullyInitialised;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000080 ELFx86TestFileAnalysis Analysis;
81};
82
83TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +000084 if (!SuccessfullyInitialised)
85 return;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000086 Analysis.parseSectionContents(
87 {
88 0x90, // 0: nop
89 0xb0, 0x00, // 1: mov $0x0, %al
90 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
91 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
92 0x48, 0xbe, 0xc4, 0x07, 0x40,
93 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
94 0x2f, // 20: (bad)
95 0x41, 0x0e, // 21: rex.B (bad)
96 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
97 },
98 0xDEADBEEF);
99
100 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
101 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
102
103 // 0xDEADBEEF: nop
104 const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
105 EXPECT_NE(nullptr, InstrMeta);
106 EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
107 EXPECT_EQ(1u, InstrMeta->InstructionSize);
108 EXPECT_TRUE(InstrMeta->Valid);
109
110 const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
111 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
112 const auto *PrevInstrMeta = InstrMeta;
113
114 // 0xDEADBEEF + 1: mov $0x0, %al
115 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
116 EXPECT_NE(nullptr, InstrMeta);
117 EXPECT_EQ(NextInstrMeta, InstrMeta);
118 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
119 EXPECT_EQ(2u, InstrMeta->InstructionSize);
120 EXPECT_TRUE(InstrMeta->Valid);
121
122 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
123 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
124 PrevInstrMeta = InstrMeta;
125
126 // 0xDEADBEEF + 3: mov %rsp, %rbp
127 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
128 EXPECT_NE(nullptr, InstrMeta);
129 EXPECT_EQ(NextInstrMeta, InstrMeta);
130 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
131 EXPECT_EQ(3u, InstrMeta->InstructionSize);
132 EXPECT_TRUE(InstrMeta->Valid);
133
134 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
135 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
136 PrevInstrMeta = InstrMeta;
137
138 // 0xDEADBEEF + 6: sub $0x18, %rsp
139 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
140 EXPECT_NE(nullptr, InstrMeta);
141 EXPECT_EQ(NextInstrMeta, InstrMeta);
142 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
143 EXPECT_EQ(4u, InstrMeta->InstructionSize);
144 EXPECT_TRUE(InstrMeta->Valid);
145
146 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
147 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
148 PrevInstrMeta = InstrMeta;
149
150 // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
151 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
152 EXPECT_NE(nullptr, InstrMeta);
153 EXPECT_EQ(NextInstrMeta, InstrMeta);
154 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
155 EXPECT_EQ(10u, InstrMeta->InstructionSize);
156 EXPECT_TRUE(InstrMeta->Valid);
157
158 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
159 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
160 PrevInstrMeta = InstrMeta;
161
162 // 0xDEADBEEF + 20: (bad)
163 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
164 EXPECT_NE(nullptr, InstrMeta);
165 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
166 EXPECT_EQ(1u, InstrMeta->InstructionSize);
167 EXPECT_FALSE(InstrMeta->Valid);
168
169 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
170 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
171
172 // 0xDEADBEEF + 21: rex.B (bad)
173 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
174 EXPECT_NE(nullptr, InstrMeta);
175 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
176 EXPECT_EQ(2u, InstrMeta->InstructionSize);
177 EXPECT_FALSE(InstrMeta->Valid);
178
179 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
180 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
181
182 // 0xDEADBEEF + 6: (bad) {%k1}
183 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
184 EXPECT_NE(nullptr, InstrMeta);
185 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
186 EXPECT_EQ(5u, InstrMeta->InstructionSize);
187 EXPECT_FALSE(InstrMeta->Valid);
188
189 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
190 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
191}
192
193TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000194 if (!SuccessfullyInitialised)
195 return;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +0000196 Analysis.parseSectionContents(
197 {
198 0x90, // 0: nop
199 0x2f, // 1: (bad)
200 0x90 // 2: nop
201 },
202 0xDEADBEEF);
203 const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
204 const auto *GoodInstrMeta =
205 Analysis.getPrevInstructionSequential(BadInstrMeta);
206 EXPECT_NE(nullptr, GoodInstrMeta);
207 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
208 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
209
210 GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
211 EXPECT_NE(nullptr, GoodInstrMeta);
212 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
213 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
214}
215
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000216TEST_F(BasicFileAnalysisTest, CFITrapTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000217 if (!SuccessfullyInitialised)
218 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000219 Analysis.parseSectionContents(
220 {
221 0x90, // 0: nop
222 0xb0, 0x00, // 1: mov $0x0, %al
223 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
224 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
225 0x48, 0xbe, 0xc4, 0x07, 0x40,
226 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
227 0x2f, // 20: (bad)
228 0x41, 0x0e, // 21: rex.B (bad)
229 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
230 0x0f, 0x0b // 28: ud2
231 },
232 0xDEADBEEF);
233
234 EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
235 EXPECT_FALSE(
236 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
237 EXPECT_FALSE(
238 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
239 EXPECT_FALSE(
240 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
241 EXPECT_FALSE(
242 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
243 EXPECT_FALSE(
244 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
245 EXPECT_FALSE(
246 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
247 EXPECT_TRUE(
248 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
249}
250
251TEST_F(BasicFileAnalysisTest, FallThroughTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000252 if (!SuccessfullyInitialised)
253 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000254 Analysis.parseSectionContents(
255 {
256 0x90, // 0: nop
257 0xb0, 0x00, // 1: mov $0x0, %al
258 0x2f, // 3: (bad)
259 0x0f, 0x0b, // 4: ud2
260 0xff, 0x20, // 6: jmpq *(%rax)
261 0xeb, 0x00, // 8: jmp +0
262 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
263 0xff, 0x10, // 15: callq *(rax)
264 0x75, 0x00, // 17: jne +0
265 0xc3, // 19: retq
266 },
267 0xDEADBEEF);
268
269 EXPECT_TRUE(
270 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
271 EXPECT_TRUE(
272 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
273 EXPECT_FALSE(
274 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
275 EXPECT_FALSE(
276 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
277 EXPECT_FALSE(
278 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
279 EXPECT_FALSE(
280 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
281 EXPECT_FALSE(
282 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
283 EXPECT_FALSE(
284 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
285 EXPECT_TRUE(
286 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
287 EXPECT_FALSE(
288 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
289}
290
291TEST_F(BasicFileAnalysisTest, DefiniteNextInstructionTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000292 if (!SuccessfullyInitialised)
293 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000294 Analysis.parseSectionContents(
295 {
296 0x90, // 0: nop
297 0xb0, 0x00, // 1: mov $0x0, %al
298 0x2f, // 3: (bad)
299 0x0f, 0x0b, // 4: ud2
300 0xff, 0x20, // 6: jmpq *(%rax)
301 0xeb, 0x00, // 8: jmp 10 [+0]
302 0xeb, 0x05, // 10: jmp 17 [+5]
303 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
304 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
305 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
306 0xff, 0x10, // 27: callq *(rax)
307 0x75, 0x00, // 29: jne 31 [+0]
308 0x75, 0xe0, // 31: jne 1 [-32]
309 0xc3, // 33: retq
310 0xeb, 0xdd, // 34: jmp 1 [-35]
311 0xeb, 0xdd, // 36: jmp 3 [-35]
312 0xeb, 0xdc, // 38: jmp 4 [-36]
313 },
314 0xDEADBEEF);
315
316 const auto *Current = Analysis.getInstruction(0xDEADBEEF);
317 const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
318 EXPECT_NE(nullptr, Next);
319 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
320
321 Current = Analysis.getInstruction(0xDEADBEEF + 1);
322 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
323
324 Current = Analysis.getInstruction(0xDEADBEEF + 3);
325 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
326
327 Current = Analysis.getInstruction(0xDEADBEEF + 4);
328 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
329
330 Current = Analysis.getInstruction(0xDEADBEEF + 6);
331 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
332
333 Current = Analysis.getInstruction(0xDEADBEEF + 8);
334 Next = Analysis.getDefiniteNextInstruction(*Current);
335 EXPECT_NE(nullptr, Next);
336 EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
337
338 Current = Analysis.getInstruction(0xDEADBEEF + 10);
339 Next = Analysis.getDefiniteNextInstruction(*Current);
340 EXPECT_NE(nullptr, Next);
341 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
342
343 Current = Analysis.getInstruction(0xDEADBEEF + 12);
344 Next = Analysis.getDefiniteNextInstruction(*Current);
345 EXPECT_NE(nullptr, Next);
346 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
347
348 Current = Analysis.getInstruction(0xDEADBEEF + 17);
349 // Note, definite next instruction address is out of range and should fail.
350 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
351 Next = Analysis.getDefiniteNextInstruction(*Current);
352
353 Current = Analysis.getInstruction(0xDEADBEEF + 22);
354 Next = Analysis.getDefiniteNextInstruction(*Current);
355 EXPECT_NE(nullptr, Next);
356 EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
357
358 Current = Analysis.getInstruction(0xDEADBEEF + 27);
359 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
360 Current = Analysis.getInstruction(0xDEADBEEF + 29);
361 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
362 Current = Analysis.getInstruction(0xDEADBEEF + 31);
363 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
364 Current = Analysis.getInstruction(0xDEADBEEF + 33);
365 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
366
367 Current = Analysis.getInstruction(0xDEADBEEF + 34);
368 Next = Analysis.getDefiniteNextInstruction(*Current);
369 EXPECT_NE(nullptr, Next);
370 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
371
372 Current = Analysis.getInstruction(0xDEADBEEF + 36);
373 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
374
375 Current = Analysis.getInstruction(0xDEADBEEF + 38);
376 Next = Analysis.getDefiniteNextInstruction(*Current);
377 EXPECT_NE(nullptr, Next);
378 EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
379}
380
381TEST_F(BasicFileAnalysisTest, ControlFlowXRefsTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000382 if (!SuccessfullyInitialised)
383 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000384 Analysis.parseSectionContents(
385 {
386 0x90, // 0: nop
387 0xb0, 0x00, // 1: mov $0x0, %al
388 0x2f, // 3: (bad)
389 0x0f, 0x0b, // 4: ud2
390 0xff, 0x20, // 6: jmpq *(%rax)
391 0xeb, 0x00, // 8: jmp 10 [+0]
392 0xeb, 0x05, // 10: jmp 17 [+5]
393 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
394 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
395 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
396 0xff, 0x10, // 27: callq *(rax)
397 0x75, 0x00, // 29: jne 31 [+0]
398 0x75, 0xe0, // 31: jne 1 [-32]
399 0xc3, // 33: retq
400 0xeb, 0xdd, // 34: jmp 1 [-35]
401 0xeb, 0xdd, // 36: jmp 3 [-35]
402 0xeb, 0xdc, // 38: jmp 4 [-36]
403 },
404 0xDEADBEEF);
405 const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
406 std::set<const Instr *> XRefs =
407 Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
408 EXPECT_TRUE(XRefs.empty());
409
410 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
411 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
412 EXPECT_THAT(XRefs, UnorderedElementsAre(
413 Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
414 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
415 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
416
417 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
418 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
419 EXPECT_THAT(XRefs, UnorderedElementsAre(
420 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
421 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
422
423 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
424 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
425 EXPECT_THAT(XRefs, UnorderedElementsAre(
426 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
427
428 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
429 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
430
431 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
432 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
433 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
434
435 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
436 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
437 EXPECT_THAT(XRefs, UnorderedElementsAre(
438 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
439
440 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
441 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
442 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
443
444 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
445 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
446 EXPECT_THAT(XRefs, UnorderedElementsAre(
447 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
448 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
449
450 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
451 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
452 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
453
454 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
455 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
456 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
457
458 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
459 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
460 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
461
462 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
463 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
464 EXPECT_THAT(XRefs, UnorderedElementsAre(
465 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
466 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
467
468 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
469 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
470 EXPECT_THAT(XRefs, UnorderedElementsAre(
471 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
472
473 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
474 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
475 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
476
477 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
478 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
479 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
480
481 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
482 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
483 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
484}
485
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000486TEST_F(BasicFileAnalysisTest, CFIProtectionInvalidTargets) {
487 if (!SuccessfullyInitialised)
488 return;
489 Analysis.parseSectionContents(
490 {
491 0x90, // 0: nop
492 0x0f, 0x0b, // 1: ud2
493 0x75, 0x00, // 3: jne 5 [+0]
494 },
495 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000496 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF);
497 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
498 Analysis.validateCFIProtection(Result));
499 Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1);
500 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
501 Analysis.validateCFIProtection(Result));
502 Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3);
503 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
504 Analysis.validateCFIProtection(Result));
505 Result = GraphBuilder::buildFlowGraph(Analysis, 0x12345678);
506 EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,
507 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000508}
509
510TEST_F(BasicFileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
511 if (!SuccessfullyInitialised)
512 return;
513 Analysis.parseSectionContents(
514 {
515 0x75, 0x02, // 0: jne 4 [+2]
516 0x0f, 0x0b, // 2: ud2
517 0xff, 0x10, // 4: callq *(%rax)
518 },
519 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000520 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4);
521 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
522 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000523}
524
525TEST_F(BasicFileAnalysisTest, CFIProtectionBasicJumpToUd2) {
526 if (!SuccessfullyInitialised)
527 return;
528 Analysis.parseSectionContents(
529 {
530 0x75, 0x02, // 0: jne 4 [+2]
531 0xff, 0x10, // 2: callq *(%rax)
532 0x0f, 0x0b, // 4: ud2
533 },
534 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000535 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2);
536 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
537 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000538}
539
540TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathUd2) {
541 if (!SuccessfullyInitialised)
542 return;
543 Analysis.parseSectionContents(
544 {
545 0x75, 0x03, // 0: jne 5 [+3]
546 0x90, // 2: nop
547 0xff, 0x10, // 3: callq *(%rax)
548 0x0f, 0x0b, // 5: ud2
549 0x75, 0xf9, // 7: jne 2 [-7]
550 0x0f, 0x0b, // 9: ud2
551 },
552 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000553 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3);
554 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
555 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000556}
557
558TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathSingleUd2) {
559 if (!SuccessfullyInitialised)
560 return;
561 Analysis.parseSectionContents(
562 {
563 0x75, 0x05, // 0: jne 7 [+5]
564 0x90, // 2: nop
565 0xff, 0x10, // 3: callq *(%rax)
566 0x75, 0xfb, // 5: jne 2 [-5]
567 0x0f, 0x0b, // 7: ud2
568 },
569 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000570 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3);
571 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
572 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000573}
574
575TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
576 if (!SuccessfullyInitialised)
577 return;
578 Analysis.parseSectionContents(
579 {
580 0x75, 0x06, // 0: jne 8 [+6]
581 0x90, // 2: nop
582 0x90, // 3: nop
583 0x90, // 4: nop
584 0x90, // 5: nop
585 0xff, 0x10, // 6: callq *(%rax)
586 0x0f, 0x0b, // 8: ud2
587 },
588 0xDEADBEEF);
589 uint64_t PrevSearchLengthForConditionalBranch =
590 SearchLengthForConditionalBranch;
591 SearchLengthForConditionalBranch = 2;
592
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000593 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6);
594 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
595 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000596
597 SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
598}
599
600TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
601 if (!SuccessfullyInitialised)
602 return;
603 Analysis.parseSectionContents(
604 {
605 0x75, 0x02, // 0: jne 4 [+2]
606 0xff, 0x10, // 2: callq *(%rax)
607 0x90, // 4: nop
608 0x90, // 5: nop
609 0x90, // 6: nop
610 0x90, // 7: nop
611 0x0f, 0x0b, // 8: ud2
612 },
613 0xDEADBEEF);
614 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
615 SearchLengthForUndef = 2;
616
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000617 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2);
618 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
619 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000620
621 SearchLengthForUndef = PrevSearchLengthForUndef;
622}
623
624TEST_F(BasicFileAnalysisTest, CFIProtectionGoodAndBadPaths) {
625 if (!SuccessfullyInitialised)
626 return;
627 Analysis.parseSectionContents(
628 {
629 0xeb, 0x02, // 0: jmp 4 [+2]
630 0x75, 0x02, // 2: jne 6 [+2]
631 0xff, 0x10, // 4: callq *(%rax)
632 0x0f, 0x0b, // 6: ud2
633 },
634 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000635 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4);
636 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
637 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000638}
639
640TEST_F(BasicFileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
641 if (!SuccessfullyInitialised)
642 return;
643 Analysis.parseSectionContents(
644 {
645 0x75, 0x04, // 0: jne 6 [+4]
646 0xeb, 0x00, // 2: jmp 4 [+0]
647 0xff, 0x10, // 4: callq *(%rax)
648 0x0f, 0x0b, // 6: ud2
649 },
650 0xDEADBEEF);
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000651 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4);
652 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
653 Analysis.validateCFIProtection(Result));
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000654}
655
656TEST_F(BasicFileAnalysisTest, CFIProtectionComplexExample) {
657 if (!SuccessfullyInitialised)
658 return;
659 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
660 // graph.
661 Analysis.parseSectionContents(
662 {
663 0x75, 0x12, // 0: jne 20 [+18]
664 0xeb, 0x03, // 2: jmp 7 [+3]
665 0x75, 0x10, // 4: jne 22 [+16]
666 0x90, // 6: nop
667 0x90, // 7: nop
668 0x90, // 8: nop
669 0xff, 0x10, // 9: callq *(%rax)
670 0xeb, 0xfc, // 11: jmp 9 [-4]
671 0x75, 0xfa, // 13: jne 9 [-6]
672 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
673 0x90, // 20: nop
674 0x90, // 21: nop
675 0x0f, 0x0b, // 22: ud2
676 },
677 0xDEADBEEF);
Mitch Phillips189ebb62017-11-03 20:00:05 +0000678 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
679 SearchLengthForUndef = 5;
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000680 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9);
681 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
682 Analysis.validateCFIProtection(Result));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000683 SearchLengthForUndef = PrevSearchLengthForUndef;
684}
685
686TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTest) {
687 Analysis.parseSectionContents(
688 {
689 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
690 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
691 0xff, 0xd0, // 0x68811d: callq *%rax
692 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
693 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
694 0x0f, 0x0b, // 0x688127: ud2
695 },
696 0x688118);
697 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
698 SearchLengthForUndef = 1;
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000699 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x68811d);
700 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
701 Analysis.validateCFIProtection(Result));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000702 SearchLengthForUndef = PrevSearchLengthForUndef;
703}
704
705TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTestFarAway) {
706 Analysis.parseSectionContents(
707 {
708 0x74, 0x73, // 0x7759eb: je 0x775a60
709 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
710 },
711 0x7759eb);
712
713 Analysis.parseSectionContents(
714 {
715 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
716 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
717 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
718 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
719 0xff, 0xd1, // 0x775a68: callq *%rcx
720 },
721 0x775a56);
722
723 Analysis.parseSectionContents(
724 {
725 0x0f, 0x0b, // 0x775e0e: ud2
726 },
727 0x775e0e);
728 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
729 SearchLengthForUndef = 1;
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000730 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68);
731 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
732 Analysis.validateCFIProtection(Result));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000733 SearchLengthForUndef = 2;
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000734 Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68);
735 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
736 Analysis.validateCFIProtection(Result));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000737 SearchLengthForUndef = 3;
Mitch Phillips3b9ea322017-11-10 21:00:22 +0000738 Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68);
739 EXPECT_EQ(CFIProtectionStatus::PROTECTED,
740 Analysis.validateCFIProtection(Result));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000741 SearchLengthForUndef = PrevSearchLengthForUndef;
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000742}
743
Mitch Phillips2e7be2a2017-11-15 00:35:26 +0000744TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
745 if (!SuccessfullyInitialised)
746 return;
747 Analysis.parseSectionContents(
748 {
749 0x75, 0x02, // 0: jne 4 [+2]
750 0x0f, 0x0b, // 2: ud2
751 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
752 0xff, 0x10, // 10: callq *(%rax)
753 },
754 0xDEADBEEF);
755 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 10);
756 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
757 Analysis.validateCFIProtection(Result));
758}
759
760TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
761 if (!SuccessfullyInitialised)
762 return;
763 Analysis.parseSectionContents(
764 {
765 0x75, 0x02, // 0: jne 4 [+2]
766 0x0f, 0x0b, // 2: ud2
767 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
768 0xff, 0x10, // 8: callq *(%rax)
769 },
770 0xDEADBEEF);
771 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8);
772 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
773 Analysis.validateCFIProtection(Result));
774}
775
776TEST_F(BasicFileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
777 if (!SuccessfullyInitialised)
778 return;
779 Analysis.parseSectionContents(
780 {
781 0x75, 0x02, // 0: jne 4 [+2]
782 0x0f, 0x0b, // 2: ud2
783 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
784 0xff, 0x10, // 9: callq *(%rax)
785 },
786 0xDEADBEEF);
787 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9);
788 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
789 Analysis.validateCFIProtection(Result));
790}
791
792TEST_F(BasicFileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
793 if (!SuccessfullyInitialised)
794 return;
795 Analysis.parseSectionContents(
796 {
797 0x75, 0x04, // 0: jne 6 [+4]
798 0x0f, 0x31, // 2: rdtsc (note: affects eax)
799 0xff, 0x10, // 4: callq *(%rax)
800 0x0f, 0x0b, // 6: ud2
801 0x75, 0xf9, // 8: jne 2 [-7]
802 0x0f, 0x0b, // 10: ud2
803 },
804 0xDEADBEEF);
805 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4);
806 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
807 Analysis.validateCFIProtection(Result));
808}
809
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +0000810} // anonymous namespace
811} // end namespace cfi_verify
812} // end namespace llvm
813
814int main(int argc, char **argv) {
815 ::testing::InitGoogleTest(&argc, argv);
816 llvm::cl::ParseCommandLineOptions(argc, argv);
817
818 llvm::InitializeAllTargetInfos();
819 llvm::InitializeAllTargetMCs();
820 llvm::InitializeAllAsmParsers();
821 llvm::InitializeAllDisassemblers();
822
823 return RUN_ALL_TESTS();
824}