1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/core/disassembler_util.h"
16 :
17 : #include "base/basictypes.h"
18 : #include "base/logging.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 :
22 : namespace core {
23 :
24 : namespace {
25 :
26 : // Decompose a block of code using distorm wrapper.
27 : _DecodeResult DecomposeCode(const uint8* code_data,
28 : size_t length,
29 : _DInst result[],
30 : const unsigned int max_results,
31 E : unsigned int* result_count) {
32 E : _CodeInfo code = {};
33 E : code.dt = Decode32Bits;
34 E : code.features = DF_NONE;
35 E : code.codeOffset = 0;
36 E : code.codeLen = length;
37 E : code.code = code_data;
38 E : return DistormDecompose(&code, result, max_results, result_count);
39 E : }
40 :
41 : // Decompose a block of code using distorm directly.
42 : _DecodeResult RawDecomposeCode(const uint8* code_data,
43 : size_t length,
44 : _DInst result[],
45 : const unsigned int max_results,
46 E : unsigned int* result_count) {
47 E : _CodeInfo code = {};
48 E : code.dt = Decode32Bits;
49 E : code.features = DF_NONE;
50 E : code.codeOffset = 0;
51 E : code.codeLen = length;
52 E : code.code = code_data;
53 E : return distorm_decompose(&code, result, max_results, result_count);
54 E : }
55 :
56 E : _DInst DecodeBuffer(const uint8* buffer, size_t length) {
57 E : _DInst inst = {};
58 E : EXPECT_TRUE(DecodeOneInstruction(buffer, length, &inst));
59 E : EXPECT_EQ(length, inst.size);
60 E : return inst;
61 E : }
62 :
63 : // One of the AVX instructions that is currently not supported by distorm.
64 : // vxorps ymm0, ymm0, ymm0
65 : const uint8 kVxorps[] = { 0xC5, 0xFC, 0x57, 0xC0 };
66 :
67 : // Instructions for which distorm indicates a size of 0 for the destination
68 : // operand size.
69 : // fnstcw m16
70 : const uint8 kFnstcw[] = { 0xD9, 0x7D, 0xEA };
71 : // fldcw m16
72 : const uint8 kFldcw[] = { 0xD9, 0x6D, 0xE4 };
73 :
74 : // Instructions for which distorm do not activated the write flag.
75 : // fst qword ptr [0A374E8h]
76 : const uint8 kFst[] = { 0xDD, 0x15, 0xE8, 0x74, 0xA3, 0x00 };
77 : // fstp qword ptr [0A374E8h]
78 : const uint8 kFstp[] = { 0xDD, 0x1D, 0xE8, 0x74, 0xA3, 0x00 };
79 : // fist qword ptr [0A374E8h]
80 : const uint8 kFist[] = { 0xDB, 0x15, 0xE0, 0x74, 0xA3, 0x00 };
81 : // fistp qword ptr [0A374E8h]
82 : const uint8 kFistp[] = { 0xDB, 0x1D, 0xE0, 0x74, 0xA3, 0x00 };
83 :
84 : // Nop Instruction byte sequences.
85 : const uint8 kNop2Mov[] = { 0x8B, 0xFF };
86 : const uint8 kNop3Lea[] = { 0x8D, 0x49, 0x00 };
87 : const uint8 kNop1[] = { 0x90 };
88 : const uint8 kNop2[] = { 0x66, 0x90 };
89 : const uint8 kNop3[] = { 0x66, 0x66, 0x90 };
90 : const uint8 kNop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
91 : const uint8 kNop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
92 : const uint8 kNop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
93 : const uint8 kNop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
94 : const uint8 kNop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
95 : const uint8 kNop9[] = {
96 : 0x66, // Prefix,
97 : 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 // kNop8.
98 : };
99 : const uint8 kNop10[] = {
100 : 0x66, 0x66, // Prefix.
101 : 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 // kNop8.
102 : };
103 : const uint8 kNop11[] = {
104 : 0x66, 0x66, 0x66, // Prefix.
105 : 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 // kNop8
106 : };
107 :
108 : // Call instruction.
109 : const uint8 kCall[] = { 0xE8, 0xCA, 0xFE, 0xBA, 0xBE };
110 :
111 : // Control Flow byte sequences (note that the JMP is indirect).
112 : const uint8 kJmp[] = { 0xFF, 0x24, 0x8D, 0xCA, 0xFE, 0xBA, 0xBE };
113 : const uint8 kRet[] = { 0xC3 };
114 : const uint8 kRetN[] = { 0xC2, 0x08, 0x00 };
115 : const uint8 kJe[] = { 0x74, 0xCA };
116 : const uint8 kSysEnter[] = { 0x0F, 0x34 };
117 : const uint8 kSysExit[] = { 0x0F, 0x35 };
118 :
119 : // Interrupts.
120 : const uint8 kInt2[] = { 0xCD, 0x02 };
121 : const uint8 kInt3[] = { 0xCC };
122 :
123 : } // namespace
124 :
125 E : TEST(DisassemblerUtilTest, DistormWrapperVxorpsPasses) {
126 E : _DInst inst = {};
127 E : EXPECT_TRUE(DecodeOneInstruction(kVxorps, sizeof(kVxorps), &inst));
128 E : }
129 :
130 E : TEST(DisassemblerUtilTest, InstructionToString) {
131 E : _DInst inst = {};
132 E : inst = DecodeBuffer(kNop1, sizeof(kNop1));
133 :
134 E : std::string Nop1Str;
135 E : EXPECT_TRUE(InstructionToString(inst, kNop1, sizeof(kNop1), &Nop1Str));
136 E : ASSERT_THAT(Nop1Str, testing::HasSubstr("90"));
137 E : ASSERT_THAT(Nop1Str, testing::HasSubstr("NOP"));
138 E : }
139 :
140 E : TEST(DisassemblerUtilTest, IsNop) {
141 E : EXPECT_FALSE(IsNop(DecodeBuffer(kJmp, sizeof(kJmp))));
142 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop1, sizeof(kNop1))));
143 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop2, sizeof(kNop2))));
144 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop3, sizeof(kNop3))));
145 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop4, sizeof(kNop4))));
146 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop5, sizeof(kNop5))));
147 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop6, sizeof(kNop6))));
148 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop7, sizeof(kNop7))));
149 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop8, sizeof(kNop8))));
150 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop9, sizeof(kNop9))));
151 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop10, sizeof(kNop10))));
152 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop11, sizeof(kNop11))));
153 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop2Mov, sizeof(kNop2Mov))));
154 E : EXPECT_TRUE(IsNop(DecodeBuffer(kNop3Lea, sizeof(kNop3Lea))));
155 E : }
156 :
157 E : TEST(DisassemblerUtilTest, IsCall) {
158 E : EXPECT_FALSE(IsCall(DecodeBuffer(kJmp, sizeof(kJmp))));
159 E : EXPECT_FALSE(IsCall(DecodeBuffer(kNop1, sizeof(kNop1))));
160 E : EXPECT_TRUE(IsCall(DecodeBuffer(kCall, sizeof(kCall))));
161 E : }
162 :
163 E : TEST(DisassemblerUtilTest, IsSystemCall) {
164 E : EXPECT_FALSE(IsSystemCall(DecodeBuffer(kJmp, sizeof(kJmp))));
165 E : EXPECT_FALSE(IsSystemCall(DecodeBuffer(kNop1, sizeof(kNop1))));
166 E : EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
167 E : EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysExit, sizeof(kSysExit))));
168 E : }
169 :
170 E : TEST(DisassemblerUtilTest, IsConditionalBranch) {
171 E : EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
172 E : EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
173 E : EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
174 E : EXPECT_TRUE(IsConditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
175 E : }
176 :
177 E : TEST(DisassemblerUtilTest, IsUnconditionalBranch) {
178 E : EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
179 E : EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
180 E : EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
181 E : EXPECT_TRUE(IsUnconditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
182 E : }
183 :
184 E : TEST(DisassemblerUtilTest, IsBranch) {
185 E : EXPECT_FALSE(IsBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
186 E : EXPECT_FALSE(IsBranch(DecodeBuffer(kRet, sizeof(kRet))));
187 E : EXPECT_TRUE(IsBranch(DecodeBuffer(kJe, sizeof(kJe))));
188 E : EXPECT_TRUE(IsBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
189 E : }
190 :
191 E : TEST(DisassemblerUtilTest, HasPcRelativeOperand) {
192 E : EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kRetN, sizeof(kRet)), 0));
193 E : EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kJmp, sizeof(kJmp)), 0));
194 E : EXPECT_TRUE(HasPcRelativeOperand(DecodeBuffer(kJe, sizeof(kJe)), 0));
195 E : }
196 :
197 E : TEST(DisassemblerUtilTest, IsControlFlow) {
198 E : EXPECT_FALSE(IsControlFlow(DecodeBuffer(kNop4, sizeof(kNop4))));
199 E : EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
200 E : EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
201 E : EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
202 E : EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
203 E : EXPECT_TRUE(IsControlFlow(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
204 E : }
205 :
206 E : TEST(DisassemblerUtilTest, IsImplicitControlFlow) {
207 E : EXPECT_FALSE(IsImplicitControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
208 E : EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
209 E : EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
210 E : EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
211 E : }
212 :
213 E : TEST(DisassemblerUtilTest, IsInterrupt) {
214 E : EXPECT_FALSE(IsInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
215 E : EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
216 E : EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
217 E : }
218 :
219 E : TEST(DisassemblerUtilTest, IsDebugInterrupt) {
220 E : EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
221 E : EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
222 E : EXPECT_TRUE(IsDebugInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
223 E : }
224 :
225 E : TEST(DisassemblerUtilTest, DistormDecompose) {
226 E : const unsigned int kMaxResults = 16;
227 E : unsigned int result_count = 0;
228 : _DInst results[kMaxResults];
229 : EXPECT_EQ(DECRES_SUCCESS,
230 : DecomposeCode(kNop3Lea,
231 : sizeof(kNop3Lea),
232 : results,
233 : kMaxResults,
234 E : &result_count));
235 E : EXPECT_EQ(1U, result_count);
236 E : EXPECT_EQ(32U, results[0].ops[0].size);
237 E : }
238 :
239 E : TEST(DisassemblerUtilTest, DistormDecomposeFnstcw) {
240 E : const unsigned int kMaxResults = 16;
241 E : unsigned int result_count = 0;
242 : _DInst results[kMaxResults];
243 : EXPECT_EQ(DECRES_SUCCESS,
244 : DecomposeCode(kFnstcw,
245 : sizeof(kFnstcw),
246 : results,
247 : kMaxResults,
248 E : &result_count));
249 E : EXPECT_EQ(1U, result_count);
250 E : EXPECT_EQ(16U, results[0].ops[0].size);
251 E : }
252 :
253 E : TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFnstcw) {
254 E : const unsigned int kMaxResults = 16;
255 E : unsigned int result_count = 0;
256 : _DInst results[kMaxResults];
257 : EXPECT_EQ(DECRES_SUCCESS,
258 : RawDecomposeCode(kFldcw,
259 : sizeof(kFldcw),
260 : results,
261 : kMaxResults,
262 E : &result_count));
263 E : EXPECT_EQ(1U, result_count);
264 E : EXPECT_EQ(0U, results[0].ops[0].size);
265 E : }
266 :
267 E : TEST(DisassemblerUtilTest, DistormDecomposeFldcw) {
268 E : const unsigned int kMaxResults = 16;
269 E : unsigned int result_count = 0;
270 : _DInst results[kMaxResults];
271 : EXPECT_EQ(DECRES_SUCCESS,
272 : DecomposeCode(kFldcw,
273 : sizeof(kFldcw),
274 : results,
275 : kMaxResults,
276 E : &result_count));
277 E : EXPECT_EQ(1U, result_count);
278 E : EXPECT_EQ(16U, results[0].ops[0].size);
279 E : }
280 :
281 E : TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFldcw) {
282 E : const unsigned int kMaxResults = 16;
283 E : unsigned int result_count = 0;
284 : _DInst results[kMaxResults];
285 : EXPECT_EQ(DECRES_SUCCESS,
286 : RawDecomposeCode(kFldcw,
287 : sizeof(kFldcw),
288 : results,
289 : kMaxResults,
290 E : &result_count));
291 E : EXPECT_EQ(1U, result_count);
292 E : EXPECT_EQ(0U, results[0].ops[0].size);
293 E : }
294 :
295 E : TEST(DisassemblerUtilTest, WrongWriteFlagOnRawDistormDecomposeFst) {
296 E : _DInst fst = DecodeBuffer(kFst, sizeof(kFst));
297 E : EXPECT_NE(0, fst.flags & FLAG_DST_WR);
298 :
299 E : _DInst fstp = DecodeBuffer(kFstp, sizeof(kFstp));
300 E : EXPECT_NE(0, fstp.flags & FLAG_DST_WR);
301 :
302 E : _DInst fist = DecodeBuffer(kFist, sizeof(kFist));
303 E : EXPECT_NE(0, fist.flags & FLAG_DST_WR);
304 :
305 E : _DInst fistp = DecodeBuffer(kFistp, sizeof(kFistp));
306 E : EXPECT_NE(0, fistp.flags & FLAG_DST_WR);
307 E : }
308 :
309 : } // namespace core
|