blob: 00bea1b4c43afb01cf7b94deb770819de8531bfa [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"
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
13
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"
37
38#include <cstdlib>
39
40using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
41using ::testing::Eq;
42
43namespace llvm {
44namespace cfi_verify {
45namespace {
46class ELFx86TestFileAnalysis : public FileAnalysis {
47public:
48 ELFx86TestFileAnalysis()
49 : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {}
50
51 // Expose this method publicly for testing.
52 void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
53 uint64_t SectionAddress) {
54 FileAnalysis::parseSectionContents(SectionBytes, SectionAddress);
55 }
56
57 Error initialiseDisassemblyMembers() {
58 return FileAnalysis::initialiseDisassemblyMembers();
59 }
60};
61
62class BasicFileAnalysisTest : public ::testing::Test {
63protected:
64 virtual void SetUp() {
65 if (Analysis.initialiseDisassemblyMembers()) {
66 FAIL() << "Failed to initialise FileAnalysis.";
67 }
68 }
69
70 ELFx86TestFileAnalysis Analysis;
71};
72
73TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
74 Analysis.parseSectionContents(
75 {
76 0x90, // 0: nop
77 0xb0, 0x00, // 1: mov $0x0, %al
78 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
79 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
80 0x48, 0xbe, 0xc4, 0x07, 0x40,
81 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
82 0x2f, // 20: (bad)
83 0x41, 0x0e, // 21: rex.B (bad)
84 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
85 },
86 0xDEADBEEF);
87
88 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
89 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
90
91 // 0xDEADBEEF: nop
92 const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
93 EXPECT_NE(nullptr, InstrMeta);
94 EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
95 EXPECT_EQ(1u, InstrMeta->InstructionSize);
96 EXPECT_TRUE(InstrMeta->Valid);
97
98 const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
99 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
100 const auto *PrevInstrMeta = InstrMeta;
101
102 // 0xDEADBEEF + 1: mov $0x0, %al
103 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
104 EXPECT_NE(nullptr, InstrMeta);
105 EXPECT_EQ(NextInstrMeta, InstrMeta);
106 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
107 EXPECT_EQ(2u, InstrMeta->InstructionSize);
108 EXPECT_TRUE(InstrMeta->Valid);
109
110 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
111 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
112 PrevInstrMeta = InstrMeta;
113
114 // 0xDEADBEEF + 3: mov %rsp, %rbp
115 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
116 EXPECT_NE(nullptr, InstrMeta);
117 EXPECT_EQ(NextInstrMeta, InstrMeta);
118 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
119 EXPECT_EQ(3u, 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 + 6: sub $0x18, %rsp
127 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
128 EXPECT_NE(nullptr, InstrMeta);
129 EXPECT_EQ(NextInstrMeta, InstrMeta);
130 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
131 EXPECT_EQ(4u, 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 + 10: movabs $0x4007c4, %rsi
139 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
140 EXPECT_NE(nullptr, InstrMeta);
141 EXPECT_EQ(NextInstrMeta, InstrMeta);
142 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
143 EXPECT_EQ(10u, InstrMeta->InstructionSize);
144 EXPECT_TRUE(InstrMeta->Valid);
145
146 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
147 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
148 PrevInstrMeta = InstrMeta;
149
150 // 0xDEADBEEF + 20: (bad)
151 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
152 EXPECT_NE(nullptr, InstrMeta);
153 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
154 EXPECT_EQ(1u, InstrMeta->InstructionSize);
155 EXPECT_FALSE(InstrMeta->Valid);
156
157 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
158 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
159
160 // 0xDEADBEEF + 21: rex.B (bad)
161 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
162 EXPECT_NE(nullptr, InstrMeta);
163 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
164 EXPECT_EQ(2u, InstrMeta->InstructionSize);
165 EXPECT_FALSE(InstrMeta->Valid);
166
167 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
168 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
169
170 // 0xDEADBEEF + 6: (bad) {%k1}
171 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
172 EXPECT_NE(nullptr, InstrMeta);
173 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
174 EXPECT_EQ(5u, InstrMeta->InstructionSize);
175 EXPECT_FALSE(InstrMeta->Valid);
176
177 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
178 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
179}
180
181TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
182 Analysis.parseSectionContents(
183 {
184 0x90, // 0: nop
185 0x2f, // 1: (bad)
186 0x90 // 2: nop
187 },
188 0xDEADBEEF);
189 const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
190 const auto *GoodInstrMeta =
191 Analysis.getPrevInstructionSequential(BadInstrMeta);
192 EXPECT_NE(nullptr, GoodInstrMeta);
193 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
194 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
195
196 GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
197 EXPECT_NE(nullptr, GoodInstrMeta);
198 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
199 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
200}
201
202} // anonymous namespace
203} // end namespace cfi_verify
204} // end namespace llvm
205
206int main(int argc, char **argv) {
207 ::testing::InitGoogleTest(&argc, argv);
208 llvm::cl::ParseCommandLineOptions(argc, argv);
209
210 llvm::InitializeAllTargetInfos();
211 llvm::InitializeAllTargetMCs();
212 llvm::InitializeAllAsmParsers();
213 llvm::InitializeAllDisassemblers();
214
215 return RUN_ALL_TESTS();
216}