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/grinder/basic_block_util.h"
16 :
17 : #include "gmock/gmock.h"
18 : #include "gtest/gtest.h"
19 : #include "syzygy/common/indexed_frequency_data.h"
20 : #include "syzygy/core/unittest_util.h"
21 : #include "syzygy/grinder/grinder.h"
22 : #include "syzygy/pe/pe_file.h"
23 : #include "syzygy/pe/unittest_util.h"
24 :
25 : namespace grinder {
26 : namespace basic_block_util {
27 :
28 : namespace {
29 :
30 : using testing::GetExeTestDataRelativePath;
31 : using trace::parser::AbsoluteAddress64;
32 : using trace::parser::Parser;
33 :
34 : class TestGrinder : public GrinderInterface {
35 : public:
36 E : TestGrinder() : parser_(NULL), on_bb_freq_was_called_(false) {
37 : // Nothing else to initialize.
38 E : }
39 :
40 : // @name GrinderInterface implementation.
41 : // @{
42 E : virtual bool ParseCommandLine(const CommandLine*) OVERRIDE { return true; }
43 E : virtual void SetParser(Parser* parser) OVERRIDE {
44 E : ASSERT_TRUE(parser != NULL);
45 E : parser_ = parser;
46 E : }
47 E : virtual bool Grind() OVERRIDE { return true; };
48 E : virtual bool OutputData(FILE*) OVERRIDE { return true; }
49 : // @}
50 :
51 : // @name ParseEventHandler overrides.
52 : // @{
53 : virtual void OnIndexedFrequency(
54 : base::Time time,
55 : DWORD process_id,
56 : DWORD thread_id,
57 E : const TraceIndexedFrequencyData* data) OVERRIDE {
58 E : on_bb_freq_was_called_ = true;
59 E : ASSERT_TRUE(data != NULL);
60 :
61 E : ASSERT_TRUE(
62 : data->data_type == common::IndexedFrequencyData::BASIC_BLOCK_ENTRY ||
63 : data->data_type == common::IndexedFrequencyData::COVERAGE);
64 :
65 : // Lookup the module information.
66 : const ModuleInformation* module_info = parser_->GetModuleInformation(
67 E : process_id, AbsoluteAddress64(data->module_base_addr));
68 E : ASSERT_TRUE(module_info != NULL);
69 :
70 : // Load the PDB information.
71 E : PdbInfo* pdb_info = NULL;
72 E : ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &pdb_info));
73 E : ASSERT_TRUE(pdb_info != NULL);
74 :
75 : // Validate that the cache works.
76 E : PdbInfo* dup_pdb_info = NULL;
77 E : ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &dup_pdb_info));
78 E : ASSERT_EQ(pdb_info, dup_pdb_info);
79 E : }
80 :
81 : Parser* parser_;
82 : PdbInfoMap pdb_info_cache_;
83 : bool on_bb_freq_was_called_;
84 : };
85 :
86 E : void PopulateModuleInformation(ModuleInformation* module_info) {
87 E : ASSERT_TRUE(module_info != NULL);
88 E : module_info->base_address = 0xDEADBEEF;
89 E : module_info->image_checksum = 0xCAFEBABE;
90 E : module_info->image_file_name = L"image_file_name";
91 E : module_info->module_size = 0x12345678;
92 E : module_info->time_date_stamp = 0x87654321;
93 E : }
94 :
95 : } // namespace
96 :
97 E : TEST(GrinderBasicBlockUtilTest, ModuleIdentityComparator) {
98 E : ModuleInformation a;
99 E : PopulateModuleInformation(&a);
100 :
101 E : ModuleInformation b = a;
102 : ModuleIdentityComparator comp;
103 : // The two should compare equal.
104 E : EXPECT_FALSE(comp(a, b));
105 E : EXPECT_FALSE(comp(b, a));
106 :
107 : // Jiggle b's base address and checksum.
108 E : b.base_address -= 10;
109 E : b.image_checksum += 100;
110 : // The two should still compare equal.
111 E : EXPECT_FALSE(comp(a, b));
112 E : EXPECT_FALSE(comp(b, a));
113 :
114 E : b = a;
115 E : b.module_size -= 1;
116 E : EXPECT_FALSE(comp(a, b));
117 E : EXPECT_TRUE(comp(b, a));
118 :
119 E : b = a;
120 E : b.time_date_stamp += 1;
121 E : EXPECT_TRUE(comp(a, b));
122 E : EXPECT_FALSE(comp(b, a));
123 :
124 E : b = a;
125 E : b.image_file_name = L"foo";
126 E : EXPECT_FALSE(comp(a, b));
127 E : EXPECT_TRUE(comp(b, a));
128 E : }
129 :
130 E : TEST(GrinderBasicBlockUtilTest, InitModuleInfo) {
131 : // Create a prototype module info structure.
132 E : ModuleInformation orig_module_info;
133 E : EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&orig_module_info));
134 :
135 : // Initialize a signature matching the prototype.
136 E : pe::PEFile::Signature signature(orig_module_info);
137 :
138 : // Extract the module information from the signature. It should match the
139 : // prototype.
140 E : ModuleInformation new_module_info;
141 E : InitModuleInfo(signature, &new_module_info);
142 E : EXPECT_EQ(orig_module_info, new_module_info);
143 E : }
144 :
145 E : TEST(GrinderBasicBlockUtilTest, FindEntryCountVector) {
146 : // Create a prototype module info structure.
147 E : ModuleInformation module_info;
148 E : EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&module_info));
149 :
150 : // Initialize a signature matching the module_info.
151 E : pe::PEFile::Signature signature(module_info);
152 :
153 : // Create an empty entry count map.
154 E : ModuleEntryCountMap module_entry_count_map;
155 E : EXPECT_TRUE(module_entry_count_map.empty());
156 :
157 : // Search the empty map for the module..
158 E : const EntryCountMap* entry_count_map = NULL;
159 : EXPECT_FALSE(
160 E : FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
161 E : EXPECT_EQ(NULL, entry_count_map);
162 :
163 : // Insert a matching module and search again.
164 E : const EntryCountMap* entry_count_map_1 = &module_entry_count_map[module_info];
165 : EXPECT_TRUE(
166 E : FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
167 E : EXPECT_EQ(entry_count_map_1, entry_count_map);
168 :
169 : // Insert a second matching module and search again. This should fail.
170 E : module_info.image_file_name = L"Some other file name";
171 E : const EntryCountMap* entry_count_map_2 = &module_entry_count_map[module_info];
172 E : ASSERT_NE(entry_count_map_1, entry_count_map_2);
173 : EXPECT_FALSE(
174 E : FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
175 E : EXPECT_EQ(NULL, entry_count_map);
176 E : }
177 :
178 E : TEST(GrinderBasicBlockUtilTest, LoadBasicBlockRanges) {
179 E : RelativeAddressRangeVector bb_ranges;
180 :
181 : base::FilePath wrong_file_type(GetExeTestDataRelativePath(
182 E : testing::kCoverageTraceFiles[0]));
183 E : EXPECT_FALSE(LoadBasicBlockRanges(wrong_file_type, &bb_ranges));
184 :
185 : base::FilePath wrong_pdb(
186 E : GetExeTestDataRelativePath(testing::kTestDllPdbName));
187 E : EXPECT_FALSE(LoadBasicBlockRanges(wrong_pdb, &bb_ranges));
188 :
189 : base::FilePath right_pdb(GetExeTestDataRelativePath(
190 E : testing::kBBEntryInstrumentedTestDllPdbName));
191 E : EXPECT_TRUE(LoadBasicBlockRanges(right_pdb, &bb_ranges));
192 E : }
193 :
194 E : TEST(GrinderBasicBlockUtilTest, LoadPdbInfo) {
195 : // TODO(rogerm): Rewrite me! This test doesn't directly test LoadPdbInfo.
196 E : Parser parser;
197 E : TestGrinder grinder;
198 E : ASSERT_TRUE(parser.Init(&grinder));
199 E : ASSERT_NO_FATAL_FAILURE(grinder.SetParser(&parser));
200 E : ASSERT_TRUE(grinder.ParseCommandLine(NULL));
201 : ASSERT_TRUE(parser.OpenTraceFile(GetExeTestDataRelativePath(
202 E : testing::kCoverageTraceFiles[0])));
203 E : ASSERT_TRUE(parser.Consume());
204 E : ASSERT_TRUE(grinder.on_bb_freq_was_called_);
205 E : ASSERT_TRUE(grinder.Grind());
206 E : ASSERT_TRUE(grinder.OutputData(NULL));
207 E : }
208 :
209 E : TEST(GrinderBasicBlockUtilTest, IsValidFrequencySize) {
210 E : EXPECT_TRUE(IsValidFrequencySize(1));
211 E : EXPECT_TRUE(IsValidFrequencySize(2));
212 E : EXPECT_TRUE(IsValidFrequencySize(4));
213 :
214 E : EXPECT_FALSE(IsValidFrequencySize(0));
215 E : EXPECT_FALSE(IsValidFrequencySize(3));
216 E : EXPECT_FALSE(IsValidFrequencySize(8));
217 E : EXPECT_FALSE(IsValidFrequencySize(65536));
218 E : }
219 :
220 E : TEST(GrinderBasicBlockUtilTest, GetFrequency) {
221 : // Counter data we'll test against.
222 : static const uint8 kData[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
223 : 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB };
224 :
225 : // A buffer over which we'll overlay a TraceIndexedFrequencyData struct.
226 E : uint8 buffer[sizeof(TraceIndexedFrequencyData) + sizeof(kData) - 1] = {};
227 E : ::memset(buffer, 0, sizeof(buffer));
228 :
229 : // A TraceDataBlockFrequencyData structure with the frequency_data populated
230 : // with a copy of kData.
231 : TraceIndexedFrequencyData* data =
232 E : reinterpret_cast<TraceIndexedFrequencyData*>(buffer);
233 E : ::memcpy(data->frequency_data, kData, sizeof(kData));
234 :
235 : // Validate 1-byte frequency data.
236 E : data->frequency_size = 1;
237 E : data->num_entries = sizeof(kData) / data->frequency_size;
238 E : EXPECT_EQ(0x44, GetFrequency(data, 0x4));
239 E : EXPECT_EQ(0xAA, GetFrequency(data, 0xA));
240 :
241 : // Validate 2-byte frequency data.
242 E : data->frequency_size = 2;
243 E : data->num_entries = sizeof(kData) / data->frequency_size;
244 E : EXPECT_EQ(0x5544, GetFrequency(data, 0x2));
245 E : EXPECT_EQ(0x9988, GetFrequency(data, 0x4));
246 :
247 : // Validate 4-byte frequency data.
248 E : data->frequency_size = 4;
249 E : data->num_entries = sizeof(kData) / data->frequency_size;
250 E : EXPECT_EQ(0x33221100, GetFrequency(data, 0x0));
251 E : EXPECT_EQ(0xBBAA9988, GetFrequency(data, 0x2));
252 E : }
253 :
254 : } // namespace basic_block_util
255 : } // namespace grinder
|