blob: 00346ab5a14e6e8622bd208839aa81a447106d1d [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);
496 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF));
497 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 1));
498 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
499 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADC0DE));
500}
501
502TEST_F(BasicFileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
503 if (!SuccessfullyInitialised)
504 return;
505 Analysis.parseSectionContents(
506 {
507 0x75, 0x02, // 0: jne 4 [+2]
508 0x0f, 0x0b, // 2: ud2
509 0xff, 0x10, // 4: callq *(%rax)
510 },
511 0xDEADBEEF);
512 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
513}
514
515TEST_F(BasicFileAnalysisTest, CFIProtectionBasicJumpToUd2) {
516 if (!SuccessfullyInitialised)
517 return;
518 Analysis.parseSectionContents(
519 {
520 0x75, 0x02, // 0: jne 4 [+2]
521 0xff, 0x10, // 2: callq *(%rax)
522 0x0f, 0x0b, // 4: ud2
523 },
524 0xDEADBEEF);
525 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 2));
526}
527
528TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathUd2) {
529 if (!SuccessfullyInitialised)
530 return;
531 Analysis.parseSectionContents(
532 {
533 0x75, 0x03, // 0: jne 5 [+3]
534 0x90, // 2: nop
535 0xff, 0x10, // 3: callq *(%rax)
536 0x0f, 0x0b, // 5: ud2
537 0x75, 0xf9, // 7: jne 2 [-7]
538 0x0f, 0x0b, // 9: ud2
539 },
540 0xDEADBEEF);
541 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
542}
543
544TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathSingleUd2) {
545 if (!SuccessfullyInitialised)
546 return;
547 Analysis.parseSectionContents(
548 {
549 0x75, 0x05, // 0: jne 7 [+5]
550 0x90, // 2: nop
551 0xff, 0x10, // 3: callq *(%rax)
552 0x75, 0xfb, // 5: jne 2 [-5]
553 0x0f, 0x0b, // 7: ud2
554 },
555 0xDEADBEEF);
556 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
557}
558
559TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
560 if (!SuccessfullyInitialised)
561 return;
562 Analysis.parseSectionContents(
563 {
564 0x75, 0x06, // 0: jne 8 [+6]
565 0x90, // 2: nop
566 0x90, // 3: nop
567 0x90, // 4: nop
568 0x90, // 5: nop
569 0xff, 0x10, // 6: callq *(%rax)
570 0x0f, 0x0b, // 8: ud2
571 },
572 0xDEADBEEF);
573 uint64_t PrevSearchLengthForConditionalBranch =
574 SearchLengthForConditionalBranch;
575 SearchLengthForConditionalBranch = 2;
576
577 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 6));
578
579 SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
580}
581
582TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
583 if (!SuccessfullyInitialised)
584 return;
585 Analysis.parseSectionContents(
586 {
587 0x75, 0x02, // 0: jne 4 [+2]
588 0xff, 0x10, // 2: callq *(%rax)
589 0x90, // 4: nop
590 0x90, // 5: nop
591 0x90, // 6: nop
592 0x90, // 7: nop
593 0x0f, 0x0b, // 8: ud2
594 },
595 0xDEADBEEF);
596 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
597 SearchLengthForUndef = 2;
598
599 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 2));
600
601 SearchLengthForUndef = PrevSearchLengthForUndef;
602}
603
604TEST_F(BasicFileAnalysisTest, CFIProtectionGoodAndBadPaths) {
605 if (!SuccessfullyInitialised)
606 return;
607 Analysis.parseSectionContents(
608 {
609 0xeb, 0x02, // 0: jmp 4 [+2]
610 0x75, 0x02, // 2: jne 6 [+2]
611 0xff, 0x10, // 4: callq *(%rax)
612 0x0f, 0x0b, // 6: ud2
613 },
614 0xDEADBEEF);
615 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
616}
617
618TEST_F(BasicFileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
619 if (!SuccessfullyInitialised)
620 return;
621 Analysis.parseSectionContents(
622 {
623 0x75, 0x04, // 0: jne 6 [+4]
624 0xeb, 0x00, // 2: jmp 4 [+0]
625 0xff, 0x10, // 4: callq *(%rax)
626 0x0f, 0x0b, // 6: ud2
627 },
628 0xDEADBEEF);
629 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
630}
631
632TEST_F(BasicFileAnalysisTest, CFIProtectionComplexExample) {
633 if (!SuccessfullyInitialised)
634 return;
635 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
636 // graph.
637 Analysis.parseSectionContents(
638 {
639 0x75, 0x12, // 0: jne 20 [+18]
640 0xeb, 0x03, // 2: jmp 7 [+3]
641 0x75, 0x10, // 4: jne 22 [+16]
642 0x90, // 6: nop
643 0x90, // 7: nop
644 0x90, // 8: nop
645 0xff, 0x10, // 9: callq *(%rax)
646 0xeb, 0xfc, // 11: jmp 9 [-4]
647 0x75, 0xfa, // 13: jne 9 [-6]
648 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
649 0x90, // 20: nop
650 0x90, // 21: nop
651 0x0f, 0x0b, // 22: ud2
652 },
653 0xDEADBEEF);
Mitch Phillips189ebb62017-11-03 20:00:05 +0000654 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
655 SearchLengthForUndef = 5;
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000656 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 9));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000657 SearchLengthForUndef = PrevSearchLengthForUndef;
658}
659
660TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTest) {
661 Analysis.parseSectionContents(
662 {
663 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
664 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
665 0xff, 0xd0, // 0x68811d: callq *%rax
666 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
667 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
668 0x0f, 0x0b, // 0x688127: ud2
669 },
670 0x688118);
671 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
672 SearchLengthForUndef = 1;
673 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x68811d));
674 SearchLengthForUndef = PrevSearchLengthForUndef;
675}
676
677TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTestFarAway) {
678 Analysis.parseSectionContents(
679 {
680 0x74, 0x73, // 0x7759eb: je 0x775a60
681 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
682 },
683 0x7759eb);
684
685 Analysis.parseSectionContents(
686 {
687 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
688 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
689 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
690 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
691 0xff, 0xd1, // 0x775a68: callq *%rcx
692 },
693 0x775a56);
694
695 Analysis.parseSectionContents(
696 {
697 0x0f, 0x0b, // 0x775e0e: ud2
698 },
699 0x775e0e);
700 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
701 SearchLengthForUndef = 1;
702 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
703 SearchLengthForUndef = 2;
704 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
705 SearchLengthForUndef = 3;
706 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
707 SearchLengthForUndef = PrevSearchLengthForUndef;
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000708}
709
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +0000710} // anonymous namespace
711} // end namespace cfi_verify
712} // end namespace llvm
713
714int main(int argc, char **argv) {
715 ::testing::InitGoogleTest(&argc, argv);
716 llvm::cl::ParseCommandLineOptions(argc, argv);
717
718 llvm::InitializeAllTargetInfos();
719 llvm::InitializeAllTargetMCs();
720 llvm::InitializeAllAsmParsers();
721 llvm::InitializeAllDisassemblers();
722
723 return RUN_ALL_TESTS();
724}