Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(948)

Side by Side Diff: minidump/minidump_module_writer_test.cc

Issue 460933004: Add MinidumpModuleWriter, MinidumpModuleListWriter, related classes, and their test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Don’t suffix uint64_t constants Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « minidump/minidump_module_writer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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);
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 // If |expected_pdb_name| is non-NULL, |codeview_record| is used to locate a
91 // CodeView record in |file_contents|, and its fields are compared against the
92 // the |expected_pdb_*| values. If |expected_pdb_uuid| is supplied, the CodeView
93 // record must be a PDB 7.0 link, otherwise, it must be a PDB 2.0 link. If
94 // |expected_pdb_name| is NULL, |codeview_record| must not point to anything.
95 void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
96 const std::string& file_contents,
97 const char* expected_pdb_name,
98 const UUID* expected_pdb_uuid,
99 time_t expected_pdb_timestamp,
100 uint32_t expected_pdb_age) {
101 if (expected_pdb_name) {
102 EXPECT_NE(0u, codeview_record->Rva);
103 ASSERT_LE(codeview_record->Rva + codeview_record->DataSize,
104 file_contents.size());
105
106 std::string observed_pdb_name;
107 if (expected_pdb_uuid) {
108 // The CodeView record should be a PDB 7.0 link.
109 EXPECT_GE(codeview_record->DataSize,
110 sizeof(MinidumpModuleCodeViewRecordPDB70));
111 const MinidumpModuleCodeViewRecordPDB70* codeview_pdb70_record =
112 reinterpret_cast<const MinidumpModuleCodeViewRecordPDB70*>(
113 &file_contents[codeview_record->Rva]);
114 EXPECT_EQ(MinidumpModuleCodeViewRecordPDB70::kSignature,
115 codeview_pdb70_record->signature);
116 EXPECT_EQ(0,
117 memcmp(expected_pdb_uuid,
118 &codeview_pdb70_record->uuid,
119 sizeof(codeview_pdb70_record->uuid)));
120 EXPECT_EQ(expected_pdb_age, codeview_pdb70_record->age);
121
122 observed_pdb_name.assign(
123 reinterpret_cast<const char*>(&codeview_pdb70_record->pdb_name[0]),
124 codeview_record->DataSize -
125 offsetof(MinidumpModuleCodeViewRecordPDB70, pdb_name));
126 } else {
127 // The CodeView record should be a PDB 2.0 link.
128 EXPECT_GE(codeview_record->DataSize,
129 sizeof(MinidumpModuleCodeViewRecordPDB20));
130 const MinidumpModuleCodeViewRecordPDB20* codeview_pdb20_record =
131 reinterpret_cast<const MinidumpModuleCodeViewRecordPDB20*>(
132 &file_contents[codeview_record->Rva]);
133 EXPECT_EQ(MinidumpModuleCodeViewRecordPDB20::kSignature,
134 codeview_pdb20_record->signature);
135 EXPECT_EQ(expected_pdb_timestamp, codeview_pdb20_record->timestamp);
136 EXPECT_EQ(expected_pdb_age, codeview_pdb20_record->age);
137
138 observed_pdb_name.assign(
139 reinterpret_cast<const char*>(&codeview_pdb20_record->pdb_name[0]),
140 codeview_record->DataSize -
141 offsetof(MinidumpModuleCodeViewRecordPDB20, pdb_name));
142 }
143
144 // Check for, and then remove, the NUL terminator.
145 EXPECT_EQ('\0', observed_pdb_name[observed_pdb_name.size() - 1]);
146 observed_pdb_name.resize(observed_pdb_name.size() - 1);
147
148 EXPECT_EQ(expected_pdb_name, observed_pdb_name);
149 } else {
150 // There should be no CodeView record.
151 EXPECT_EQ(0u, codeview_record->DataSize);
152 EXPECT_EQ(0u, codeview_record->Rva);
153 }
154 }
155
156 // If |expected_debug_name| is non-NULL, |misc_record| is used to locate a
157 // miscellanous debugging record in |file_contents|, and its fields are compared
158 // against the the |expected_debug_*| values. If |expected_debug_name| is NULL,
159 // |misc_record| must not point to anything.
160 void ExpectMiscellaneousDebugRecord(
161 const MINIDUMP_LOCATION_DESCRIPTOR* misc_record,
162 const std::string& file_contents,
163 const char* expected_debug_name,
164 uint32_t expected_debug_type,
165 bool expected_debug_utf16) {
166 if (expected_debug_name) {
167 EXPECT_GE(misc_record->DataSize, sizeof(IMAGE_DEBUG_MISC));
168 EXPECT_NE(0u, misc_record->Rva);
169 ASSERT_LE(misc_record->Rva + misc_record->DataSize, file_contents.size());
170 const IMAGE_DEBUG_MISC* misc_debug_record =
171 reinterpret_cast<const IMAGE_DEBUG_MISC*>(
172 &file_contents[misc_record->Rva]);
173 EXPECT_EQ(expected_debug_type, misc_debug_record->DataType);
174 EXPECT_EQ(misc_record->DataSize, misc_debug_record->Length);
175 EXPECT_EQ(expected_debug_utf16, misc_debug_record->Unicode);
176 EXPECT_EQ(0u, misc_debug_record->Reserved[0]);
177 EXPECT_EQ(0u, misc_debug_record->Reserved[1]);
178 EXPECT_EQ(0u, misc_debug_record->Reserved[2]);
179
180 // Check for the NUL terminator.
181 size_t bytes_available =
182 misc_debug_record->Length - offsetof(IMAGE_DEBUG_MISC, Data);
183 EXPECT_EQ('\0', misc_debug_record->Data[bytes_available - 1]);
184 std::string observed_data(
185 reinterpret_cast<const char*>(misc_debug_record->Data));
186
187 size_t bytes_used;
188 if (misc_debug_record->Unicode) {
189 string16 observed_data_utf16(
190 reinterpret_cast<const char16*>(misc_debug_record->Data));
191 bytes_used = (observed_data_utf16.size() + 1) * sizeof(char16);
192 observed_data = base::UTF16ToUTF8(observed_data_utf16);
193 } else {
194 observed_data = reinterpret_cast<const char*>(misc_debug_record->Data);
195 bytes_used = (observed_data.size() + 1) * sizeof(char);
196 }
197 EXPECT_LE(bytes_used, bytes_available);
198
199 // Make sure that any padding bytes after the first NUL are also NUL.
200 for (size_t index = bytes_used; index < bytes_available; ++index) {
201 EXPECT_EQ('\0', misc_debug_record->Data[index]);
202 }
203
204 EXPECT_EQ(expected_debug_name, observed_data);
205 } else {
206 // There should be no miscellaneous debugging record.
207 EXPECT_EQ(0u, misc_record->DataSize);
208 EXPECT_EQ(0u, misc_record->Rva);
209 }
210 }
211
212 // ExpectModule() verifies that |expected| matches |observed|. Fields that are
213 // supposed to contain constant magic numbers are verified against the expected
214 // constants instead of |expected|. Reserved fields are verified to be 0. RVA
215 // and MINIDUMP_LOCATION_DESCRIPTOR fields are not verified against |expected|.
216 // Instead, |ModuleNameRva| is used to locate the module name, which is compared
217 // against |expected_module_name|. ExpectCodeViewRecord() and
218 // ExpectMiscellaneousDebugRecord() are used to verify the |CvRecord| and
219 // |MiscRecord| fields against |expected_pdb_*| and |expected_debug_*|
220 // parameters, respectively.
221 void ExpectModule(const MINIDUMP_MODULE* expected,
222 const MINIDUMP_MODULE* observed,
223 const std::string& file_contents,
224 const std::string& expected_module_name,
225 const char* expected_pdb_name,
226 const UUID* expected_pdb_uuid,
227 time_t expected_pdb_timestamp,
228 uint32_t expected_pdb_age,
229 const char* expected_debug_name,
230 uint32_t expected_debug_type,
231 bool expected_debug_utf16) {
232 EXPECT_EQ(expected->BaseOfImage, observed->BaseOfImage);
233 EXPECT_EQ(expected->SizeOfImage, observed->SizeOfImage);
234 EXPECT_EQ(expected->CheckSum, observed->CheckSum);
235 EXPECT_EQ(expected->TimeDateStamp, observed->TimeDateStamp);
236 EXPECT_EQ(static_cast<uint32_t>(VS_FFI_SIGNATURE),
237 observed->VersionInfo.dwSignature);
238 EXPECT_EQ(static_cast<uint32_t>(VS_FFI_STRUCVERSION),
239 observed->VersionInfo.dwStrucVersion);
240 EXPECT_EQ(expected->VersionInfo.dwFileVersionMS,
241 observed->VersionInfo.dwFileVersionMS);
242 EXPECT_EQ(expected->VersionInfo.dwFileVersionLS,
243 observed->VersionInfo.dwFileVersionLS);
244 EXPECT_EQ(expected->VersionInfo.dwProductVersionMS,
245 observed->VersionInfo.dwProductVersionMS);
246 EXPECT_EQ(expected->VersionInfo.dwProductVersionLS,
247 observed->VersionInfo.dwProductVersionLS);
248 EXPECT_EQ(expected->VersionInfo.dwFileFlagsMask,
249 observed->VersionInfo.dwFileFlagsMask);
250 EXPECT_EQ(expected->VersionInfo.dwFileFlags,
251 observed->VersionInfo.dwFileFlags);
252 EXPECT_EQ(expected->VersionInfo.dwFileOS, observed->VersionInfo.dwFileOS);
253 EXPECT_EQ(expected->VersionInfo.dwFileType, observed->VersionInfo.dwFileType);
254 EXPECT_EQ(expected->VersionInfo.dwFileSubtype,
255 observed->VersionInfo.dwFileSubtype);
256 EXPECT_EQ(expected->VersionInfo.dwFileDateMS,
257 observed->VersionInfo.dwFileDateMS);
258 EXPECT_EQ(expected->VersionInfo.dwFileDateLS,
259 observed->VersionInfo.dwFileDateLS);
260 EXPECT_EQ(0u, observed->Reserved0);
261 EXPECT_EQ(0u, observed->Reserved1);
262
263 EXPECT_NE(0u, observed->ModuleNameRva);
264 ASSERT_LE(observed->ModuleNameRva,
265 file_contents.size() - sizeof(MINIDUMP_STRING));
266 const MINIDUMP_STRING* module_name = reinterpret_cast<const MINIDUMP_STRING*>(
267 &file_contents[observed->ModuleNameRva]);
268 ASSERT_LE(observed->ModuleNameRva + sizeof(MINIDUMP_STRING) +
269 (module_name->Length + 1),
270 file_contents.size());
271 ASSERT_EQ(0u, module_name->Length % 2);
272 string16 observed_module_name_utf16(
273 reinterpret_cast<const char16*>(
274 &file_contents[observed->ModuleNameRva + sizeof(MINIDUMP_STRING)]),
275 module_name->Length / 2);
276 string16 expected_module_name_utf16 = base::UTF8ToUTF16(expected_module_name);
277 EXPECT_EQ(expected_module_name_utf16, observed_module_name_utf16);
278
279 ExpectCodeViewRecord(&observed->CvRecord,
280 file_contents,
281 expected_pdb_name,
282 expected_pdb_uuid,
283 expected_pdb_timestamp,
284 expected_pdb_age);
285 if (testing::Test::HasFatalFailure()) {
286 return;
287 }
288
289 ExpectMiscellaneousDebugRecord(&observed->MiscRecord,
290 file_contents,
291 expected_debug_name,
292 expected_debug_type,
293 expected_debug_utf16);
294 if (testing::Test::HasFatalFailure()) {
295 return;
296 }
297 }
298
299 TEST(MinidumpModuleWriter, EmptyModule) {
300 MinidumpFileWriter minidump_file_writer;
301 MinidumpModuleListWriter module_list_writer;
302
303 const char kModuleName[] = "test_executable";
304
305 MinidumpModuleWriter module_writer;
306 module_writer.SetName(kModuleName);
307
308 module_list_writer.AddModule(&module_writer);
309 minidump_file_writer.AddStream(&module_list_writer);
310
311 StringFileWriter file_writer;
312 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
313
314 ASSERT_GT(file_writer.string().size(),
315 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
316 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE));
317
318 const MINIDUMP_MODULE_LIST* module_list;
319 GetModuleListStream(file_writer.string(), &module_list);
320 if (Test::HasFatalFailure()) {
321 return;
322 }
323
324 EXPECT_EQ(1u, module_list->NumberOfModules);
325
326 MINIDUMP_MODULE expected = {};
327 ExpectModule(&expected,
328 &module_list->Modules[0],
329 file_writer.string(),
330 kModuleName,
331 NULL,
332 NULL,
333 0,
334 0,
335 NULL,
336 0,
337 false);
338 if (Test::HasFatalFailure()) {
339 return;
340 }
341 }
342
343 TEST(MinidumpModuleWriter, OneModule) {
344 MinidumpFileWriter minidump_file_writer;
345 MinidumpModuleListWriter module_list_writer;
346
347 const char kModuleName[] = "statically_linked";
348 const uint64_t kModuleBase = 0x10da69000;
349 const uint32_t kModuleSize = 0x1000;
350 const uint32_t kChecksum = 0x76543210;
351 const time_t kTimestamp = 0x386d4380;
352 const uint32_t kFileVersionMS = 0x00010002;
353 const uint32_t kFileVersionLS = 0x00030004;
354 const uint32_t kProductVersionMS = 0x00050006;
355 const uint32_t kProductVersionLS = 0x00070008;
356 const uint32_t kFileFlagsMask = VS_FF_DEBUG | VS_FF_PRERELEASE |
357 VS_FF_PATCHED | VS_FF_PRIVATEBUILD |
358 VS_FF_INFOINFERRED | VS_FF_SPECIALBUILD;
359 const uint32_t kFileFlags = VS_FF_PRIVATEBUILD | VS_FF_SPECIALBUILD;
360 const uint32_t kFileOS = VOS_DOS;
361 const uint32_t kFileType = VFT_DRV;
362 const uint32_t kFileSubtype = VFT2_DRV_KEYBOARD;
363 const char kPDBName[] = "statical.pdb";
364 const uint8_t kPDBUUIDBytes[16] =
365 {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
366 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f};
367 UUID pdb_uuid;
368 pdb_uuid.InitializeFromBytes(kPDBUUIDBytes);
369 const uint32_t kPDBAge = 1;
370 const uint32_t kDebugType = IMAGE_DEBUG_MISC_EXENAME;
371 const char kDebugName[] = "statical.dbg";
372 const bool kDebugUTF16 = false;
373
374 MinidumpModuleWriter module_writer;
375 module_writer.SetName(kModuleName);
376 module_writer.SetImageBaseAddress(kModuleBase);
377 module_writer.SetImageSize(kModuleSize);
378 module_writer.SetChecksum(kChecksum);
379 module_writer.SetTimestamp(kTimestamp);
380 module_writer.SetFileVersion(kFileVersionMS >> 16,
381 kFileVersionMS & 0xffff,
382 kFileVersionLS >> 16,
383 kFileVersionLS & 0xffff);
384 module_writer.SetProductVersion(kProductVersionMS >> 16,
385 kProductVersionMS & 0xffff,
386 kProductVersionLS >> 16,
387 kProductVersionLS & 0xffff);
388 module_writer.SetFileFlagsAndMask(kFileFlags, kFileFlagsMask);
389 module_writer.SetFileOS(kFileOS);
390 module_writer.SetFileTypeAndSubtype(kFileType, kFileSubtype);
391
392 MinidumpModuleCodeViewRecordPDB70Writer codeview_pdb70_writer;
393 codeview_pdb70_writer.SetPDBName(kPDBName);
394 codeview_pdb70_writer.SetUUIDAndAge(pdb_uuid, kPDBAge);
395 module_writer.SetCodeViewRecord(&codeview_pdb70_writer);
396
397 MinidumpModuleMiscDebugRecordWriter misc_debug_writer;
398 misc_debug_writer.SetDataType(kDebugType);
399 misc_debug_writer.SetData(kDebugName, kDebugUTF16);
400 module_writer.SetMiscDebugRecord(&misc_debug_writer);
401
402 module_list_writer.AddModule(&module_writer);
403 minidump_file_writer.AddStream(&module_list_writer);
404
405 StringFileWriter file_writer;
406 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
407
408 ASSERT_GT(file_writer.string().size(),
409 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
410 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE));
411
412 const MINIDUMP_MODULE_LIST* module_list;
413 GetModuleListStream(file_writer.string(), &module_list);
414 if (Test::HasFatalFailure()) {
415 return;
416 }
417
418 EXPECT_EQ(1u, module_list->NumberOfModules);
419
420 MINIDUMP_MODULE expected = {};
421 expected.BaseOfImage = kModuleBase;
422 expected.SizeOfImage = kModuleSize;
423 expected.CheckSum = kChecksum;
424 expected.TimeDateStamp = kTimestamp;
425 expected.VersionInfo.dwFileVersionMS = kFileVersionMS;
426 expected.VersionInfo.dwFileVersionLS = kFileVersionLS;
427 expected.VersionInfo.dwProductVersionMS = kProductVersionMS;
428 expected.VersionInfo.dwProductVersionLS = kProductVersionLS;
429 expected.VersionInfo.dwFileFlagsMask = kFileFlagsMask;
430 expected.VersionInfo.dwFileFlags = kFileFlags;
431 expected.VersionInfo.dwFileOS = kFileOS;
432 expected.VersionInfo.dwFileType = kFileType;
433 expected.VersionInfo.dwFileSubtype = kFileSubtype;
434
435 ExpectModule(&expected,
436 &module_list->Modules[0],
437 file_writer.string(),
438 kModuleName,
439 kPDBName,
440 &pdb_uuid,
441 0,
442 kPDBAge,
443 kDebugName,
444 kDebugType,
445 kDebugUTF16);
446 if (Test::HasFatalFailure()) {
447 return;
448 }
449 }
450
451 TEST(MinidumpModuleWriter, OneModule_CodeViewUsesPDB20_MiscUsesUTF16) {
452 // MinidumpModuleWriter.OneModule tested with a PDB 7.0 link as the CodeView
453 // record and an IMAGE_DEBUG_MISC record in UTF-8. This test exercises the
454 // alternatives, a PDB 2.0 link as the CodeView record and an IMAGE_DEBUG_MISC
455 // record with UTF-16 data.
456 MinidumpFileWriter minidump_file_writer;
457 MinidumpModuleListWriter module_list_writer;
458
459 const char kModuleName[] = "dinosaur";
460 const char kPDBName[] = "d1n05.pdb";
461 const time_t kPDBTimestamp = 0x386d4380;
462 const uint32_t kPDBAge = 1;
463 const uint32_t kDebugType = IMAGE_DEBUG_MISC_EXENAME;
464 const char kDebugName[] = "d1n05.dbg";
465 const bool kDebugUTF16 = true;
466
467 MinidumpModuleWriter module_writer;
468 module_writer.SetName(kModuleName);
469
470 MinidumpModuleCodeViewRecordPDB20Writer codeview_pdb20_writer;
471 codeview_pdb20_writer.SetPDBName(kPDBName);
472 codeview_pdb20_writer.SetTimestampAndAge(kPDBTimestamp, kPDBAge);
473 module_writer.SetCodeViewRecord(&codeview_pdb20_writer);
474
475 MinidumpModuleMiscDebugRecordWriter misc_debug_writer;
476 misc_debug_writer.SetDataType(kDebugType);
477 misc_debug_writer.SetData(kDebugName, kDebugUTF16);
478 module_writer.SetMiscDebugRecord(&misc_debug_writer);
479
480 module_list_writer.AddModule(&module_writer);
481 minidump_file_writer.AddStream(&module_list_writer);
482
483 StringFileWriter file_writer;
484 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
485
486 ASSERT_GT(file_writer.string().size(),
487 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
488 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE));
489
490 const MINIDUMP_MODULE_LIST* module_list;
491 GetModuleListStream(file_writer.string(), &module_list);
492 if (Test::HasFatalFailure()) {
493 return;
494 }
495
496 EXPECT_EQ(1u, module_list->NumberOfModules);
497
498 MINIDUMP_MODULE expected = {};
499
500 ExpectModule(&expected,
501 &module_list->Modules[0],
502 file_writer.string(),
503 kModuleName,
504 kPDBName,
505 NULL,
506 kPDBTimestamp,
507 kPDBAge,
508 kDebugName,
509 kDebugType,
510 kDebugUTF16);
511 if (Test::HasFatalFailure()) {
512 return;
513 }
514 }
515
516 TEST(MinidumpModuleWriter, ThreeModules) {
517 // As good exercise, this test uses three modules, one with a PDB 7.0 link as
518 // its CodeView record, one with no CodeView record, and one with a PDB 2.0
519 // link as its CodeView record.
520 MinidumpFileWriter minidump_file_writer;
521 MinidumpModuleListWriter module_list_writer;
522
523 const char kModuleName1[] = "main";
524 const uint64_t kModuleBase1 = 0x100101000;
525 const uint32_t kModuleSize1 = 0xf000;
526 const char kPDBName1[] = "main";
527 const uint8_t kPDBUUIDBytes1[16] =
528 {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11,
529 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
530 UUID pdb_uuid_1;
531 pdb_uuid_1.InitializeFromBytes(kPDBUUIDBytes1);
532 const uint32_t kPDBAge1 = 0;
533
534 const char kModuleName2[] = "ld.so";
535 const uint64_t kModuleBase2 = 0x200202000;
536 const uint32_t kModuleSize2 = 0x1e000;
537
538 const char kModuleName3[] = "libc.so";
539 const uint64_t kModuleBase3 = 0x300303000;
540 const uint32_t kModuleSize3 = 0x2d000;
541 const char kPDBName3[] = "libc.so";
542 const time_t kPDBTimestamp3 = 0x386d4380;
543 const uint32_t kPDBAge3 = 2;
544
545 MinidumpModuleWriter module_writer_1;
546 module_writer_1.SetName(kModuleName1);
547 module_writer_1.SetImageBaseAddress(kModuleBase1);
548 module_writer_1.SetImageSize(kModuleSize1);
549
550 MinidumpModuleCodeViewRecordPDB70Writer codeview_pdb70_writer_1;
551 codeview_pdb70_writer_1.SetPDBName(kPDBName1);
552 codeview_pdb70_writer_1.SetUUIDAndAge(pdb_uuid_1, kPDBAge1);
553 module_writer_1.SetCodeViewRecord(&codeview_pdb70_writer_1);
554
555 module_list_writer.AddModule(&module_writer_1);
556
557 MinidumpModuleWriter module_writer_2;
558 module_writer_2.SetName(kModuleName2);
559 module_writer_2.SetImageBaseAddress(kModuleBase2);
560 module_writer_2.SetImageSize(kModuleSize2);
561
562 module_list_writer.AddModule(&module_writer_2);
563
564 MinidumpModuleWriter module_writer_3;
565 module_writer_3.SetName(kModuleName3);
566 module_writer_3.SetImageBaseAddress(kModuleBase3);
567 module_writer_3.SetImageSize(kModuleSize3);
568
569 MinidumpModuleCodeViewRecordPDB20Writer codeview_pdb70_writer_3;
570 codeview_pdb70_writer_3.SetPDBName(kPDBName3);
571 codeview_pdb70_writer_3.SetTimestampAndAge(kPDBTimestamp3, kPDBAge3);
572 module_writer_3.SetCodeViewRecord(&codeview_pdb70_writer_3);
573
574 module_list_writer.AddModule(&module_writer_3);
575
576 minidump_file_writer.AddStream(&module_list_writer);
577
578 StringFileWriter file_writer;
579 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
580
581 ASSERT_GT(file_writer.string().size(),
582 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
583 sizeof(MINIDUMP_MODULE_LIST) + 1 * sizeof(MINIDUMP_MODULE));
584
585 const MINIDUMP_MODULE_LIST* module_list;
586 GetModuleListStream(file_writer.string(), &module_list);
587 if (Test::HasFatalFailure()) {
588 return;
589 }
590
591 EXPECT_EQ(3u, module_list->NumberOfModules);
592
593 MINIDUMP_MODULE expected = {};
594
595 {
596 SCOPED_TRACE("module 0");
597
598 expected.BaseOfImage = kModuleBase1;
599 expected.SizeOfImage = kModuleSize1;
600
601 ExpectModule(&expected,
602 &module_list->Modules[0],
603 file_writer.string(),
604 kModuleName1,
605 kPDBName1,
606 &pdb_uuid_1,
607 0,
608 kPDBAge1,
609 NULL,
610 0,
611 false);
612 if (Test::HasFatalFailure()) {
613 return;
614 }
615 }
616
617 {
618 SCOPED_TRACE("module 1");
619
620 expected.BaseOfImage = kModuleBase2;
621 expected.SizeOfImage = kModuleSize2;
622
623 ExpectModule(&expected,
624 &module_list->Modules[1],
625 file_writer.string(),
626 kModuleName2,
627 NULL,
628 NULL,
629 0,
630 0,
631 NULL,
632 0,
633 false);
634 if (Test::HasFatalFailure()) {
635 return;
636 }
637 }
638
639 {
640 SCOPED_TRACE("module 2");
641
642 expected.BaseOfImage = kModuleBase3;
643 expected.SizeOfImage = kModuleSize3;
644
645 ExpectModule(&expected,
646 &module_list->Modules[2],
647 file_writer.string(),
648 kModuleName3,
649 kPDBName3,
650 NULL,
651 kPDBTimestamp3,
652 kPDBAge3,
653 NULL,
654 0,
655 false);
656 if (Test::HasFatalFailure()) {
657 return;
658 }
659 }
660 }
661
662 TEST(MinidumpSystemInfoWriterDeathTest, NoModuleName) {
663 MinidumpFileWriter minidump_file_writer;
664 MinidumpModuleListWriter module_list_writer;
665 MinidumpModuleWriter module_writer;
666 module_list_writer.AddModule(&module_writer);
667 minidump_file_writer.AddStream(&module_list_writer);
668
669 StringFileWriter file_writer;
670 ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "name_");
671 }
672
673 } // namespace
OLDNEW
« no previous file with comments | « minidump/minidump_module_writer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698