1 : // Copyright 2012 Google Inc.
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/reorder/dead_code_finder.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/block_graph/block_graph.h"
19 : #include "syzygy/core/address.h"
20 : #include "syzygy/core/random_number_generator.h"
21 : #include "syzygy/reorder/order_generator_test.h"
22 :
23 : namespace reorder {
24 :
25 : class DeadCodeFinderTest : public testing::OrderGeneratorTest {
26 : protected:
27 : typedef std::set<const block_graph::BlockGraph::Block*> BlockSet;
28 : typedef BlockSet::iterator BlockIter;
29 :
30 E : DeadCodeFinderTest() : random_(12345) {
31 E : }
32 :
33 : DeadCodeFinder dead_code_finder_;
34 : BlockSet live_blocks_;
35 : BlockSet dead_blocks_;
36 : core::RandomNumberGenerator random_;
37 : };
38 :
39 E : TEST_F(DeadCodeFinderTest, TestDLL) {
40 E : const size_t kNumBlocks = 20;
41 :
42 : // Get the .text code section.
43 E : size_t section_index = input_dll_.GetSectionIndex(".text");
44 : const IMAGE_SECTION_HEADER* section =
45 E : input_dll_.section_header(section_index);
46 E : ASSERT_TRUE(section != NULL);
47 :
48 : // Get a bunch of random blocks to visit (and consider live).
49 E : ASSERT_TRUE(live_blocks_.size() == 0);
50 E : while (live_blocks_.size() < kNumBlocks) {
51 : core::RelativeAddress addr(
52 E : section->VirtualAddress + random_(section->Misc.VirtualSize));
53 : const block_graph::BlockGraph::Block* block =
54 E : image_layout_.blocks.GetBlockByAddress(addr);
55 E : ASSERT_TRUE(block->addr() <= addr);
56 E : ASSERT_TRUE(addr <= block->addr() + block->size());
57 E : live_blocks_.insert(block);
58 E : }
59 :
60 : // Get a bunch of random blocks to NOT visit (and consider dead).
61 E : ASSERT_TRUE(dead_blocks_.size() == 0);
62 E : while (dead_blocks_.size() < kNumBlocks) {
63 : core::RelativeAddress addr(
64 E : section->VirtualAddress + random_(section->Misc.VirtualSize));
65 : const block_graph::BlockGraph::Block* block =
66 E : image_layout_.blocks.GetBlockByAddress(addr);
67 : if ((block->attributes() & block_graph::BlockGraph::GAP_BLOCK) == 0 &&
68 E : (live_blocks_.find(block) == live_blocks_.end())) {
69 E : dead_blocks_.insert(block);
70 : }
71 E : }
72 :
73 : // Generate calls to the live blocks.
74 E : dead_code_finder_.OnProcessStarted(1, GetSystemTime());
75 E : for (BlockIter it = live_blocks_.begin(); it != live_blocks_.end(); ++it) {
76 : dead_code_finder_.OnCodeBlockEntry(
77 E : *it, (*it)->addr(), 1, 1, GetSystemTime());
78 E : }
79 E : dead_code_finder_.OnProcessEnded(1, GetSystemTime());
80 :
81 : // Do the reordering.
82 : EXPECT_TRUE(dead_code_finder_.CalculateReordering(input_dll_,
83 : image_layout_,
84 : true,
85 : false,
86 E : &order_));
87 :
88 E : ExpectNoDuplicateBlocks();
89 :
90 : // Check the live blocks.
91 E : for (BlockIter it = live_blocks_.begin(); it != live_blocks_.end(); ++it) {
92 E : EXPECT_FALSE(dead_code_finder_.IsDead(*it))
93 : << "Block '" << (*it)->name() << "' was not expected to be dead.";
94 E : }
95 :
96 : // Check the dead blocks.
97 E : for (BlockIter it = dead_blocks_.begin(); it != dead_blocks_.end(); ++it) {
98 E : EXPECT_TRUE(dead_code_finder_.IsDead(*it))
99 : << "Block '" << (*it)->name() << "' was expected to be dead.";
100 E : }
101 :
102 : // Check the ordering.
103 E : ASSERT_TRUE(order_.section_block_lists.size() == 1);
104 E : ASSERT_TRUE(order_.section_block_lists[0].size() >= dead_blocks_.size());
105 : typedef Reorderer::Order::BlockList BlockList;
106 E : BlockList::iterator iter = order_.section_block_lists[0].begin();
107 E : for (; iter != order_.section_block_lists[0].end(); ++iter) {
108 E : ASSERT_TRUE(dead_code_finder_.IsDead(*iter));
109 E : ASSERT_TRUE(live_blocks_.find(*iter) == live_blocks_.end());
110 E : }
111 E : }
112 :
113 : } // namespace reorder
|