blob: a3da1fc3f56da6aa3774615473337f734196813a [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 Phillipsd9af3832017-10-23 20:54:01 +000067 SuccessfullyInitialised = true;
68 if (auto Err = Analysis.initialiseDisassemblyMembers()) {
69 handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
70 SuccessfullyInitialised = false;
71 outs()
72 << "Note: CFIVerifyTests are disabled due to lack of x86 support "
73 "on this build.\n";
74 });
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000075 }
76 }
77
Mitch Phillipsd9af3832017-10-23 20:54:01 +000078 bool SuccessfullyInitialised;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000079 ELFx86TestFileAnalysis Analysis;
80};
81
82TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +000083 if (!SuccessfullyInitialised)
84 return;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000085 Analysis.parseSectionContents(
86 {
87 0x90, // 0: nop
88 0xb0, 0x00, // 1: mov $0x0, %al
89 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
90 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
91 0x48, 0xbe, 0xc4, 0x07, 0x40,
92 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
93 0x2f, // 20: (bad)
94 0x41, 0x0e, // 21: rex.B (bad)
95 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
96 },
97 0xDEADBEEF);
98
99 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
100 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
101
102 // 0xDEADBEEF: nop
103 const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
104 EXPECT_NE(nullptr, InstrMeta);
105 EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
106 EXPECT_EQ(1u, InstrMeta->InstructionSize);
107 EXPECT_TRUE(InstrMeta->Valid);
108
109 const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
110 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
111 const auto *PrevInstrMeta = InstrMeta;
112
113 // 0xDEADBEEF + 1: mov $0x0, %al
114 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
115 EXPECT_NE(nullptr, InstrMeta);
116 EXPECT_EQ(NextInstrMeta, InstrMeta);
117 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
118 EXPECT_EQ(2u, InstrMeta->InstructionSize);
119 EXPECT_TRUE(InstrMeta->Valid);
120
121 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
122 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
123 PrevInstrMeta = InstrMeta;
124
125 // 0xDEADBEEF + 3: mov %rsp, %rbp
126 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
127 EXPECT_NE(nullptr, InstrMeta);
128 EXPECT_EQ(NextInstrMeta, InstrMeta);
129 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
130 EXPECT_EQ(3u, InstrMeta->InstructionSize);
131 EXPECT_TRUE(InstrMeta->Valid);
132
133 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
134 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
135 PrevInstrMeta = InstrMeta;
136
137 // 0xDEADBEEF + 6: sub $0x18, %rsp
138 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
139 EXPECT_NE(nullptr, InstrMeta);
140 EXPECT_EQ(NextInstrMeta, InstrMeta);
141 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
142 EXPECT_EQ(4u, InstrMeta->InstructionSize);
143 EXPECT_TRUE(InstrMeta->Valid);
144
145 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
146 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
147 PrevInstrMeta = InstrMeta;
148
149 // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
150 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
151 EXPECT_NE(nullptr, InstrMeta);
152 EXPECT_EQ(NextInstrMeta, InstrMeta);
153 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
154 EXPECT_EQ(10u, InstrMeta->InstructionSize);
155 EXPECT_TRUE(InstrMeta->Valid);
156
157 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
158 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
159 PrevInstrMeta = InstrMeta;
160
161 // 0xDEADBEEF + 20: (bad)
162 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
163 EXPECT_NE(nullptr, InstrMeta);
164 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
165 EXPECT_EQ(1u, InstrMeta->InstructionSize);
166 EXPECT_FALSE(InstrMeta->Valid);
167
168 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
169 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
170
171 // 0xDEADBEEF + 21: rex.B (bad)
172 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
173 EXPECT_NE(nullptr, InstrMeta);
174 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
175 EXPECT_EQ(2u, InstrMeta->InstructionSize);
176 EXPECT_FALSE(InstrMeta->Valid);
177
178 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
179 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
180
181 // 0xDEADBEEF + 6: (bad) {%k1}
182 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
183 EXPECT_NE(nullptr, InstrMeta);
184 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
185 EXPECT_EQ(5u, InstrMeta->InstructionSize);
186 EXPECT_FALSE(InstrMeta->Valid);
187
188 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
189 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
190}
191
192TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000193 if (!SuccessfullyInitialised)
194 return;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +0000195 Analysis.parseSectionContents(
196 {
197 0x90, // 0: nop
198 0x2f, // 1: (bad)
199 0x90 // 2: nop
200 },
201 0xDEADBEEF);
202 const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
203 const auto *GoodInstrMeta =
204 Analysis.getPrevInstructionSequential(BadInstrMeta);
205 EXPECT_NE(nullptr, GoodInstrMeta);
206 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
207 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
208
209 GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
210 EXPECT_NE(nullptr, GoodInstrMeta);
211 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
212 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
213}
214
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000215TEST_F(BasicFileAnalysisTest, CFITrapTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000216 if (!SuccessfullyInitialised)
217 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000218 Analysis.parseSectionContents(
219 {
220 0x90, // 0: nop
221 0xb0, 0x00, // 1: mov $0x0, %al
222 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
223 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
224 0x48, 0xbe, 0xc4, 0x07, 0x40,
225 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
226 0x2f, // 20: (bad)
227 0x41, 0x0e, // 21: rex.B (bad)
228 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
229 0x0f, 0x0b // 28: ud2
230 },
231 0xDEADBEEF);
232
233 EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
234 EXPECT_FALSE(
235 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
236 EXPECT_FALSE(
237 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
238 EXPECT_FALSE(
239 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
240 EXPECT_FALSE(
241 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
242 EXPECT_FALSE(
243 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
244 EXPECT_FALSE(
245 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
246 EXPECT_TRUE(
247 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
248}
249
250TEST_F(BasicFileAnalysisTest, FallThroughTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000251 if (!SuccessfullyInitialised)
252 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000253 Analysis.parseSectionContents(
254 {
255 0x90, // 0: nop
256 0xb0, 0x00, // 1: mov $0x0, %al
257 0x2f, // 3: (bad)
258 0x0f, 0x0b, // 4: ud2
259 0xff, 0x20, // 6: jmpq *(%rax)
260 0xeb, 0x00, // 8: jmp +0
261 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
262 0xff, 0x10, // 15: callq *(rax)
263 0x75, 0x00, // 17: jne +0
264 0xc3, // 19: retq
265 },
266 0xDEADBEEF);
267
268 EXPECT_TRUE(
269 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
270 EXPECT_TRUE(
271 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
272 EXPECT_FALSE(
273 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
274 EXPECT_FALSE(
275 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
276 EXPECT_FALSE(
277 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
278 EXPECT_FALSE(
279 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
280 EXPECT_FALSE(
281 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
282 EXPECT_FALSE(
283 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
284 EXPECT_TRUE(
285 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
286 EXPECT_FALSE(
287 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
288}
289
290TEST_F(BasicFileAnalysisTest, DefiniteNextInstructionTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000291 if (!SuccessfullyInitialised)
292 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000293 Analysis.parseSectionContents(
294 {
295 0x90, // 0: nop
296 0xb0, 0x00, // 1: mov $0x0, %al
297 0x2f, // 3: (bad)
298 0x0f, 0x0b, // 4: ud2
299 0xff, 0x20, // 6: jmpq *(%rax)
300 0xeb, 0x00, // 8: jmp 10 [+0]
301 0xeb, 0x05, // 10: jmp 17 [+5]
302 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
303 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
304 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
305 0xff, 0x10, // 27: callq *(rax)
306 0x75, 0x00, // 29: jne 31 [+0]
307 0x75, 0xe0, // 31: jne 1 [-32]
308 0xc3, // 33: retq
309 0xeb, 0xdd, // 34: jmp 1 [-35]
310 0xeb, 0xdd, // 36: jmp 3 [-35]
311 0xeb, 0xdc, // 38: jmp 4 [-36]
312 },
313 0xDEADBEEF);
314
315 const auto *Current = Analysis.getInstruction(0xDEADBEEF);
316 const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
317 EXPECT_NE(nullptr, Next);
318 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
319
320 Current = Analysis.getInstruction(0xDEADBEEF + 1);
321 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
322
323 Current = Analysis.getInstruction(0xDEADBEEF + 3);
324 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
325
326 Current = Analysis.getInstruction(0xDEADBEEF + 4);
327 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
328
329 Current = Analysis.getInstruction(0xDEADBEEF + 6);
330 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
331
332 Current = Analysis.getInstruction(0xDEADBEEF + 8);
333 Next = Analysis.getDefiniteNextInstruction(*Current);
334 EXPECT_NE(nullptr, Next);
335 EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
336
337 Current = Analysis.getInstruction(0xDEADBEEF + 10);
338 Next = Analysis.getDefiniteNextInstruction(*Current);
339 EXPECT_NE(nullptr, Next);
340 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
341
342 Current = Analysis.getInstruction(0xDEADBEEF + 12);
343 Next = Analysis.getDefiniteNextInstruction(*Current);
344 EXPECT_NE(nullptr, Next);
345 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
346
347 Current = Analysis.getInstruction(0xDEADBEEF + 17);
348 // Note, definite next instruction address is out of range and should fail.
349 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
350 Next = Analysis.getDefiniteNextInstruction(*Current);
351
352 Current = Analysis.getInstruction(0xDEADBEEF + 22);
353 Next = Analysis.getDefiniteNextInstruction(*Current);
354 EXPECT_NE(nullptr, Next);
355 EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
356
357 Current = Analysis.getInstruction(0xDEADBEEF + 27);
358 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
359 Current = Analysis.getInstruction(0xDEADBEEF + 29);
360 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
361 Current = Analysis.getInstruction(0xDEADBEEF + 31);
362 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
363 Current = Analysis.getInstruction(0xDEADBEEF + 33);
364 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
365
366 Current = Analysis.getInstruction(0xDEADBEEF + 34);
367 Next = Analysis.getDefiniteNextInstruction(*Current);
368 EXPECT_NE(nullptr, Next);
369 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
370
371 Current = Analysis.getInstruction(0xDEADBEEF + 36);
372 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
373
374 Current = Analysis.getInstruction(0xDEADBEEF + 38);
375 Next = Analysis.getDefiniteNextInstruction(*Current);
376 EXPECT_NE(nullptr, Next);
377 EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
378}
379
380TEST_F(BasicFileAnalysisTest, ControlFlowXRefsTest) {
Mitch Phillipsd9af3832017-10-23 20:54:01 +0000381 if (!SuccessfullyInitialised)
382 return;
Vlad Tsyrklevich0ee26322017-10-11 23:17:29 +0000383 Analysis.parseSectionContents(
384 {
385 0x90, // 0: nop
386 0xb0, 0x00, // 1: mov $0x0, %al
387 0x2f, // 3: (bad)
388 0x0f, 0x0b, // 4: ud2
389 0xff, 0x20, // 6: jmpq *(%rax)
390 0xeb, 0x00, // 8: jmp 10 [+0]
391 0xeb, 0x05, // 10: jmp 17 [+5]
392 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
393 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
394 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
395 0xff, 0x10, // 27: callq *(rax)
396 0x75, 0x00, // 29: jne 31 [+0]
397 0x75, 0xe0, // 31: jne 1 [-32]
398 0xc3, // 33: retq
399 0xeb, 0xdd, // 34: jmp 1 [-35]
400 0xeb, 0xdd, // 36: jmp 3 [-35]
401 0xeb, 0xdc, // 38: jmp 4 [-36]
402 },
403 0xDEADBEEF);
404 const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
405 std::set<const Instr *> XRefs =
406 Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
407 EXPECT_TRUE(XRefs.empty());
408
409 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
410 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
411 EXPECT_THAT(XRefs, UnorderedElementsAre(
412 Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
413 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
414 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
415
416 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
417 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
418 EXPECT_THAT(XRefs, UnorderedElementsAre(
419 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
420 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
421
422 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
423 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
424 EXPECT_THAT(XRefs, UnorderedElementsAre(
425 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
426
427 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
428 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
429
430 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
431 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
432 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
433
434 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
435 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
436 EXPECT_THAT(XRefs, UnorderedElementsAre(
437 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
438
439 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
440 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
441 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
442
443 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
444 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
445 EXPECT_THAT(XRefs, UnorderedElementsAre(
446 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
447 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
448
449 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
450 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
451 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
452
453 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
454 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
455 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
456
457 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
458 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
459 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
460
461 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
462 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
463 EXPECT_THAT(XRefs, UnorderedElementsAre(
464 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
465 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
466
467 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
468 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
469 EXPECT_THAT(XRefs, UnorderedElementsAre(
470 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
471
472 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
473 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
474 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
475
476 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
477 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
478 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
479
480 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
481 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
482 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
483}
484
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000485TEST_F(BasicFileAnalysisTest, CFIProtectionInvalidTargets) {
486 if (!SuccessfullyInitialised)
487 return;
488 Analysis.parseSectionContents(
489 {
490 0x90, // 0: nop
491 0x0f, 0x0b, // 1: ud2
492 0x75, 0x00, // 3: jne 5 [+0]
493 },
494 0xDEADBEEF);
495 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF));
496 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 1));
497 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
498 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADC0DE));
499}
500
501TEST_F(BasicFileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
502 if (!SuccessfullyInitialised)
503 return;
504 Analysis.parseSectionContents(
505 {
506 0x75, 0x02, // 0: jne 4 [+2]
507 0x0f, 0x0b, // 2: ud2
508 0xff, 0x10, // 4: callq *(%rax)
509 },
510 0xDEADBEEF);
511 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
512}
513
514TEST_F(BasicFileAnalysisTest, CFIProtectionBasicJumpToUd2) {
515 if (!SuccessfullyInitialised)
516 return;
517 Analysis.parseSectionContents(
518 {
519 0x75, 0x02, // 0: jne 4 [+2]
520 0xff, 0x10, // 2: callq *(%rax)
521 0x0f, 0x0b, // 4: ud2
522 },
523 0xDEADBEEF);
524 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 2));
525}
526
527TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathUd2) {
528 if (!SuccessfullyInitialised)
529 return;
530 Analysis.parseSectionContents(
531 {
532 0x75, 0x03, // 0: jne 5 [+3]
533 0x90, // 2: nop
534 0xff, 0x10, // 3: callq *(%rax)
535 0x0f, 0x0b, // 5: ud2
536 0x75, 0xf9, // 7: jne 2 [-7]
537 0x0f, 0x0b, // 9: ud2
538 },
539 0xDEADBEEF);
540 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
541}
542
543TEST_F(BasicFileAnalysisTest, CFIProtectionDualPathSingleUd2) {
544 if (!SuccessfullyInitialised)
545 return;
546 Analysis.parseSectionContents(
547 {
548 0x75, 0x05, // 0: jne 7 [+5]
549 0x90, // 2: nop
550 0xff, 0x10, // 3: callq *(%rax)
551 0x75, 0xfb, // 5: jne 2 [-5]
552 0x0f, 0x0b, // 7: ud2
553 },
554 0xDEADBEEF);
555 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 3));
556}
557
558TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
559 if (!SuccessfullyInitialised)
560 return;
561 Analysis.parseSectionContents(
562 {
563 0x75, 0x06, // 0: jne 8 [+6]
564 0x90, // 2: nop
565 0x90, // 3: nop
566 0x90, // 4: nop
567 0x90, // 5: nop
568 0xff, 0x10, // 6: callq *(%rax)
569 0x0f, 0x0b, // 8: ud2
570 },
571 0xDEADBEEF);
572 uint64_t PrevSearchLengthForConditionalBranch =
573 SearchLengthForConditionalBranch;
574 SearchLengthForConditionalBranch = 2;
575
576 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 6));
577
578 SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
579}
580
581TEST_F(BasicFileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
582 if (!SuccessfullyInitialised)
583 return;
584 Analysis.parseSectionContents(
585 {
586 0x75, 0x02, // 0: jne 4 [+2]
587 0xff, 0x10, // 2: callq *(%rax)
588 0x90, // 4: nop
589 0x90, // 5: nop
590 0x90, // 6: nop
591 0x90, // 7: nop
592 0x0f, 0x0b, // 8: ud2
593 },
594 0xDEADBEEF);
595 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
596 SearchLengthForUndef = 2;
597
598 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 2));
599
600 SearchLengthForUndef = PrevSearchLengthForUndef;
601}
602
603TEST_F(BasicFileAnalysisTest, CFIProtectionGoodAndBadPaths) {
604 if (!SuccessfullyInitialised)
605 return;
606 Analysis.parseSectionContents(
607 {
608 0xeb, 0x02, // 0: jmp 4 [+2]
609 0x75, 0x02, // 2: jne 6 [+2]
610 0xff, 0x10, // 4: callq *(%rax)
611 0x0f, 0x0b, // 6: ud2
612 },
613 0xDEADBEEF);
614 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
615}
616
617TEST_F(BasicFileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
618 if (!SuccessfullyInitialised)
619 return;
620 Analysis.parseSectionContents(
621 {
622 0x75, 0x04, // 0: jne 6 [+4]
623 0xeb, 0x00, // 2: jmp 4 [+0]
624 0xff, 0x10, // 4: callq *(%rax)
625 0x0f, 0x0b, // 6: ud2
626 },
627 0xDEADBEEF);
628 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 4));
629}
630
631TEST_F(BasicFileAnalysisTest, CFIProtectionComplexExample) {
632 if (!SuccessfullyInitialised)
633 return;
634 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
635 // graph.
636 Analysis.parseSectionContents(
637 {
638 0x75, 0x12, // 0: jne 20 [+18]
639 0xeb, 0x03, // 2: jmp 7 [+3]
640 0x75, 0x10, // 4: jne 22 [+16]
641 0x90, // 6: nop
642 0x90, // 7: nop
643 0x90, // 8: nop
644 0xff, 0x10, // 9: callq *(%rax)
645 0xeb, 0xfc, // 11: jmp 9 [-4]
646 0x75, 0xfa, // 13: jne 9 [-6]
647 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
648 0x90, // 20: nop
649 0x90, // 21: nop
650 0x0f, 0x0b, // 22: ud2
651 },
652 0xDEADBEEF);
Mitch Phillips189ebb62017-11-03 20:00:05 +0000653 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
654 SearchLengthForUndef = 5;
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000655 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0xDEADBEEF + 9));
Mitch Phillips189ebb62017-11-03 20:00:05 +0000656 SearchLengthForUndef = PrevSearchLengthForUndef;
657}
658
659TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTest) {
660 Analysis.parseSectionContents(
661 {
662 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
663 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
664 0xff, 0xd0, // 0x68811d: callq *%rax
665 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
666 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
667 0x0f, 0x0b, // 0x688127: ud2
668 },
669 0x688118);
670 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
671 SearchLengthForUndef = 1;
672 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x68811d));
673 SearchLengthForUndef = PrevSearchLengthForUndef;
674}
675
676TEST_F(BasicFileAnalysisTest, UndefSearchLengthOneTestFarAway) {
677 Analysis.parseSectionContents(
678 {
679 0x74, 0x73, // 0x7759eb: je 0x775a60
680 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
681 },
682 0x7759eb);
683
684 Analysis.parseSectionContents(
685 {
686 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
687 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
688 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
689 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
690 0xff, 0xd1, // 0x775a68: callq *%rcx
691 },
692 0x775a56);
693
694 Analysis.parseSectionContents(
695 {
696 0x0f, 0x0b, // 0x775e0e: ud2
697 },
698 0x775e0e);
699 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
700 SearchLengthForUndef = 1;
701 EXPECT_FALSE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
702 SearchLengthForUndef = 2;
703 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
704 SearchLengthForUndef = 3;
705 EXPECT_TRUE(Analysis.isIndirectInstructionCFIProtected(0x775a68));
706 SearchLengthForUndef = PrevSearchLengthForUndef;
Mitch Phillips5ff01cd2017-10-25 21:21:16 +0000707}
708
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +0000709} // anonymous namespace
710} // end namespace cfi_verify
711} // end namespace llvm
712
713int main(int argc, char **argv) {
714 ::testing::InitGoogleTest(&argc, argv);
715 llvm::cl::ParseCommandLineOptions(argc, argv);
716
717 llvm::InitializeAllTargetInfos();
718 llvm::InitializeAllTargetMCs();
719 llvm::InitializeAllAsmParsers();
720 llvm::InitializeAllDisassemblers();
721
722 return RUN_ALL_TESTS();
723}