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/block_graph/basic_block_assembler.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/block_graph/basic_block_subgraph.h"
19 :
20 : namespace block_graph {
21 :
22 : namespace {
23 :
24 : class BasicBlockAssemblerTest : public testing::Test {
25 : public:
26 : typedef BlockGraph::RelativeAddress RelativeAddress;
27 : typedef BlockGraph::Block::SourceRange SourceRange;
28 :
29 : BasicBlockAssemblerTest();
30 :
31 E : void SetUp() OVERRIDE {
32 E : }
33 :
34 E : void TearDown() OVERRIDE {
35 E : }
36 :
37 : protected:
38 : struct Ref {
39 : size_t offset;
40 : BasicBlockReference::ReferredType type;
41 : const void* reference;
42 : };
43 :
44 : template <size_t N>
45 E : void AssertRefs(const Ref(& refs)[N]) {
46 E : ASSERT_EQ(1, instructions_.size());
47 E : const Instruction& instr = instructions_.front();
48 :
49 E : for (size_t i = 0; i < N; ++i) {
50 : BasicBlock::BasicBlockReferenceMap::const_iterator it =
51 E : instr.references().find(refs[i].offset);
52 E : ASSERT_NE(instr.references().end(), it);
53 E : ASSERT_EQ(refs[i].type, it->second.referred_type());
54 E : switch (refs[i].type) {
55 : case BasicBlockReference::REFERRED_TYPE_BLOCK:
56 E : ASSERT_EQ(refs[i].reference, it->second.block());
57 E : break;
58 : case BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK:
59 E : ASSERT_EQ(refs[i].reference, it->second.basic_block());
60 E : break;
61 : default:
62 i : ASSERT_TRUE(false);
63 : }
64 :
65 E : ASSERT_EQ(refs[i].type, it->second.referred_type());
66 E : }
67 :
68 E : instructions_.clear();
69 E : }
70 :
71 E : void AssertNoRefs() {
72 E : ASSERT_EQ(1, instructions_.size());
73 E : ASSERT_EQ(0, instructions_.front().references().size());
74 E : instructions_.clear();
75 E : }
76 :
77 : BlockGraph block_graph_;
78 : BlockGraph::Block* test_block_;
79 : BasicBlockSubGraph subgraph_;
80 : BasicCodeBlock* test_bb_;
81 : BasicBlock::Instructions instructions_;
82 : BasicBlockAssembler asm_;
83 : };
84 :
85 : #define ASSERT_REFS(...) \
86 : do { \
87 : const Ref refs[] = { __VA_ARGS__ }; \
88 : ASSERT_NO_FATAL_FAILURE(AssertRefs(refs)); \
89 : } while (0)
90 :
91 : #define ASSERT_NO_REFS() ASSERT_NO_FATAL_FAILURE(AssertNoRefs())
92 :
93 : BasicBlockAssemblerTest::BasicBlockAssemblerTest()
94 : : test_block_(NULL),
95 : test_bb_(NULL),
96 E : asm_(instructions_.end(), &instructions_) {
97 E : test_block_ = block_graph_.AddBlock(BlockGraph::CODE_BLOCK, 10, "test block");
98 E : test_bb_= subgraph_.AddBasicCodeBlock("foo");
99 E : }
100 :
101 : void TestValue(const Value& value,
102 : uint32 expected_value,
103 E : core::ValueSize expected_size) {
104 E : EXPECT_EQ(expected_size, value.size());
105 E : EXPECT_EQ(expected_value, value.value());
106 : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
107 E : value.reference().referred_type());
108 :
109 E : Value value_copy(value);
110 E : EXPECT_EQ(expected_size, value_copy.size());
111 E : EXPECT_EQ(expected_value, value_copy.value());
112 : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
113 E : value_copy.reference().referred_type());
114 :
115 E : EXPECT_TRUE(value == value_copy);
116 :
117 E : Value value_diff(expected_value - 1);
118 E : EXPECT_FALSE(value == value_diff);
119 E : }
120 :
121 E : void Test8BitValue(uint32 input_value, uint32 expected_value) {
122 E : TestValue(Value(input_value), expected_value, core::kSize8Bit);
123 : TestValue(
124 E : Value(input_value, core::kSize8Bit), expected_value, core::kSize8Bit);
125 E : }
126 :
127 E : void Test32BitValue(uint32 input_value, uint32 expected_value) {
128 E : TestValue(Value(input_value), expected_value, core::kSize32Bit);
129 : TestValue(
130 E : Value(input_value, core::kSize32Bit), expected_value, core::kSize32Bit);
131 E : }
132 :
133 : typedef BasicBlockAssemblerTest ValueTest;
134 :
135 E : void TestValueCopy(const Value& input) {
136 : // Make sure copy-constructing the value works.
137 E : Value copy(input);
138 :
139 E : ASSERT_EQ(input.value(), copy.value());
140 E : ASSERT_EQ(input.size(), copy.size());
141 : ASSERT_EQ(input.reference().referred_type(),
142 E : copy.reference().referred_type());
143 E : ASSERT_EQ(input.reference().block(), copy.reference().block());
144 E : ASSERT_EQ(input.reference().basic_block(), copy.reference().basic_block());
145 E : ASSERT_EQ(input.reference().offset(), copy.reference().offset());
146 E : ASSERT_EQ(input.reference().base(), copy.reference().base());
147 :
148 : // Make sure assignment operator works.
149 E : Value copy2;
150 E : copy2 = input;
151 E : ASSERT_EQ(input.value(), copy2.value());
152 E : ASSERT_EQ(input.size(), copy2.size());
153 : ASSERT_EQ(input.reference().referred_type(),
154 E : copy2.reference().referred_type());
155 E : ASSERT_EQ(input.reference().block(), copy2.reference().block());
156 E : ASSERT_EQ(input.reference().basic_block(), copy2.reference().basic_block());
157 E : ASSERT_EQ(input.reference().offset(), copy2.reference().offset());
158 E : ASSERT_EQ(input.reference().base(), copy2.reference().base());
159 E : }
160 :
161 : } // namespace
162 :
163 E : TEST(UntypedReferenceTest, DefaultConstructor) {
164 E : UntypedReference r;
165 E : EXPECT_EQ(NULL, r.basic_block());
166 E : EXPECT_EQ(NULL, r.block());
167 E : EXPECT_EQ(0, r.offset());
168 E : EXPECT_EQ(0, r.base());
169 E : EXPECT_FALSE(r.IsValid());
170 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN, r.referred_type());
171 E : }
172 :
173 E : TEST(UntypedReferenceTest, BasicBlockReferenceToBasicBlockConstructor) {
174 E : BasicBlockSubGraph subgraph;
175 E : BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
176 E : BasicBlock* bb = bcb;
177 E : BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, bcb);
178 E : UntypedReference r(bbref);
179 E : EXPECT_EQ(bb, r.basic_block());
180 E : EXPECT_EQ(NULL, r.block());
181 E : EXPECT_EQ(0, r.offset());
182 E : EXPECT_EQ(0, r.base());
183 E : EXPECT_TRUE(r.IsValid());
184 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
185 E : }
186 :
187 E : TEST(UntypedReferenceTest, BasicBlockReferenceToBlockConstructor) {
188 E : BlockGraph block_graph;
189 : BlockGraph::Block* b =
190 E : block_graph.AddBlock(BlockGraph::CODE_BLOCK, 20, "foo");
191 E : BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, b, 4, 10);
192 E : UntypedReference r(bbref);
193 E : EXPECT_EQ(NULL, r.basic_block());
194 E : EXPECT_EQ(b, r.block());
195 E : EXPECT_EQ(4, r.offset());
196 E : EXPECT_EQ(10, r.base());
197 E : EXPECT_TRUE(r.IsValid());
198 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
199 E : }
200 :
201 E : TEST(UntypedReferenceTest, BasicBlockConstructor) {
202 E : BasicBlockSubGraph subgraph;
203 E : BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
204 E : BasicBlock* bb = bcb;
205 E : UntypedReference r(bcb);
206 E : EXPECT_EQ(bb, r.basic_block());
207 E : EXPECT_EQ(NULL, r.block());
208 E : EXPECT_EQ(0, r.offset());
209 E : EXPECT_EQ(0, r.base());
210 E : EXPECT_TRUE(r.IsValid());
211 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
212 E : }
213 :
214 E : TEST(UntypedReferenceTest, BlockConstructor) {
215 E : BlockGraph block_graph;
216 : BlockGraph::Block* b =
217 E : block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
218 E : UntypedReference r(b, 4, 10);
219 E : EXPECT_EQ(NULL, r.basic_block());
220 E : EXPECT_EQ(b, r.block());
221 E : EXPECT_EQ(4, r.offset());
222 E : EXPECT_EQ(10, r.base());
223 E : EXPECT_TRUE(r.IsValid());
224 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
225 E : }
226 :
227 E : TEST(UntypedReferenceTest, CopyConstructor) {
228 E : BlockGraph block_graph;
229 : BlockGraph::Block* b =
230 E : block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
231 E : UntypedReference r1(b, 4, 10);
232 :
233 E : UntypedReference r2(r1);
234 E : EXPECT_EQ(r1.basic_block(), r2.basic_block());
235 E : EXPECT_EQ(r1.block(), r2.block());
236 E : EXPECT_EQ(r1.offset(), r2.offset());
237 E : EXPECT_EQ(r1.base(), r2.base());
238 E : EXPECT_EQ(r1.IsValid(), r2.IsValid());
239 E : }
240 :
241 E : TEST(UntypedReferenceTest, Comparison) {
242 E : BlockGraph block_graph;
243 E : BasicBlockSubGraph subgraph;
244 : BlockGraph::Block* b =
245 E : block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
246 E : UntypedReference r1(b, 4, 10);
247 :
248 E : UntypedReference r2(b, 0, 0);
249 E : EXPECT_FALSE(r1 == r2);
250 :
251 E : BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
252 E : BasicBlock* bb = bcb;
253 E : UntypedReference r3(bcb);
254 E : EXPECT_FALSE(r1 == r3);
255 E : EXPECT_FALSE(r2 == r3);
256 :
257 E : UntypedReference r4(r1);
258 E : EXPECT_TRUE(r1 == r4);
259 :
260 E : UntypedReference r5(r2);
261 E : EXPECT_TRUE(r2 == r5);
262 E : }
263 :
264 E : TEST_F(ValueTest, Construction) {
265 : {
266 E : Value value_empty;
267 E : ASSERT_EQ(0, value_empty.value());
268 E : ASSERT_EQ(core::kSizeNone, value_empty.size());
269 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
270 E : value_empty.reference().referred_type());
271 :
272 E : TestValueCopy(value_empty);
273 E : }
274 :
275 E : Test8BitValue(0, 0);
276 E : Test8BitValue(127, 127);
277 :
278 E : Test8BitValue(-128, 0xFFFFFF80);
279 E : Test8BitValue(0, 0);
280 E : Test8BitValue(127, 0x0000007F);
281 :
282 E : Test32BitValue(128, 0x00000080);
283 E : Test32BitValue(0xCAFEBABE, 0xCAFEBABE);
284 :
285 E : Test32BitValue(-129, 0xFFFFFF7F);
286 E : Test32BitValue(128, 0x000000080);
287 E : Test32BitValue(0xBABE, 0xBABE);
288 :
289 : {
290 E : const BlockGraph::Offset kOffs = 10;
291 E : Value value_block_ref(test_block_, kOffs);
292 :
293 E : ASSERT_EQ(0, value_block_ref.value());
294 E : ASSERT_EQ(core::kSize32Bit, value_block_ref.size());
295 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
296 E : value_block_ref.reference().referred_type());
297 E : ASSERT_EQ(test_block_, value_block_ref.reference().block());
298 E : ASSERT_EQ(kOffs, value_block_ref.reference().offset());
299 E : ASSERT_EQ(kOffs, value_block_ref.reference().base());
300 :
301 E : TestValueCopy(value_block_ref);
302 E : }
303 :
304 : {
305 E : Value value_bb_ref(test_bb_);
306 :
307 E : ASSERT_EQ(0, value_bb_ref.value());
308 E : ASSERT_EQ(core::kSize32Bit, value_bb_ref.size());
309 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK,
310 E : value_bb_ref.reference().referred_type());
311 E : ASSERT_EQ(test_bb_, value_bb_ref.reference().basic_block());
312 E : ASSERT_EQ(0, value_bb_ref.reference().offset());
313 E : ASSERT_EQ(0, value_bb_ref.reference().base());
314 :
315 E : TestValueCopy(value_bb_ref);
316 E : }
317 :
318 : {
319 : // Explicitly specified size and reference info.
320 E : UntypedReference ref(test_block_, 1, 2);
321 E : Value value_expl_ref(0xBE, core::kSize8Bit, ref);
322 :
323 E : ASSERT_EQ(0xBE, value_expl_ref.value());
324 E : ASSERT_EQ(core::kSize8Bit, value_expl_ref.size());
325 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
326 E : value_expl_ref.reference().referred_type());
327 E : ASSERT_EQ(test_block_, value_expl_ref.reference().block());
328 E : ASSERT_EQ(1, value_expl_ref.reference().offset());
329 E : ASSERT_EQ(2, value_expl_ref.reference().base());
330 :
331 E : TestValueCopy(value_expl_ref);
332 E : }
333 E : }
334 :
335 : typedef BasicBlockAssemblerTest OperandTest;
336 :
337 E : void TestOperandCopy(const Operand& input) {
338 E : Operand copy(input);
339 :
340 E : ASSERT_EQ(input.base(), copy.base());
341 E : ASSERT_EQ(input.index(), copy.index());
342 E : ASSERT_EQ(input.scale(), copy.scale());
343 E : ASSERT_EQ(input.displacement().value(), copy.displacement().value());
344 E : ASSERT_EQ(input.displacement().size(), copy.displacement().size());
345 E : ASSERT_EQ(input.displacement().reference(), copy.displacement().reference());
346 :
347 E : Operand copy2(core::eax);
348 :
349 E : copy2 = input;
350 E : ASSERT_EQ(input.base(), copy2.base());
351 E : ASSERT_EQ(input.index(), copy2.index());
352 E : ASSERT_EQ(input.scale(), copy2.scale());
353 E : ASSERT_EQ(input.displacement().value(), copy2.displacement().value());
354 E : ASSERT_EQ(input.displacement().size(), copy2.displacement().size());
355 E : ASSERT_EQ(input.displacement().reference(), copy2.displacement().reference());
356 E : }
357 :
358 E : TEST_F(OperandTest, Construction) {
359 : // A register-indirect.
360 E : TestOperandCopy(Operand(core::eax));
361 :
362 : // Register-indirect with displacement.
363 E : TestOperandCopy(Operand(core::eax, Displacement(100)));
364 E : TestOperandCopy(Operand(core::eax, Displacement(test_block_, 2)));
365 E : TestOperandCopy(Operand(core::eax, Displacement(test_bb_)));
366 :
367 : // Displacement-only mode.
368 E : TestOperandCopy(Operand(Displacement(100)));
369 E : TestOperandCopy(Operand(Displacement(test_block_, 2)));
370 E : TestOperandCopy(Operand(Displacement(test_bb_)));
371 :
372 : TestOperandCopy(Operand(core::eax,
373 : core::ebp,
374 : core::kTimes2,
375 E : Displacement(100)));
376 : TestOperandCopy(Operand(core::eax,
377 : core::ebp,
378 : core::kTimes2,
379 E : Displacement(test_block_, 2)));
380 : TestOperandCopy(Operand(core::eax,
381 : core::ebp,
382 : core::kTimes2,
383 E : Displacement(test_bb_)));
384 :
385 : // The [base + index * scale] mode - no displ.
386 E : TestOperandCopy(Operand(core::eax, core::ebp, core::kTimes2));
387 :
388 : // The [index * scale + displ32] mode - no base.
389 : TestOperandCopy(Operand(core::ebp,
390 : core::kTimes2,
391 E : Displacement(100)));
392 : TestOperandCopy(Operand(core::ebp,
393 : core::kTimes2,
394 E : Displacement(test_block_, 2)));
395 : TestOperandCopy(Operand(core::ebp,
396 : core::kTimes2,
397 E : Displacement(test_bb_)));
398 E : }
399 :
400 E : TEST_F(BasicBlockAssemblerTest, nop) {
401 : // We can't use ASSERT_NO_REFS here as nop may generate more than 1
402 : // instruction, an exception to the rule of 1 instruction that ASSERT_NO_REFS
403 : // enforces.
404 E : asm_.nop(0);
405 E : ASSERT_EQ(0u, instructions_.size());
406 :
407 : // Exactly 1 or 2 instructions should be emitted per NOP length from
408 : // 1 to 15.
409 E : for (size_t i = 1; i <= 15; ++i) {
410 E : asm_.nop(i);
411 E : ASSERT_LT(0u, instructions_.size());
412 E : ASSERT_GE(2u, instructions_.size());
413 :
414 : // NOP instructions should have no references.
415 : for (BasicCodeBlock::Instructions::const_iterator inst_it =
416 E : instructions_.begin();
417 E : inst_it != instructions_.end();
418 E : ++inst_it) {
419 E : ASSERT_EQ(0u, inst_it->references().size());
420 E : }
421 E : instructions_.clear();
422 E : }
423 E : }
424 :
425 E : TEST_F(BasicBlockAssemblerTest, call) {
426 E : asm_.call(Immediate(test_block_, 0));
427 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
428 :
429 E : asm_.call(Operand(Displacement(test_bb_)));
430 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
431 E : }
432 :
433 E : TEST_F(BasicBlockAssemblerTest, jmp) {
434 E : asm_.jmp(Immediate(test_block_, 0));
435 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
436 :
437 E : asm_.jmp(Operand(Displacement(test_bb_)));
438 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
439 E : }
440 :
441 E : TEST_F(BasicBlockAssemblerTest, mov_b) {
442 : // mov BYTE PTR [base + index * scale + displ], immediate
443 : asm_.mov_b(Operand(core::eax, core::ebx, core::kTimes4,
444 : Displacement(test_block_, 0)),
445 E : Immediate(10));
446 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
447 E : }
448 :
449 E : TEST_F(BasicBlockAssemblerTest, movzx_b) {
450 : // movzx eax, BYTE PTR [base + index * scale + displ]
451 : asm_.movzx_b(core::eax,
452 : Operand(core::eax, core::ebx, core::kTimes4,
453 E : Displacement(test_block_, 0)));
454 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
455 E : }
456 :
457 E : TEST_F(BasicBlockAssemblerTest, mov) {
458 : // Simple register-register move.
459 E : asm_.mov(core::eax, core::ebx);
460 E : ASSERT_NO_REFS();
461 :
462 : // Simple immediate-register move.
463 E : asm_.mov(core::eax, Immediate(10));
464 E : ASSERT_NO_REFS();
465 :
466 : // Immediate-with reference to register.
467 E : asm_.mov(core::eax, Immediate(test_block_, 0));
468 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
469 :
470 : // Torture test; mov [displ], immediate,
471 : // both src and dst contain references.
472 E : asm_.mov(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
473 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
474 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
475 :
476 : // Torture test; mov [base + index * scale + displ], immediate,
477 : // both src and dst contain references.
478 : asm_.mov(Operand(core::eax, core::ebx, core::kTimes4,
479 : Displacement(test_block_, 0)),
480 E : Immediate(test_bb_));
481 : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
482 E : 7, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
483 E : }
484 :
485 E : TEST_F(BasicBlockAssemblerTest, mov_fs) {
486 : asm_.mov_fs(Operand(core::eax, core::ebx, core::kTimes4,
487 : Displacement(test_block_, 0)),
488 E : core::eax);
489 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
490 :
491 : asm_.mov_fs(core::eax,
492 : Operand(core::eax, core::ebx, core::kTimes4,
493 E : Displacement(test_block_, 0)));
494 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
495 E : }
496 :
497 E : TEST_F(BasicBlockAssemblerTest, lea) {
498 E : asm_.lea(core::eax, Operand(core::eax));
499 E : ASSERT_NO_REFS();
500 :
501 : asm_.lea(core::eax,
502 : Operand(core::eax, core::ebx, core::kTimes4,
503 E : Displacement(test_bb_)));
504 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
505 E : }
506 :
507 E : TEST_F(BasicBlockAssemblerTest, push) {
508 E : asm_.push(core::esp);
509 E : ASSERT_NO_REFS();
510 :
511 E : asm_.push(Immediate(test_block_, 0));
512 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
513 :
514 : asm_.push(Operand(core::eax, core::ebx, core::kTimes4,
515 E : Displacement(test_bb_)));
516 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
517 E : }
518 :
519 E : TEST_F(BasicBlockAssemblerTest, pop) {
520 E : asm_.pop(core::ebp);
521 E : ASSERT_NO_REFS();
522 :
523 : asm_.pop(Operand(core::eax, core::ebx, core::kTimes4,
524 E : Displacement(test_bb_)));
525 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
526 E : }
527 :
528 E : TEST_F(BasicBlockAssemblerTest, pushfd) {
529 E : asm_.pushfd();
530 E : ASSERT_NO_REFS();
531 E : }
532 :
533 E : TEST_F(BasicBlockAssemblerTest, popfd) {
534 E : asm_.popfd();
535 E : ASSERT_NO_REFS();
536 E : }
537 :
538 E : TEST_F(BasicBlockAssemblerTest, lahf) {
539 E : asm_.lahf();
540 E : ASSERT_NO_REFS();
541 E : }
542 :
543 E : TEST_F(BasicBlockAssemblerTest, sahf) {
544 E : asm_.sahf();
545 E : ASSERT_NO_REFS();
546 E : }
547 :
548 E : TEST_F(BasicBlockAssemblerTest, setxx) {
549 : // Simple register-register operation.
550 E : asm_.set(core::kParityEven, core::eax);
551 E : ASSERT_NO_REFS();
552 :
553 E : asm_.set(core::kOverflow, core::ebx);
554 E : ASSERT_NO_REFS();
555 E : }
556 :
557 E : TEST_F(BasicBlockAssemblerTest, test) {
558 : // Simple register-register operation.
559 E : asm_.test(core::al, core::bl);
560 E : ASSERT_NO_REFS();
561 :
562 : // Simple immediate-register operation.
563 E : asm_.test(core::al, Immediate(10, core::kSize8Bit));
564 E : ASSERT_NO_REFS();
565 :
566 : // Simple register-register operation.
567 E : asm_.test(core::eax, core::ebx);
568 E : ASSERT_NO_REFS();
569 :
570 : // Simple immediate-register operation.
571 E : asm_.test(core::eax, Immediate(10));
572 E : ASSERT_NO_REFS();
573 :
574 : // Immediate-with reference to register.
575 E : asm_.test(core::eax, Immediate(test_block_, 0));
576 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
577 :
578 : // Torture test: both src and dst contain references.
579 E : asm_.test(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
580 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
581 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
582 :
583 E : asm_.test(Operand(Displacement(test_block_, 0)), Immediate(10));
584 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
585 E : }
586 :
587 E : TEST_F(BasicBlockAssemblerTest, cmp) {
588 : // Simple register-register operation.
589 E : asm_.cmp(core::al, core::bl);
590 E : ASSERT_NO_REFS();
591 :
592 : // Simple immediate-register operation.
593 E : asm_.cmp(core::al, Immediate(10, core::kSize8Bit));
594 E : ASSERT_NO_REFS();
595 :
596 : // Simple register-register operation.
597 E : asm_.cmp(core::eax, core::ebx);
598 E : ASSERT_NO_REFS();
599 :
600 : // Simple immediate-register operation.
601 E : asm_.cmp(core::eax, Immediate(10));
602 E : ASSERT_NO_REFS();
603 :
604 : // Immediate-with reference to register.
605 E : asm_.cmp(core::eax, Immediate(test_block_, 0));
606 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
607 :
608 : // Torture test: both src and dst contain references.
609 E : asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
610 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
611 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
612 :
613 E : asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(10));
614 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
615 E : }
616 :
617 E : TEST_F(BasicBlockAssemblerTest, add) {
618 : // Simple register-register operation.
619 E : asm_.add(core::al, core::bl);
620 E : ASSERT_NO_REFS();
621 :
622 : // Simple immediate-register operation.
623 E : asm_.add(core::al, Immediate(10, core::kSize8Bit));
624 E : ASSERT_NO_REFS();
625 :
626 : // Simple register-register operation.
627 E : asm_.add(core::eax, core::ebx);
628 E : ASSERT_NO_REFS();
629 :
630 : // Simple immediate-register operation.
631 E : asm_.add(core::eax, Immediate(10));
632 E : ASSERT_NO_REFS();
633 :
634 : // Immediate-with reference to register.
635 E : asm_.add(core::eax, Immediate(test_block_, 0));
636 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
637 :
638 : // Torture test: both src and dst contain references.
639 E : asm_.add(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
640 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
641 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
642 :
643 E : asm_.add(Operand(Displacement(test_block_, 0)), Immediate(10));
644 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
645 E : }
646 :
647 E : TEST_F(BasicBlockAssemblerTest, sub) {
648 : // Simple register-register operation.
649 E : asm_.sub(core::al, core::bl);
650 E : ASSERT_NO_REFS();
651 :
652 : // Simple immediate-register operation.
653 E : asm_.sub(core::al, Immediate(10, core::kSize8Bit));
654 E : ASSERT_NO_REFS();
655 :
656 : // Simple register-register operation.
657 E : asm_.sub(core::eax, core::ebx);
658 E : ASSERT_NO_REFS();
659 :
660 : // Simple immediate-register operation.
661 E : asm_.sub(core::eax, Immediate(10));
662 E : ASSERT_NO_REFS();
663 :
664 : // Immediate-with reference to register.
665 E : asm_.sub(core::eax, Immediate(test_block_, 0));
666 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
667 :
668 : // Torture test: both src and dst contain references.
669 E : asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
670 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
671 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
672 :
673 E : asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(10));
674 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
675 E : }
676 :
677 E : TEST_F(BasicBlockAssemblerTest, shl) {
678 : // Simple immediate-register operation.
679 E : asm_.shl(core::eax, Immediate(1));
680 E : ASSERT_NO_REFS();
681 E : }
682 :
683 E : TEST_F(BasicBlockAssemblerTest, shr) {
684 : // Simple immediate-register operation.
685 E : asm_.shr(core::eax, Immediate(1));
686 E : ASSERT_NO_REFS();
687 E : }
688 :
689 E : TEST_F(BasicBlockAssemblerTest, ret) {
690 E : asm_.ret();
691 E : ASSERT_NO_REFS();
692 :
693 E : asm_.ret(4);
694 E : ASSERT_NO_REFS();
695 E : }
696 :
697 E : TEST_F(BasicBlockAssemblerTest, xchg) {
698 E : asm_.xchg(core::eax, core::ecx);
699 E : ASSERT_NO_REFS();
700 :
701 E : asm_.xchg(core::esp, core::edx);
702 E : ASSERT_NO_REFS();
703 :
704 E : asm_.xchg(core::ax, core::cx);
705 E : ASSERT_NO_REFS();
706 :
707 E : asm_.xchg(core::sp, core::dx);
708 E : ASSERT_NO_REFS();
709 :
710 E : asm_.xchg(core::al, core::ch);
711 E : ASSERT_NO_REFS();
712 :
713 E : asm_.xchg(core::dh, core::bl);
714 E : ASSERT_NO_REFS();
715 E : }
716 :
717 E : TEST_F(BasicBlockAssemblerTest, UndefinedSourceRange) {
718 E : ASSERT_EQ(asm_.source_range(), SourceRange());
719 E : asm_.call(Immediate(test_block_, 0));
720 E : ASSERT_EQ(instructions_.back().source_range(), SourceRange());
721 E : }
722 :
723 E : TEST_F(BasicBlockAssemblerTest, SetSourceRange) {
724 E : SourceRange range(RelativeAddress(10), 10);
725 E : asm_.set_source_range(range);
726 E : asm_.call(Immediate(test_block_, 0));
727 E : ASSERT_EQ(instructions_.back().source_range(), range);
728 E : }
729 :
730 E : TEST_F(BasicBlockAssemblerTest, SetMultipleSourceRange) {
731 E : SourceRange range1(RelativeAddress(10), 10);
732 E : SourceRange range2(RelativeAddress(20), 20);
733 :
734 E : asm_.set_source_range(range1);
735 E : asm_.call(Immediate(test_block_, 0));
736 E : ASSERT_EQ(instructions_.back().source_range(), range1);
737 :
738 E : asm_.set_source_range(range2);
739 E : asm_.pop(core::ebp);
740 E : ASSERT_EQ(instructions_.back().source_range(), range2);
741 :
742 E : asm_.ret(4);
743 E : ASSERT_EQ(instructions_.back().source_range(), range2);
744 E : }
745 :
746 : } // namespace block_graph
|