1 : // Copyright 2011 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/reorder/order_generator_test.h"
16 :
17 : #include "syzygy/block_graph/block_graph.h"
18 : #include "syzygy/core/address.h"
19 : #include "syzygy/core/unittest_util.h"
20 :
21 : namespace testing {
22 :
23 : using block_graph::BlockGraph;
24 : using core::RelativeAddress;
25 :
26 : typedef reorder::Reorderer::Order::BlockSpec BlockSpec;
27 : typedef reorder::Reorderer::Order::SectionSpec SectionSpec;
28 : typedef reorder::Reorderer::Order::SectionSpecVector SectionSpecVector;
29 :
30 E : OrderGeneratorTest::OrderGeneratorTest() : image_layout_(&block_graph_) {
31 E : }
32 :
33 E : void OrderGeneratorTest::SetUp() {
34 E : base::FilePath test_data_dir = testing::GetExeRelativePath(L"test_data");
35 E : base::FilePath input_dll_path = test_data_dir.Append(testing::kTestDllName);
36 :
37 E : ASSERT_TRUE(input_dll_.Init(input_dll_path));
38 E : pe::Decomposer decomposer(input_dll_);
39 E : ASSERT_TRUE(decomposer.Decompose(&image_layout_));
40 E : }
41 :
42 E : reorder::Reorderer::UniqueTime OrderGeneratorTest::GetSystemTime() {
43 E : return reorder::Reorderer::UniqueTime(base::Time::NowFromSystemTime());
44 E : }
45 :
46 E : void OrderGeneratorTest::ExpectNoDuplicateBlocks() {
47 : // Verifies that there are no duplicate blocks for each section.
48 E : SectionSpecVector::const_iterator it = order_.sections.begin();
49 E : for (; it != order_.sections.end(); ++it) {
50 E : std::set<const BlockGraph::Block*> block_set;
51 E : for (size_t i = 0; i < it->blocks.size(); ++i) {
52 E : EXPECT_TRUE(block_set.insert(it->blocks[i].block).second);
53 E : }
54 E : }
55 E : }
56 :
57 : void OrderGeneratorTest::ExpectMatchingMetadata(
58 : const IMAGE_SECTION_HEADER* section, const SectionSpec& section_spec) {
59 : DCHECK(section != NULL);
60 : // If specified, the section spec's name and characteristics should match.
61 : if (!section_spec.name.empty()) {
62 : EXPECT_EQ(1, ::strncmp(reinterpret_cast<const char*>(§ion->Name[0]),
63 : section_spec.name.c_str(),
64 : sizeof(section->Name)));
65 : EXPECT_EQ(section->Characteristics, section_spec.characteristics);
66 : }
67 : }
68 :
69 : void OrderGeneratorTest::ExpectSameOrder(const IMAGE_SECTION_HEADER* section,
70 E : const BlockSpecVector& block_specs) {
71 E : DCHECK(section != NULL);
72 : // Verifies that the blocks in block_list match the order of the blocks
73 : // in the specified section. If the specified section is empty, then it
74 : // implies that original block ordering should be reused.
75 E : if (!block_specs.empty()) {
76 E : BlockSpecVector original_block_specs;
77 E : GetBlockListForSection(section, &original_block_specs);
78 E : ASSERT_EQ(original_block_specs.size(), block_specs.size());
79 : EXPECT_TRUE(std::equal(original_block_specs.begin(),
80 : original_block_specs.end(),
81 : block_specs.begin(),
82 E : &BlockSpecsAreEqual));
83 E : }
84 E : }
85 :
86 : void OrderGeneratorTest::ExpectDifferentOrder(
87 E : const IMAGE_SECTION_HEADER* section, const BlockSpecVector& block_specs) {
88 E : DCHECK(section != NULL);
89 : // Verifies that the blocks in block_list match the order of the blocks
90 : // in the specified section. If the specified section is empty, then it
91 : // implies that original block ordering should be reused.
92 E : if (!block_specs.empty()) {
93 E : BlockSpecVector original_block_specs;
94 E : GetBlockListForSection(section, &original_block_specs);
95 E : ASSERT_EQ(original_block_specs.size(), block_specs.size());
96 : EXPECT_FALSE(std::equal(original_block_specs.begin(),
97 : original_block_specs.end(),
98 : block_specs.begin(),
99 E : &BlockSpecsAreEqual));
100 E : }
101 E : }
102 :
103 : void OrderGeneratorTest::GetBlockListForSection(
104 E : const IMAGE_SECTION_HEADER* section, BlockSpecVector* block_specs) {
105 E : DCHECK(section != NULL);
106 E : DCHECK(block_specs != NULL);
107 :
108 E : RelativeAddress section_start = RelativeAddress(section->VirtualAddress);
109 : BlockGraph::AddressSpace::RangeMapConstIterPair section_blocks =
110 : image_layout_.blocks.GetIntersectingBlocks(
111 E : section_start, section->Misc.VirtualSize);
112 : BlockGraph::AddressSpace::RangeMapConstIter& section_it =
113 E : section_blocks.first;
114 : const BlockGraph::AddressSpace::RangeMapConstIter& section_end =
115 E : section_blocks.second;
116 :
117 E : for (; section_it != section_end; ++section_it) {
118 E : block_specs->push_back(BlockSpec(section_it->second));
119 E : }
120 E : }
121 :
122 : bool BlockSpecsAreEqual(const reorder::Reorderer::Order::BlockSpec& lhs,
123 E : const reorder::Reorderer::Order::BlockSpec& rhs) {
124 : // Each block should be the same.
125 E : if (lhs.block != rhs.block)
126 E : return false;
127 :
128 : // They should have the same number of block offsets.
129 E : if (lhs.basic_block_offsets.size() != rhs.basic_block_offsets.size())
130 E : return false;
131 :
132 : // They should have identical block offsets.
133 : if (!std::equal(lhs.basic_block_offsets.begin(),
134 : lhs.basic_block_offsets.end(),
135 E : rhs.basic_block_offsets.begin())) {
136 i : return false;
137 : }
138 :
139 : // If we get here then the block specs are identical.
140 E : return true;
141 E : }
142 :
143 : bool SectionSpecsAreEqual(const reorder::Reorderer::Order::SectionSpec& lhs,
144 E : const reorder::Reorderer::Order::SectionSpec& rhs) {
145 : // Each IDs should be the same.
146 E : if (lhs.id != rhs.id)
147 E : return false;
148 :
149 : // Each names should be the same.
150 E : if (lhs.name != rhs.name)
151 i : return false;
152 :
153 : // The characteristics should be the same.
154 E : if (lhs.characteristics != rhs.characteristics)
155 i : return false;
156 :
157 : // They must have the same number of blocks specs.
158 E : if (lhs.blocks.size() != rhs.blocks.size())
159 i : return false;
160 :
161 : // The blocks specifications should be identical.
162 : if (!std::equal(lhs.blocks.begin(),
163 : lhs.blocks.end(),
164 : rhs.blocks.begin(),
165 E : &BlockSpecsAreEqual)) {
166 i : return false;
167 : }
168 :
169 : // If we reach here then the section specs are identical.
170 E : return true;
171 E : }
172 :
173 : bool OrdersAreEqual(const reorder::Reorderer::Order& lhs,
174 E : const reorder::Reorderer::Order& rhs) {
175 : // The comments should be the same.
176 E : if (lhs.comment != rhs.comment)
177 E : return false;
178 :
179 : // They should have the same number of sections.
180 E : if (lhs.sections.size() != rhs.sections.size())
181 i : return false;
182 :
183 : // The sections should be identical.
184 : if (!std::equal(lhs.sections.begin(),
185 : lhs.sections.end(),
186 : rhs.sections.begin(),
187 E : &SectionSpecsAreEqual)) {
188 i : return false;
189 : }
190 :
191 : // If we reach here then the orders are identical.
192 E : return true;
193 E : }
194 :
195 : } // namespace testing
|