OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Crashpad Authors. 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 "minidump/minidump_module_writer.h" | |
16 | |
17 #include <dbghelp.h> | |
18 #include <stdint.h> | |
19 #include <string.h> | |
20 | |
21 #include "base/strings/utf_string_conversions.h" | |
22 #include "gtest/gtest.h" | |
23 #include "minidump/minidump_extensions.h" | |
24 #include "minidump/minidump_file_writer.h" | |
25 #include "minidump/minidump_test_util.h" | |
26 #include "util/file/string_file_writer.h" | |
27 #include "util/misc/uuid.h" | |
28 | |
29 namespace { | |
30 | |
31 using namespace crashpad; | |
32 using namespace crashpad::test; | |
33 | |
34 void GetModuleListStream(const std::string& file_contents, | |
35 const MINIDUMP_MODULE_LIST** module_list) { | |
36 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | |
37 const size_t kModuleListStreamOffset = | |
38 kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); | |
39 const size_t kModulesOffset = | |
40 kModuleListStreamOffset + sizeof(MINIDUMP_MODULE_LIST); | |
41 | |
42 ASSERT_GE(file_contents.size(), kModulesOffset); | |
43 | |
44 const MINIDUMP_HEADER* header = | |
45 reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]); | |
46 | |
47 VerifyMinidumpHeader(header, 1, 0); | |
Robert Sesek
2014/08/12 22:56:05
IWYU
| |
48 if (testing::Test::HasFatalFailure()) { | |
49 return; | |
50 } | |
51 | |
52 const MINIDUMP_DIRECTORY* directory = | |
53 reinterpret_cast<const MINIDUMP_DIRECTORY*>( | |
54 &file_contents[kDirectoryOffset]); | |
55 | |
56 ASSERT_EQ(kMinidumpStreamTypeModuleList, directory->StreamType); | |
57 ASSERT_GE(directory->Location.DataSize, sizeof(MINIDUMP_MODULE_LIST)); | |
58 ASSERT_EQ(kModuleListStreamOffset, directory->Location.Rva); | |
59 | |
60 *module_list = reinterpret_cast<const MINIDUMP_MODULE_LIST*>( | |
61 &file_contents[kModuleListStreamOffset]); | |
62 | |
63 ASSERT_EQ(sizeof(MINIDUMP_MODULE_LIST) + | |
64 (*module_list)->NumberOfModules * sizeof(MINIDUMP_MODULE), | |
65 directory->Location.DataSize); | |
66 } | |
67 | |
68 TEST(MinidumpModuleWriter, EmptyModuleList) { | |
69 MinidumpFileWriter minidump_file_writer; | |
70 MinidumpModuleListWriter module_list_writer; | |
71 | |
72 minidump_file_writer.AddStream(&module_list_writer); | |
73 | |
74 StringFileWriter file_writer; | |
75 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
76 | |
77 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
78 sizeof(MINIDUMP_MODULE_LIST), | |
79 file_writer.string().size()); | |
80 | |
81 const MINIDUMP_MODULE_LIST* module_list; | |
82 GetModuleListStream(file_writer.string(), &module_list); | |
83 if (Test::HasFatalFailure()) { | |
84 return; | |
85 } | |
86 | |
87 EXPECT_EQ(0u, module_list->NumberOfModules); | |
88 } | |
89 | |
90 // ExpectModule() verifies that |expected| matches |observed|. Fields that are | |
91 // supposed to contain constant magic numbers are verified against the expected | |
92 // constants instead of |expected|. Reserved fields are verified to be 0. RVA | |
93 // and MINIDUMP_LOCATION_DESCRIPTOR fields are not verified against |expected|. | |
94 // Instead, |ModuleNameRva| is used to locate the module name, which is compared | |
95 // against |expected_module_name|. If |expected_pdb_name| is non-NULL, | |
96 // |CvRecord| is used to locate a CodeView record, whose fields are compared | |
97 // against the |expected_pdb_*| values. If |expected_pdb_uuid| is supplied, the | |
98 // CodeView record must be a PDB 7.0 link, otherwise, it must be a PDB 2.0 link. | |
99 // If |expected_pdb_name| is NULL, |CvRecord| must be absent. Similarly, | |
100 // |expected_debug_name| is used to control verification of |MiscRecord| against | |
101 // the |expected_debug_*| values. | |
102 void ExpectModule(const MINIDUMP_MODULE* expected, | |
103 const MINIDUMP_MODULE* observed, | |
104 const std::string& file_contents, | |
105 const char* expected_module_name, | |
Robert Sesek
2014/08/12 22:56:05
Why const char* for the expected names instead of
Mark Mentovai
2014/08/12 23:23:26
rsesek wrote:
| |
106 const char* expected_pdb_name, | |
107 const UUID* expected_pdb_uuid, | |
108 time_t expected_pdb_timestamp, | |
109 uint32_t expected_pdb_age, | |
110 const char* expected_debug_name, | |
111 uint32_t expected_debug_type, | |
112 bool expected_debug_utf16) { | |
113 EXPECT_EQ(expected->BaseOfImage, observed->BaseOfImage); | |
114 EXPECT_EQ(expected->SizeOfImage, observed->SizeOfImage); | |
115 EXPECT_EQ(expected->CheckSum, observed->CheckSum); | |
116 EXPECT_EQ(expected->TimeDateStamp, observed->TimeDateStamp); | |
117 EXPECT_EQ(static_cast<uint32_t>(VS_FFI_SIGNATURE), | |
118 observed->VersionInfo.dwSignature); | |
119 EXPECT_EQ(static_cast<uint32_t>(VS_FFI_STRUCVERSION), | |
120 observed->VersionInfo.dwStrucVersion); | |
121 EXPECT_EQ(expected->VersionInfo.dwFileVersionMS, | |
122 observed->VersionInfo.dwFileVersionMS); | |
123 EXPECT_EQ(expected->VersionInfo.dwFileVersionLS, | |
124 observed->VersionInfo.dwFileVersionLS); | |
125 EXPECT_EQ(expected->VersionInfo.dwProductVersionMS, | |
126 observed->VersionInfo.dwProductVersionMS); | |
127 EXPECT_EQ(expected->VersionInfo.dwProductVersionLS, | |
128 observed->VersionInfo.dwProductVersionLS); | |
129 EXPECT_EQ(expected->VersionInfo.dwFileFlagsMask, | |
130 observed->VersionInfo.dwFileFlagsMask); | |
131 EXPECT_EQ(expected->VersionInfo.dwFileFlags, | |
132 observed->VersionInfo.dwFileFlags); | |
133 EXPECT_EQ(expected->VersionInfo.dwFileOS, observed->VersionInfo.dwFileOS); | |
134 EXPECT_EQ(expected->VersionInfo.dwFileType, observed->VersionInfo.dwFileType); | |
135 EXPECT_EQ(expected->VersionInfo.dwFileSubtype, | |
136 observed->VersionInfo.dwFileSubtype); | |
137 EXPECT_EQ(expected->VersionInfo.dwFileDateMS, | |
138 observed->VersionInfo.dwFileDateMS); | |
139 EXPECT_EQ(expected->VersionInfo.dwFileDateLS, | |
140 observed->VersionInfo.dwFileDateLS); | |
141 EXPECT_EQ(0u, observed->Reserved0); | |
142 EXPECT_EQ(0u, observed->Reserved1); | |
143 | |
144 EXPECT_NE(0u, observed->ModuleNameRva); | |
145 ASSERT_LE(observed->ModuleNameRva, | |
146 file_contents.size() - sizeof(MINIDUMP_STRING)); | |
147 const MINIDUMP_STRING* module_name = reinterpret_cast<const MINIDUMP_STRING*>( | |
148 &file_contents[observed->ModuleNameRva]); | |
149 ASSERT_LE(observed->ModuleNameRva + sizeof(MINIDUMP_STRING) + | |
150 (module_name->Length + 1), | |
151 file_contents.size()); | |
152 ASSERT_EQ(0u, module_name->Length % 2); | |
153 string16 observed_module_name_utf16( | |
154 reinterpret_cast<const char16*>( | |
155 &file_contents[observed->ModuleNameRva + sizeof(MINIDUMP_STRING)]), | |
156 module_name->Length / 2); | |
157 string16 expected_module_name_utf16 = base::UTF8ToUTF16(expected_module_name); | |
158 EXPECT_EQ(expected_module_name_utf16, observed_module_name_utf16); | |
159 | |
160 if (expected_pdb_name) { | |
Robert Sesek
2014/08/12 22:56:05
If this weren't in a test, this is where I'd tell
Mark Mentovai
2014/08/12 23:23:26
rsesek wrote:
| |
161 EXPECT_NE(0u, observed->CvRecord.Rva); | |
162 ASSERT_LE(observed->CvRecord.Rva + observed->CvRecord.DataSize, | |
163 file_contents.size()); | |
164 | |
165 std::string observed_pdb_name; | |
166 if (expected_pdb_uuid) { | |
167 // The CodeView record should be a PDB 7.0 link. | |
168 EXPECT_GE(observed->CvRecord.DataSize, | |
169 sizeof(MinidumpModuleCodeViewRecordPDB70)); | |
170 const MinidumpModuleCodeViewRecordPDB70* codeview_pdb70_record = | |
171 reinterpret_cast<const MinidumpModuleCodeViewRecordPDB70*>( | |
172 &file_contents[observed->CvRecord.Rva]); | |
173 EXPECT_EQ(MinidumpModuleCodeViewRecordPDB70::kSignature, | |
174 codeview_pdb70_record->signature); | |
175 EXPECT_EQ(0, | |
176 memcmp(expected_pdb_uuid, | |
177 &codeview_pdb70_record->uuid, | |
178 sizeof(codeview_pdb70_record->uuid))); | |
179 EXPECT_EQ(expected_pdb_age, codeview_pdb70_record->age); | |
180 | |
181 observed_pdb_name.assign( | |
182 reinterpret_cast<const char*>(&codeview_pdb70_record->pdb_name[0]), | |
183 observed->CvRecord.DataSize - | |
184 offsetof(MinidumpModuleCodeViewRecordPDB70, pdb_name)); | |
185 } else { | |
186 // The CodeView record should be a PDB 2.0 link. | |
187 EXPECT_GE(observed->CvRecord.DataSize, | |
188 sizeof(MinidumpModuleCodeViewRecordPDB20)); | |
189 const MinidumpModuleCodeViewRecordPDB20* codeview_pdb20_record = | |
190 reinterpret_cast<const MinidumpModuleCodeViewRecordPDB20*>( | |
191 &file_contents[observed->CvRecord.Rva]); | |
192 EXPECT_EQ(MinidumpModuleCodeViewRecordPDB20::kSignature, | |
193 codeview_pdb20_record->signature); | |
194 EXPECT_EQ(expected_pdb_timestamp, codeview_pdb20_record->timestamp); | |
195 EXPECT_EQ(expected_pdb_age, codeview_pdb20_record->age); | |
196 | |
197 observed_pdb_name.assign( | |
198 reinterpret_cast<const char*>(&codeview_pdb20_record->pdb_name[0]), | |
199 observed->CvRecord.DataSize - | |
200 offsetof(MinidumpModuleCodeViewRecordPDB20, pdb_name)); | |
201 } | |
202 | |
203 // Check for, and then remove, the NUL terminator. | |
204 EXPECT_EQ('\0', observed_pdb_name[observed_pdb_name.size() - 1]); | |
205 observed_pdb_name.resize(observed_pdb_name.size() - 1); | |
206 | |
207 EXPECT_EQ(expected_pdb_name, observed_pdb_name); | |
208 } else { | |
209 // There should be no CodeView record. | |
210 EXPECT_EQ(0u, observed->CvRecord.DataSize); | |
211 EXPECT_EQ(0u, observed->CvRecord.Rva); | |
212 } | |
213 | |
214 if (expected_debug_name) { | |
215 EXPECT_GE(observed->MiscRecord.DataSize, sizeof(IMAGE_DEBUG_MISC)); | |
216 EXPECT_NE(0u, observed->MiscRecord.Rva); | |
217 ASSERT_LE(observed->MiscRecord.Rva + observed->MiscRecord.DataSize, | |
218 file_contents.size()); | |
219 const IMAGE_DEBUG_MISC* misc_debug_record = | |
220 reinterpret_cast<const IMAGE_DEBUG_MISC*>( | |
221 &file_contents[observed->MiscRecord.Rva]); | |
222 EXPECT_EQ(expected_debug_type, misc_debug_record->DataType); | |
223 EXPECT_EQ(observed->MiscRecord.DataSize, misc_debug_record->Length); | |
224 EXPECT_EQ(expected_debug_utf16, misc_debug_record->Unicode); | |
225 EXPECT_EQ(0u, misc_debug_record->Reserved[0]); | |
226 EXPECT_EQ(0u, misc_debug_record->Reserved[1]); | |
227 EXPECT_EQ(0u, misc_debug_record->Reserved[2]); | |
228 | |
229 // Check for the NUL terminator. | |
230 size_t bytes_available = | |
231 misc_debug_record->Length - offsetof(IMAGE_DEBUG_MISC, Data); | |
232 EXPECT_EQ('\0', misc_debug_record->Data[bytes_available - 1]); | |
233 std::string observed_data( | |
234 reinterpret_cast<const char*>(misc_debug_record->Data)); | |
235 | |
236 size_t bytes_used; | |
237 if (misc_debug_record->Unicode) { | |
238 string16 observed_data_utf16( | |
239 reinterpret_cast<const char16*>(misc_debug_record->Data)); | |
240 bytes_used = (observed_data_utf16.size() + 1) * sizeof(char16); | |
241 observed_data = base::UTF16ToUTF8(observed_data_utf16); | |
242 } else { | |
243 observed_data = reinterpret_cast<const char*>(misc_debug_record->Data); | |
244 bytes_used = (observed_data.size() + 1) * sizeof(char); | |
245 } | |
246 EXPECT_LE(bytes_used, bytes_available); | |
247 | |
248 // Make sure that any padding bytes after the first NUL are also NUL. | |
249 for (size_t index = bytes_used; index < bytes_available; ++index) { | |
250 EXPECT_EQ('\0', misc_debug_record->Data[index]); | |
251 } | |
252 | |
253 EXPECT_EQ(expected_debug_name, observed_data); | |
254 } else { | |
255 // There should be no miscellaneous debugging record. | |
256 EXPECT_EQ(0u, observed->MiscRecord.DataSize); | |
257 EXPECT_EQ(0u, observed->MiscRecord.Rva); | |
258 } | |
259 } | |
260 | |
261 TEST(MinidumpModuleWriter, EmptyModule) { | |
262 MinidumpFileWriter minidump_file_writer; | |
263 MinidumpModuleListWriter module_list_writer; | |
264 | |
265 const char kModuleName[] = "test_executable"; | |
266 | |
267 MinidumpModuleWriter module_writer; | |
268 module_writer.SetName(kModuleName); | |
269 | |
270 module_list_writer.AddModule(&module_writer); | |
271 minidump_file_writer.AddStream(&module_list_writer); | |
272 | |
273 StringFileWriter file_writer; | |
274 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
275 | |
276 ASSERT_GT(file_writer.string().size(), | |
277 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
278 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE)); | |
279 | |
280 const MINIDUMP_MODULE_LIST* module_list; | |
281 GetModuleListStream(file_writer.string(), &module_list); | |
282 if (Test::HasFatalFailure()) { | |
283 return; | |
284 } | |
285 | |
286 EXPECT_EQ(1u, module_list->NumberOfModules); | |
287 | |
288 MINIDUMP_MODULE expected = {}; | |
289 ExpectModule(&expected, | |
290 &module_list->Modules[0], | |
291 file_writer.string(), | |
292 kModuleName, | |
293 NULL, | |
294 NULL, | |
295 0, | |
296 0, | |
297 NULL, | |
298 0, | |
299 false); | |
300 if (Test::HasFatalFailure()) { | |
301 return; | |
302 } | |
303 } | |
304 | |
305 TEST(MinidumpModuleWriter, OneModule) { | |
306 MinidumpFileWriter minidump_file_writer; | |
307 MinidumpModuleListWriter module_list_writer; | |
308 | |
309 const char kModuleName[] = "statically_linked"; | |
310 const uint64_t kModuleBase = 0x000000010da69000ull; | |
311 const uint32_t kModuleSize = 0x1000; | |
312 const uint32_t kChecksum = 0x76543210; | |
313 const time_t kTimestamp = 0x386d4380; | |
314 const uint32_t kFileVersionMS = 0x00010002; | |
315 const uint32_t kFileVersionLS = 0x00030004; | |
316 const uint32_t kProductVersionMS = 0x00050006; | |
317 const uint32_t kProductVersionLS = 0x00070008; | |
318 const uint32_t kFileFlagsMask = VS_FF_DEBUG | VS_FF_PRERELEASE | | |
319 VS_FF_PATCHED | VS_FF_PRIVATEBUILD | | |
320 VS_FF_INFOINFERRED | VS_FF_SPECIALBUILD; | |
321 const uint32_t kFileFlags = VS_FF_PRIVATEBUILD | VS_FF_SPECIALBUILD; | |
322 const uint32_t kFileOS = VOS_DOS; | |
323 const uint32_t kFileType = VFT_DRV; | |
324 const uint32_t kFileSubtype = VFT2_DRV_KEYBOARD; | |
325 const char kPDBName[] = "statical.pdb"; | |
326 const uint8_t kPDBUUIDBytes[16] = | |
327 {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, | |
328 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f}; | |
329 UUID pdb_uuid; | |
330 pdb_uuid.InitializeFromBytes(kPDBUUIDBytes); | |
331 const uint32_t kPDBAge = 1; | |
332 const uint32_t kDebugType = IMAGE_DEBUG_MISC_EXENAME; | |
333 const char kDebugName[] = "statical.dbg"; | |
334 const bool kDebugUTF16 = false; | |
335 | |
336 MinidumpModuleWriter module_writer; | |
337 module_writer.SetName(kModuleName); | |
338 module_writer.SetImageBaseAddress(kModuleBase); | |
339 module_writer.SetImageSize(kModuleSize); | |
340 module_writer.SetChecksum(kChecksum); | |
341 module_writer.SetTimestamp(kTimestamp); | |
342 module_writer.SetFileVersion(kFileVersionMS >> 16, | |
343 kFileVersionMS & 0xffff, | |
344 kFileVersionLS >> 16, | |
345 kFileVersionLS & 0xffff); | |
346 module_writer.SetProductVersion(kProductVersionMS >> 16, | |
347 kProductVersionMS & 0xffff, | |
348 kProductVersionLS >> 16, | |
349 kProductVersionLS & 0xffff); | |
350 module_writer.SetFileFlagsAndMask(kFileFlags, kFileFlagsMask); | |
351 module_writer.SetFileOS(kFileOS); | |
352 module_writer.SetFileTypeAndSubtype(kFileType, kFileSubtype); | |
353 | |
354 MinidumpModuleCodeViewRecordPDB70Writer codeview_pdb70_writer; | |
355 codeview_pdb70_writer.SetPDBName(kPDBName); | |
356 codeview_pdb70_writer.SetUUIDAndAge(pdb_uuid, kPDBAge); | |
357 module_writer.SetCodeViewRecord(&codeview_pdb70_writer); | |
358 | |
359 MinidumpModuleMiscDebugRecordWriter misc_debug_writer; | |
360 misc_debug_writer.SetDataType(kDebugType); | |
361 misc_debug_writer.SetData(kDebugName, kDebugUTF16); | |
362 module_writer.SetMiscDebugRecord(&misc_debug_writer); | |
363 | |
364 module_list_writer.AddModule(&module_writer); | |
365 minidump_file_writer.AddStream(&module_list_writer); | |
366 | |
367 StringFileWriter file_writer; | |
368 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
369 | |
370 ASSERT_GT(file_writer.string().size(), | |
371 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
372 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE)); | |
373 | |
374 const MINIDUMP_MODULE_LIST* module_list; | |
375 GetModuleListStream(file_writer.string(), &module_list); | |
376 if (Test::HasFatalFailure()) { | |
377 return; | |
378 } | |
379 | |
380 EXPECT_EQ(1u, module_list->NumberOfModules); | |
381 | |
382 MINIDUMP_MODULE expected = {}; | |
383 expected.BaseOfImage = kModuleBase; | |
384 expected.SizeOfImage = kModuleSize; | |
385 expected.CheckSum = kChecksum; | |
386 expected.TimeDateStamp = kTimestamp; | |
387 expected.VersionInfo.dwFileVersionMS = kFileVersionMS; | |
388 expected.VersionInfo.dwFileVersionLS = kFileVersionLS; | |
389 expected.VersionInfo.dwProductVersionMS = kProductVersionMS; | |
390 expected.VersionInfo.dwProductVersionLS = kProductVersionLS; | |
391 expected.VersionInfo.dwFileFlagsMask = kFileFlagsMask; | |
392 expected.VersionInfo.dwFileFlags = kFileFlags; | |
393 expected.VersionInfo.dwFileOS = kFileOS; | |
394 expected.VersionInfo.dwFileType = kFileType; | |
395 expected.VersionInfo.dwFileSubtype = kFileSubtype; | |
396 | |
397 ExpectModule(&expected, | |
398 &module_list->Modules[0], | |
399 file_writer.string(), | |
400 kModuleName, | |
401 kPDBName, | |
402 &pdb_uuid, | |
403 0, | |
404 kPDBAge, | |
405 kDebugName, | |
406 kDebugType, | |
407 kDebugUTF16); | |
408 if (Test::HasFatalFailure()) { | |
409 return; | |
410 } | |
411 } | |
412 | |
413 TEST(MinidumpModuleWriter, OneModule_CodeViewUsesPDB20_MiscUsesUTF16) { | |
414 // MinidumpModuleWriter.OneModule tested with a PDB 7.0 link as the CodeView | |
415 // record and an IMAGE_DEBUG_MISC record in UTF-8. This test exercises the | |
416 // alternatives, a PDB 2.0 link as the CodeView record and an IMAGE_DEBUG_MISC | |
417 // record with UTF-16 data. | |
418 MinidumpFileWriter minidump_file_writer; | |
419 MinidumpModuleListWriter module_list_writer; | |
420 | |
421 const char kModuleName[] = "dinosaur"; | |
422 const char kPDBName[] = "d1n05.pdb"; | |
423 const time_t kPDBTimestamp = 0x386d4380; | |
424 const uint32_t kPDBAge = 1; | |
425 const uint32_t kDebugType = IMAGE_DEBUG_MISC_EXENAME; | |
426 const char kDebugName[] = "d1n05.dbg"; | |
427 const bool kDebugUTF16 = true; | |
428 | |
429 MinidumpModuleWriter module_writer; | |
430 module_writer.SetName(kModuleName); | |
431 | |
432 MinidumpModuleCodeViewRecordPDB20Writer codeview_pdb20_writer; | |
433 codeview_pdb20_writer.SetPDBName(kPDBName); | |
434 codeview_pdb20_writer.SetTimestampAndAge(kPDBTimestamp, kPDBAge); | |
435 module_writer.SetCodeViewRecord(&codeview_pdb20_writer); | |
436 | |
437 MinidumpModuleMiscDebugRecordWriter misc_debug_writer; | |
438 misc_debug_writer.SetDataType(kDebugType); | |
439 misc_debug_writer.SetData(kDebugName, kDebugUTF16); | |
440 module_writer.SetMiscDebugRecord(&misc_debug_writer); | |
441 | |
442 module_list_writer.AddModule(&module_writer); | |
443 minidump_file_writer.AddStream(&module_list_writer); | |
444 | |
445 StringFileWriter file_writer; | |
446 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
447 | |
448 ASSERT_GT(file_writer.string().size(), | |
449 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
450 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE)); | |
451 | |
452 const MINIDUMP_MODULE_LIST* module_list; | |
453 GetModuleListStream(file_writer.string(), &module_list); | |
454 if (Test::HasFatalFailure()) { | |
455 return; | |
456 } | |
457 | |
458 EXPECT_EQ(1u, module_list->NumberOfModules); | |
459 | |
460 MINIDUMP_MODULE expected = {}; | |
461 | |
462 ExpectModule(&expected, | |
463 &module_list->Modules[0], | |
464 file_writer.string(), | |
465 kModuleName, | |
466 kPDBName, | |
467 NULL, | |
468 kPDBTimestamp, | |
469 kPDBAge, | |
470 kDebugName, | |
471 kDebugType, | |
472 kDebugUTF16); | |
473 if (Test::HasFatalFailure()) { | |
474 return; | |
475 } | |
476 } | |
477 | |
478 TEST(MinidumpModuleWriter, ThreeModules) { | |
479 MinidumpFileWriter minidump_file_writer; | |
480 MinidumpModuleListWriter module_list_writer; | |
481 | |
482 const char kModuleName1[] = "main"; | |
483 const uint64_t kModuleBase1 = 0x0000000100101000ull; | |
484 const uint32_t kModuleSize1 = 0xf000; | |
485 const char kPDBName1[] = "main"; | |
486 const uint8_t kPDBUUIDBytes1[16] = | |
487 {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, | |
488 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}; | |
489 UUID pdb_uuid_1; | |
490 pdb_uuid_1.InitializeFromBytes(kPDBUUIDBytes1); | |
491 const uint32_t kPDBAge1 = 0; | |
492 | |
493 const char kModuleName2[] = "ld.so"; | |
494 const uint64_t kModuleBase2 = 0x0000000200202000ull; | |
495 const uint32_t kModuleSize2 = 0x1e000; | |
496 | |
497 const char kModuleName3[] = "libc.so"; | |
498 const uint64_t kModuleBase3 = 0x0000000300303000ull; | |
499 const uint32_t kModuleSize3 = 0x2d000; | |
500 const char kPDBName3[] = "libc.so"; | |
501 const uint8_t kPDBUUIDBytes3[16] = | |
502 {0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, | |
503 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00}; | |
504 UUID pdb_uuid_3; | |
505 pdb_uuid_3.InitializeFromBytes(kPDBUUIDBytes3); | |
506 const uint32_t kPDBAge3 = 0; | |
507 | |
508 MinidumpModuleWriter module_writer_1; | |
509 module_writer_1.SetName(kModuleName1); | |
510 module_writer_1.SetImageBaseAddress(kModuleBase1); | |
511 module_writer_1.SetImageSize(kModuleSize1); | |
512 | |
513 MinidumpModuleCodeViewRecordPDB70Writer codeview_pdb70_writer_1; | |
514 codeview_pdb70_writer_1.SetPDBName(kPDBName1); | |
515 codeview_pdb70_writer_1.SetUUIDAndAge(pdb_uuid_1, kPDBAge1); | |
516 module_writer_1.SetCodeViewRecord(&codeview_pdb70_writer_1); | |
517 | |
518 module_list_writer.AddModule(&module_writer_1); | |
519 | |
520 MinidumpModuleWriter module_writer_2; | |
521 module_writer_2.SetName(kModuleName2); | |
522 module_writer_2.SetImageBaseAddress(kModuleBase2); | |
523 module_writer_2.SetImageSize(kModuleSize2); | |
524 | |
525 module_list_writer.AddModule(&module_writer_2); | |
526 | |
527 MinidumpModuleWriter module_writer_3; | |
528 module_writer_3.SetName(kModuleName3); | |
529 module_writer_3.SetImageBaseAddress(kModuleBase3); | |
530 module_writer_3.SetImageSize(kModuleSize3); | |
531 | |
532 MinidumpModuleCodeViewRecordPDB70Writer codeview_pdb70_writer_3; | |
533 codeview_pdb70_writer_3.SetPDBName(kPDBName3); | |
534 codeview_pdb70_writer_3.SetUUIDAndAge(pdb_uuid_3, kPDBAge3); | |
535 module_writer_3.SetCodeViewRecord(&codeview_pdb70_writer_3); | |
536 | |
537 module_list_writer.AddModule(&module_writer_3); | |
538 | |
539 minidump_file_writer.AddStream(&module_list_writer); | |
540 | |
541 StringFileWriter file_writer; | |
542 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
543 | |
544 ASSERT_GT(file_writer.string().size(), | |
545 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
546 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE)); | |
547 | |
548 const MINIDUMP_MODULE_LIST* module_list; | |
549 GetModuleListStream(file_writer.string(), &module_list); | |
550 if (Test::HasFatalFailure()) { | |
551 return; | |
552 } | |
553 | |
554 EXPECT_EQ(3u, module_list->NumberOfModules); | |
555 | |
556 MINIDUMP_MODULE expected = {}; | |
557 | |
558 { | |
559 SCOPED_TRACE("module 0"); | |
560 | |
561 expected.BaseOfImage = kModuleBase1; | |
562 expected.SizeOfImage = kModuleSize1; | |
563 | |
564 ExpectModule(&expected, | |
565 &module_list->Modules[0], | |
566 file_writer.string(), | |
567 kModuleName1, | |
568 kPDBName1, | |
569 &pdb_uuid_1, | |
570 0, | |
571 kPDBAge1, | |
572 NULL, | |
573 0, | |
574 false); | |
575 if (Test::HasFatalFailure()) { | |
576 return; | |
577 } | |
578 } | |
579 | |
580 { | |
581 SCOPED_TRACE("module 1"); | |
582 | |
583 expected.BaseOfImage = kModuleBase2; | |
584 expected.SizeOfImage = kModuleSize2; | |
585 | |
586 ExpectModule(&expected, | |
587 &module_list->Modules[1], | |
588 file_writer.string(), | |
589 kModuleName2, | |
590 NULL, | |
591 NULL, | |
592 0, | |
593 0, | |
594 NULL, | |
595 0, | |
596 false); | |
597 if (Test::HasFatalFailure()) { | |
598 return; | |
599 } | |
600 } | |
601 | |
602 { | |
603 SCOPED_TRACE("module 2"); | |
604 | |
605 expected.BaseOfImage = kModuleBase3; | |
606 expected.SizeOfImage = kModuleSize3; | |
607 | |
608 ExpectModule(&expected, | |
609 &module_list->Modules[2], | |
610 file_writer.string(), | |
611 kModuleName3, | |
612 kPDBName3, | |
613 &pdb_uuid_3, | |
614 0, | |
615 kPDBAge3, | |
616 NULL, | |
617 0, | |
618 false); | |
619 if (Test::HasFatalFailure()) { | |
620 return; | |
621 } | |
622 } | |
623 } | |
624 | |
Robert Sesek
2014/08/12 22:56:05
I assume you can mix and match modules with differ
Mark Mentovai
2014/08/12 23:23:26
rsesek wrote:
| |
625 TEST(MinidumpSystemInfoWriterDeathTest, NoModuleName) { | |
626 MinidumpFileWriter minidump_file_writer; | |
627 MinidumpModuleListWriter module_list_writer; | |
628 MinidumpModuleWriter module_writer; | |
629 module_list_writer.AddModule(&module_writer); | |
630 minidump_file_writer.AddStream(&module_list_writer); | |
631 | |
632 StringFileWriter file_writer; | |
633 ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "name_"); | |
634 } | |
635 | |
636 } // namespace | |
OLD | NEW |