1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Unit test for Minidump. Uses a pre-generated minidump and
30 // verifies that certain streams are correct.
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h> // Must come first
34 #endif
35
36 #include <iostream>
37 #include <fstream>
38 #include <sstream>
39 #include <stdlib.h>
40 #include <string>
41 #include <vector>
42
43 #include "breakpad_googletest_includes.h"
44 #include "common/using_std_string.h"
45 #include "google_breakpad/common/minidump_format.h"
46 #include "google_breakpad/processor/minidump.h"
47 #include "processor/logging.h"
48 #include "processor/synth_minidump.h"
49
50 namespace {
51
52 using google_breakpad::Minidump;
53 using google_breakpad::MinidumpContext;
54 using google_breakpad::MinidumpCrashpadInfo;
55 using google_breakpad::MinidumpException;
56 using google_breakpad::MinidumpMemoryInfo;
57 using google_breakpad::MinidumpMemoryInfoList;
58 using google_breakpad::MinidumpMemoryList;
59 using google_breakpad::MinidumpMemoryRegion;
60 using google_breakpad::MinidumpModule;
61 using google_breakpad::MinidumpModuleList;
62 using google_breakpad::MinidumpSystemInfo;
63 using google_breakpad::MinidumpUnloadedModule;
64 using google_breakpad::MinidumpUnloadedModuleList;
65 using google_breakpad::MinidumpThread;
66 using google_breakpad::MinidumpThreadList;
67 using google_breakpad::SynthMinidump::Context;
68 using google_breakpad::SynthMinidump::Dump;
69 using google_breakpad::SynthMinidump::Exception;
70 using google_breakpad::SynthMinidump::Memory;
71 using google_breakpad::SynthMinidump::Module;
72 using google_breakpad::SynthMinidump::UnloadedModule;
73 using google_breakpad::SynthMinidump::Section;
74 using google_breakpad::SynthMinidump::Stream;
75 using google_breakpad::SynthMinidump::String;
76 using google_breakpad::SynthMinidump::SystemInfo;
77 using google_breakpad::SynthMinidump::Thread;
78 using google_breakpad::test_assembler::kBigEndian;
79 using google_breakpad::test_assembler::kLittleEndian;
80 using std::ifstream;
81 using std::istringstream;
82 using std::vector;
83 using ::testing::Return;
84
85 class MinidumpTest : public ::testing::Test {
86 public:
SetUp()87 void SetUp() {
88 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
89 "/src/processor/testdata/minidump2.dmp";
90 }
91 string minidump_file_;
92 };
93
TEST_F(MinidumpTest,TestMinidumpFromFile)94 TEST_F(MinidumpTest, TestMinidumpFromFile) {
95 Minidump minidump(minidump_file_);
96 ASSERT_EQ(minidump.path(), minidump_file_);
97 ASSERT_TRUE(minidump.Read());
98 const MDRawHeader* header = minidump.header();
99 ASSERT_NE(header, (MDRawHeader*)NULL);
100 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
101
102 MinidumpModuleList* md_module_list = minidump.GetModuleList();
103 ASSERT_TRUE(md_module_list != NULL);
104 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0);
105 ASSERT_TRUE(md_module != NULL);
106 ASSERT_EQ("c:\\test_app.exe", md_module->code_file());
107 ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file());
108 ASSERT_EQ("45D35F6C2d000", md_module->code_identifier());
109 ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier());
110 }
111
TEST_F(MinidumpTest,TestMinidumpFromStream)112 TEST_F(MinidumpTest, TestMinidumpFromStream) {
113 // read minidump contents into memory, construct a stringstream around them
114 ifstream file_stream(minidump_file_.c_str(), std::ios::in);
115 ASSERT_TRUE(file_stream.good());
116 vector<char> bytes;
117 file_stream.seekg(0, std::ios_base::end);
118 ASSERT_TRUE(file_stream.good());
119 bytes.resize(file_stream.tellg());
120 file_stream.seekg(0, std::ios_base::beg);
121 ASSERT_TRUE(file_stream.good());
122 file_stream.read(&bytes[0], bytes.size());
123 ASSERT_TRUE(file_stream.good());
124 string str(&bytes[0], bytes.size());
125 istringstream stream(str);
126 ASSERT_TRUE(stream.good());
127
128 // now read minidump from stringstream
129 Minidump minidump(stream);
130 ASSERT_EQ(minidump.path(), "");
131 ASSERT_TRUE(minidump.Read());
132 const MDRawHeader* header = minidump.header();
133 ASSERT_NE(header, (MDRawHeader*)NULL);
134 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
135 //TODO: add more checks here
136 }
137
TEST_F(MinidumpTest,TestMinidumpWithCrashpadAnnotations)138 TEST_F(MinidumpTest, TestMinidumpWithCrashpadAnnotations) {
139 string crashpad_minidump_file =
140 string(getenv("srcdir") ? getenv("srcdir") : ".") +
141 "/src/processor/testdata/minidump_crashpad_annotation.dmp";
142
143 Minidump minidump(crashpad_minidump_file);
144 ASSERT_EQ(minidump.path(), crashpad_minidump_file);
145 ASSERT_TRUE(minidump.Read());
146
147 MinidumpCrashpadInfo* crashpad_info = minidump.GetCrashpadInfo();
148 ASSERT_TRUE(crashpad_info != NULL);
149
150 const std::vector<std::vector<MinidumpCrashpadInfo::AnnotationObject>>*
151 annotation_objects_list =
152 crashpad_info->GetModuleCrashpadInfoAnnotationObjects();
153 ASSERT_EQ(2U, annotation_objects_list->size());
154
155 std::vector<MinidumpCrashpadInfo::AnnotationObject> annotation_objects =
156 annotation_objects_list->at(0);
157 ASSERT_EQ(5U, annotation_objects.size());
158
159 std::vector<std::string> annotation_names;
160 for (size_t i = 0; i < annotation_objects.size(); i++) {
161 MinidumpCrashpadInfo::AnnotationObject annotation_object =
162 annotation_objects.at(i);
163 annotation_names.push_back(annotation_object.name);
164 ASSERT_TRUE(annotation_object.type > 0);
165 ASSERT_TRUE(annotation_object.value.size() > 0);
166 }
167
168 std::vector<std::string> expected_strings{
169 "exceptionReason", "exceptionName", "firstexception_bt", "firstexception",
170 "CounterAnnotation"};
171 ASSERT_EQ(annotation_names, expected_strings);
172 }
173
TEST(Dump,ReadBackEmpty)174 TEST(Dump, ReadBackEmpty) {
175 Dump dump(0);
176 dump.Finish();
177 string contents;
178 ASSERT_TRUE(dump.GetContents(&contents));
179 istringstream stream(contents);
180 Minidump minidump(stream);
181 ASSERT_TRUE(minidump.Read());
182 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
183 }
184
TEST(Dump,ReadBackEmptyBigEndian)185 TEST(Dump, ReadBackEmptyBigEndian) {
186 Dump big_minidump(0, kBigEndian);
187 big_minidump.Finish();
188 string contents;
189 ASSERT_TRUE(big_minidump.GetContents(&contents));
190 istringstream stream(contents);
191 Minidump minidump(stream);
192 ASSERT_TRUE(minidump.Read());
193 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
194 }
195
TEST(Dump,OneStream)196 TEST(Dump, OneStream) {
197 Dump dump(0, kBigEndian);
198 Stream stream(dump, 0xfbb7fa2bU);
199 stream.Append("stream contents");
200 dump.Add(&stream);
201 dump.Finish();
202
203 string contents;
204 ASSERT_TRUE(dump.GetContents(&contents));
205 istringstream minidump_stream(contents);
206 Minidump minidump(minidump_stream);
207 ASSERT_TRUE(minidump.Read());
208 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
209
210 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0);
211 ASSERT_TRUE(dir != NULL);
212 EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
213
214 uint32_t stream_length;
215 ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
216 ASSERT_EQ(15U, stream_length);
217 char stream_contents[15];
218 ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
219 EXPECT_EQ(string("stream contents"),
220 string(stream_contents, sizeof(stream_contents)));
221
222 EXPECT_FALSE(minidump.GetThreadList());
223 EXPECT_FALSE(minidump.GetModuleList());
224 EXPECT_FALSE(minidump.GetMemoryList());
225 EXPECT_FALSE(minidump.GetException());
226 EXPECT_FALSE(minidump.GetAssertion());
227 EXPECT_FALSE(minidump.GetSystemInfo());
228 EXPECT_FALSE(minidump.GetMiscInfo());
229 EXPECT_FALSE(minidump.GetBreakpadInfo());
230 }
231
TEST(Dump,OneMemory)232 TEST(Dump, OneMemory) {
233 Dump dump(0, kBigEndian);
234 Memory memory(dump, 0x309d68010bd21b2cULL);
235 memory.Append("memory contents");
236 dump.Add(&memory);
237 dump.Finish();
238
239 string contents;
240 ASSERT_TRUE(dump.GetContents(&contents));
241 istringstream minidump_stream(contents);
242 Minidump minidump(minidump_stream);
243 ASSERT_TRUE(minidump.Read());
244 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
245
246 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0);
247 ASSERT_TRUE(dir != NULL);
248 EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
249
250 MinidumpMemoryList* memory_list = minidump.GetMemoryList();
251 ASSERT_TRUE(memory_list != NULL);
252 ASSERT_EQ(1U, memory_list->region_count());
253
254 MinidumpMemoryRegion* region1 = memory_list->GetMemoryRegionAtIndex(0);
255 ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
256 ASSERT_EQ(15U, region1->GetSize());
257 const uint8_t* region1_bytes = region1->GetMemory();
258 ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
259 }
260
261 // One thread --- and its requisite entourage.
TEST(Dump,OneThread)262 TEST(Dump, OneThread) {
263 Dump dump(0, kLittleEndian);
264 Memory stack(dump, 0x2326a0fa);
265 stack.Append("stack for thread");
266
267 MDRawContextX86 raw_context;
268 const uint32_t kExpectedEIP = 0x6913f540;
269 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
270 raw_context.edi = 0x3ecba80d;
271 raw_context.esi = 0x382583b9;
272 raw_context.ebx = 0x7fccc03f;
273 raw_context.edx = 0xf62f8ec2;
274 raw_context.ecx = 0x46a6a6a8;
275 raw_context.eax = 0x6a5025e2;
276 raw_context.ebp = 0xd9fabb4a;
277 raw_context.eip = kExpectedEIP;
278 raw_context.cs = 0xbffe6eda;
279 raw_context.eflags = 0xb2ce1e2d;
280 raw_context.esp = 0x659caaa4;
281 raw_context.ss = 0x2e951ef7;
282 Context context(dump, raw_context);
283
284 Thread thread(dump, 0xa898f11b, stack, context,
285 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
286
287 dump.Add(&stack);
288 dump.Add(&context);
289 dump.Add(&thread);
290 dump.Finish();
291
292 string contents;
293 ASSERT_TRUE(dump.GetContents(&contents));
294
295 istringstream minidump_stream(contents);
296 Minidump minidump(minidump_stream);
297 ASSERT_TRUE(minidump.Read());
298 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
299
300 MinidumpMemoryList* md_memory_list = minidump.GetMemoryList();
301 ASSERT_TRUE(md_memory_list != NULL);
302 ASSERT_EQ(1U, md_memory_list->region_count());
303
304 MinidumpMemoryRegion* md_region = md_memory_list->GetMemoryRegionAtIndex(0);
305 ASSERT_EQ(0x2326a0faU, md_region->GetBase());
306 ASSERT_EQ(16U, md_region->GetSize());
307 const uint8_t* region_bytes = md_region->GetMemory();
308 ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
309
310 MinidumpThreadList* thread_list = minidump.GetThreadList();
311 ASSERT_TRUE(thread_list != NULL);
312 ASSERT_EQ(1U, thread_list->thread_count());
313
314 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
315 ASSERT_TRUE(md_thread != NULL);
316 uint32_t thread_id;
317 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
318 ASSERT_EQ(0xa898f11bU, thread_id);
319 MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
320 ASSERT_TRUE(md_stack != NULL);
321 ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
322 ASSERT_EQ(16U, md_stack->GetSize());
323 const uint8_t* md_stack_bytes = md_stack->GetMemory();
324 ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
325
326 MinidumpContext* md_context = md_thread->GetContext();
327 ASSERT_TRUE(md_context != NULL);
328 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
329
330 uint64_t eip;
331 ASSERT_TRUE(md_context->GetInstructionPointer(&eip));
332 EXPECT_EQ(kExpectedEIP, eip);
333
334 const MDRawContextX86* md_raw_context = md_context->GetContextX86();
335 ASSERT_TRUE(md_raw_context != NULL);
336 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
337 (md_raw_context->context_flags
338 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
339 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
340 EXPECT_EQ(0x382583b9U, raw_context.esi);
341 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
342 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
343 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
344 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
345 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
346 EXPECT_EQ(kExpectedEIP, raw_context.eip);
347 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
348 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
349 EXPECT_EQ(0x659caaa4U, raw_context.esp);
350 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
351 }
352
TEST(Dump,ThreadMissingMemory)353 TEST(Dump, ThreadMissingMemory) {
354 Dump dump(0, kLittleEndian);
355 Memory stack(dump, 0x2326a0fa);
356 // Stack has no contents.
357
358 MDRawContextX86 raw_context;
359 memset(&raw_context, 0, sizeof(raw_context));
360 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
361 Context context(dump, raw_context);
362
363 Thread thread(dump, 0xa898f11b, stack, context,
364 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
365
366 dump.Add(&stack);
367 dump.Add(&context);
368 dump.Add(&thread);
369 dump.Finish();
370
371 string contents;
372 ASSERT_TRUE(dump.GetContents(&contents));
373
374 istringstream minidump_stream(contents);
375 Minidump minidump(minidump_stream);
376 ASSERT_TRUE(minidump.Read());
377 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
378
379 // This should succeed even though the thread has no stack memory.
380 MinidumpThreadList* thread_list = minidump.GetThreadList();
381 ASSERT_TRUE(thread_list != NULL);
382 ASSERT_EQ(1U, thread_list->thread_count());
383
384 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
385 ASSERT_TRUE(md_thread != NULL);
386
387 uint32_t thread_id;
388 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
389 ASSERT_EQ(0xa898f11bU, thread_id);
390
391 MinidumpContext* md_context = md_thread->GetContext();
392 ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context);
393
394 MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
395 ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
396 }
397
TEST(Dump,ThreadMissingContext)398 TEST(Dump, ThreadMissingContext) {
399 Dump dump(0, kLittleEndian);
400 Memory stack(dump, 0x2326a0fa);
401 stack.Append("stack for thread");
402
403 // Context is empty.
404 Context context(dump);
405
406 Thread thread(dump, 0xa898f11b, stack, context,
407 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
408
409 dump.Add(&stack);
410 dump.Add(&context);
411 dump.Add(&thread);
412 dump.Finish();
413
414 string contents;
415 ASSERT_TRUE(dump.GetContents(&contents));
416
417 istringstream minidump_stream(contents);
418 Minidump minidump(minidump_stream);
419 ASSERT_TRUE(minidump.Read());
420 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
421
422 // This should succeed even though the thread has no stack memory.
423 MinidumpThreadList* thread_list = minidump.GetThreadList();
424 ASSERT_TRUE(thread_list != NULL);
425 ASSERT_EQ(1U, thread_list->thread_count());
426
427 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
428 ASSERT_TRUE(md_thread != NULL);
429
430 uint32_t thread_id;
431 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
432 ASSERT_EQ(0xa898f11bU, thread_id);
433 MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
434 ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
435
436 MinidumpContext* md_context = md_thread->GetContext();
437 ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context);
438 }
439
TEST(Dump,OneUnloadedModule)440 TEST(Dump, OneUnloadedModule) {
441 Dump dump(0, kBigEndian);
442 String module_name(dump, "unloaded module");
443
444 String csd_version(dump, "Windows 9000");
445 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
446
447 UnloadedModule unloaded_module(
448 dump,
449 0xa90206ca83eb2852ULL,
450 0xada542bd,
451 module_name,
452 0x34571371,
453 0xb1054d2a);
454
455 dump.Add(&unloaded_module);
456 dump.Add(&module_name);
457 dump.Add(&system_info);
458 dump.Add(&csd_version);
459 dump.Finish();
460
461 string contents;
462 ASSERT_TRUE(dump.GetContents(&contents));
463 istringstream minidump_stream(contents);
464 Minidump minidump(minidump_stream);
465 ASSERT_TRUE(minidump.Read());
466 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
467
468 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1);
469 ASSERT_TRUE(dir != NULL);
470 EXPECT_EQ((uint32_t) MD_UNLOADED_MODULE_LIST_STREAM, dir->stream_type);
471
472 MinidumpUnloadedModuleList* md_unloaded_module_list =
473 minidump.GetUnloadedModuleList();
474 ASSERT_TRUE(md_unloaded_module_list != NULL);
475 ASSERT_EQ(1U, md_unloaded_module_list->module_count());
476
477 const MinidumpUnloadedModule* md_unloaded_module =
478 md_unloaded_module_list->GetModuleAtIndex(0);
479 ASSERT_TRUE(md_unloaded_module != NULL);
480 ASSERT_EQ(0xa90206ca83eb2852ULL, md_unloaded_module->base_address());
481 ASSERT_EQ(0xada542bd, md_unloaded_module->size());
482 ASSERT_EQ("unloaded module", md_unloaded_module->code_file());
483 ASSERT_EQ("", md_unloaded_module->debug_file());
484 // time_date_stamp and size_of_image concatenated
485 ASSERT_EQ("B1054D2Aada542bd", md_unloaded_module->code_identifier());
486 ASSERT_EQ("", md_unloaded_module->debug_identifier());
487
488 const MDRawUnloadedModule* md_raw_unloaded_module =
489 md_unloaded_module->module();
490 ASSERT_TRUE(md_raw_unloaded_module != NULL);
491 ASSERT_EQ(0xb1054d2aU, md_raw_unloaded_module->time_date_stamp);
492 ASSERT_EQ(0x34571371U, md_raw_unloaded_module->checksum);
493 }
494
495 static const MDVSFixedFileInfo fixed_file_info = {
496 0xb2fba33a, // signature
497 0x33d7a728, // struct_version
498 0x31afcb20, // file_version_hi
499 0xe51cdab1, // file_version_lo
500 0xd1ea6907, // product_version_hi
501 0x03032857, // product_version_lo
502 0x11bf71d7, // file_flags_mask
503 0x5fb8cdbf, // file_flags
504 0xe45d0d5d, // file_os
505 0x107d9562, // file_type
506 0x5a8844d4, // file_subtype
507 0xa8d30b20, // file_date_hi
508 0x651c3e4e // file_date_lo
509 };
510
TEST(Dump,OneModule)511 TEST(Dump, OneModule) {
512 Dump dump(0, kBigEndian);
513 String module_name(dump, "single module");
514 Section cv_info(dump);
515 cv_info
516 .D32(MD_CVINFOPDB70_SIGNATURE) // signature
517 // signature, a MDGUID
518 .D32(0xabcd1234)
519 .D16(0xf00d)
520 .D16(0xbeef)
521 .Append("\x01\x02\x03\x04\x05\x06\x07\x08")
522 .D32(1) // age
523 .AppendCString("c:\\foo\\file.pdb"); // pdb_file_name
524
525 String csd_version(dump, "Windows 9000");
526 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
527
528 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
529 module_name,
530 0xb1054d2a,
531 0x34571371,
532 fixed_file_info, // from synth_minidump_unittest_data.h
533 &cv_info, nullptr);
534
535 dump.Add(&module);
536 dump.Add(&module_name);
537 dump.Add(&cv_info);
538 dump.Add(&system_info);
539 dump.Add(&csd_version);
540 dump.Finish();
541
542 string contents;
543 ASSERT_TRUE(dump.GetContents(&contents));
544 istringstream minidump_stream(contents);
545 Minidump minidump(minidump_stream);
546 ASSERT_TRUE(minidump.Read());
547 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
548
549 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1);
550 ASSERT_TRUE(dir != NULL);
551 EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
552
553 MinidumpModuleList* md_module_list = minidump.GetModuleList();
554 ASSERT_TRUE(md_module_list != NULL);
555 ASSERT_EQ(1U, md_module_list->module_count());
556
557 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0);
558 ASSERT_TRUE(md_module != NULL);
559 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
560 ASSERT_EQ(0xada542bd, md_module->size());
561 ASSERT_EQ("single module", md_module->code_file());
562 ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file());
563 // time_date_stamp and size_of_image concatenated
564 ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier());
565 ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier());
566
567 const MDRawModule* md_raw_module = md_module->module();
568 ASSERT_TRUE(md_raw_module != NULL);
569 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
570 ASSERT_EQ(0x34571371U, md_raw_module->checksum);
571 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
572 sizeof(fixed_file_info)) == 0);
573 }
574
575 // Test that a module with a MDCVInfoELF CV record is handled properly.
TEST(Dump,OneModuleCVELF)576 TEST(Dump, OneModuleCVELF) {
577 Dump dump(0, kLittleEndian);
578 String module_name(dump, "elf module");
579 Section cv_info(dump);
580 cv_info
581 .D32(MD_CVINFOELF_SIGNATURE) // signature
582 // build_id
583 .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
584 "\x37\x38\xce\xa3\x4a\x87");
585
586 const MDRawSystemInfo linux_x86 = {
587 MD_CPU_ARCHITECTURE_X86, // processor_architecture
588 6, // processor_level
589 0xd08, // processor_revision
590 1, // number_of_processors
591 0, // product_type
592 0, // major_version
593 0, // minor_version
594 0, // build_number
595 MD_OS_LINUX, // platform_id
596 0xdeadbeef, // csd_version_rva
597 0x100, // suite_mask
598 0, // reserved2
599 { // cpu
600 { // x86_cpu_info
601 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
602 0x6d8, // version_information
603 0xafe9fbff, // feature_information
604 0xffffffff // amd_extended_cpu_features
605 }
606 }
607 };
608 String csd_version(dump, "Literally Linux");
609 SystemInfo system_info(dump, linux_x86, csd_version);
610
611 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
612 module_name,
613 0xb1054d2a,
614 0x34571371,
615 fixed_file_info, // from synth_minidump_unittest_data.h
616 &cv_info, nullptr);
617
618 dump.Add(&module);
619 dump.Add(&module_name);
620 dump.Add(&cv_info);
621 dump.Add(&system_info);
622 dump.Add(&csd_version);
623 dump.Finish();
624
625 string contents;
626 ASSERT_TRUE(dump.GetContents(&contents));
627 istringstream minidump_stream(contents);
628 Minidump minidump(minidump_stream);
629 ASSERT_TRUE(minidump.Read());
630
631 MinidumpModuleList* md_module_list = minidump.GetModuleList();
632 ASSERT_TRUE(md_module_list != NULL);
633 ASSERT_EQ(1U, md_module_list->module_count());
634
635 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0);
636 ASSERT_TRUE(md_module != NULL);
637 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
638 ASSERT_EQ(0xada542bd, md_module->size());
639 ASSERT_EQ("elf module", md_module->code_file());
640 // debug_file == code_file
641 ASSERT_EQ("elf module", md_module->debug_file());
642 // just the build_id, directly
643 ASSERT_EQ("5fa9cdb41053df1b86fab733b4df3738cea34a87",
644 md_module->code_identifier());
645 // build_id truncted to GUID length and treated as such, with zero
646 // age appended
647 ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
648
649 const MDRawModule* md_raw_module = md_module->module();
650 ASSERT_TRUE(md_raw_module != NULL);
651 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
652 ASSERT_EQ(0x34571371U, md_raw_module->checksum);
653 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
654 sizeof(fixed_file_info)) == 0);
655 }
656
657 // Test that a build_id that's shorter than a GUID is handled properly.
TEST(Dump,CVELFShort)658 TEST(Dump, CVELFShort) {
659 Dump dump(0, kLittleEndian);
660 String module_name(dump, "elf module");
661 Section cv_info(dump);
662 cv_info
663 .D32(MD_CVINFOELF_SIGNATURE) // signature
664 // build_id, shorter than a GUID
665 .Append("\x5f\xa9\xcd\xb4");
666
667 const MDRawSystemInfo linux_x86 = {
668 MD_CPU_ARCHITECTURE_X86, // processor_architecture
669 6, // processor_level
670 0xd08, // processor_revision
671 1, // number_of_processors
672 0, // product_type
673 0, // major_version
674 0, // minor_version
675 0, // build_number
676 MD_OS_LINUX, // platform_id
677 0xdeadbeef, // csd_version_rva
678 0x100, // suite_mask
679 0, // reserved2
680 { // cpu
681 { // x86_cpu_info
682 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
683 0x6d8, // version_information
684 0xafe9fbff, // feature_information
685 0xffffffff // amd_extended_cpu_features
686 }
687 }
688 };
689 String csd_version(dump, "Literally Linux");
690 SystemInfo system_info(dump, linux_x86, csd_version);
691
692 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
693 module_name,
694 0xb1054d2a,
695 0x34571371,
696 fixed_file_info, // from synth_minidump_unittest_data.h
697 &cv_info, nullptr);
698
699 dump.Add(&module);
700 dump.Add(&module_name);
701 dump.Add(&cv_info);
702 dump.Add(&system_info);
703 dump.Add(&csd_version);
704 dump.Finish();
705
706 string contents;
707 ASSERT_TRUE(dump.GetContents(&contents));
708 istringstream minidump_stream(contents);
709 Minidump minidump(minidump_stream);
710 ASSERT_TRUE(minidump.Read());
711 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
712
713 MinidumpModuleList* md_module_list = minidump.GetModuleList();
714 ASSERT_TRUE(md_module_list != NULL);
715 ASSERT_EQ(1U, md_module_list->module_count());
716
717 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0);
718 ASSERT_TRUE(md_module != NULL);
719 // just the build_id, directly
720 ASSERT_EQ("5fa9cdb4", md_module->code_identifier());
721 // build_id expanded to GUID length and treated as such, with zero
722 // age appended
723 ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier());
724 }
725
726 // Test that a build_id that's very long is handled properly.
TEST(Dump,CVELFLong)727 TEST(Dump, CVELFLong) {
728 Dump dump(0, kLittleEndian);
729 String module_name(dump, "elf module");
730 Section cv_info(dump);
731 cv_info
732 .D32(MD_CVINFOELF_SIGNATURE) // signature
733 // build_id, lots of bytes
734 .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
735 "\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08"
736 "\x09\x0a\x0b\x0c\x0d\x0e\x0f");
737
738
739 const MDRawSystemInfo linux_x86 = {
740 MD_CPU_ARCHITECTURE_X86, // processor_architecture
741 6, // processor_level
742 0xd08, // processor_revision
743 1, // number_of_processors
744 0, // product_type
745 0, // major_version
746 0, // minor_version
747 0, // build_number
748 MD_OS_LINUX, // platform_id
749 0xdeadbeef, // csd_version_rva
750 0x100, // suite_mask
751 0, // reserved2
752 { // cpu
753 { // x86_cpu_info
754 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
755 0x6d8, // version_information
756 0xafe9fbff, // feature_information
757 0xffffffff // amd_extended_cpu_features
758 }
759 }
760 };
761 String csd_version(dump, "Literally Linux");
762 SystemInfo system_info(dump, linux_x86, csd_version);
763
764 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
765 module_name,
766 0xb1054d2a,
767 0x34571371,
768 fixed_file_info, // from synth_minidump_unittest_data.h
769 &cv_info, nullptr);
770
771 dump.Add(&module);
772 dump.Add(&module_name);
773 dump.Add(&cv_info);
774 dump.Add(&system_info);
775 dump.Add(&csd_version);
776 dump.Finish();
777
778 string contents;
779 ASSERT_TRUE(dump.GetContents(&contents));
780 istringstream minidump_stream(contents);
781 Minidump minidump(minidump_stream);
782 ASSERT_TRUE(minidump.Read());
783 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
784
785 MinidumpModuleList* md_module_list = minidump.GetModuleList();
786 ASSERT_TRUE(md_module_list != NULL);
787 ASSERT_EQ(1U, md_module_list->module_count());
788
789 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0);
790 ASSERT_TRUE(md_module != NULL);
791 // just the build_id, directly
792 ASSERT_EQ(
793 "5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f",
794 md_module->code_identifier());
795 // build_id truncated to GUID length and treated as such, with zero
796 // age appended.
797 ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
798 }
799
TEST(Dump,OneSystemInfo)800 TEST(Dump, OneSystemInfo) {
801 Dump dump(0, kLittleEndian);
802 String csd_version(dump, "Petulant Pierogi");
803 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
804
805 dump.Add(&system_info);
806 dump.Add(&csd_version);
807 dump.Finish();
808
809 string contents;
810 ASSERT_TRUE(dump.GetContents(&contents));
811 istringstream minidump_stream(contents);
812 Minidump minidump(minidump_stream);
813 ASSERT_TRUE(minidump.Read());
814 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
815
816 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0);
817 ASSERT_TRUE(dir != NULL);
818 EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
819
820 MinidumpSystemInfo* md_system_info = minidump.GetSystemInfo();
821 ASSERT_TRUE(md_system_info != NULL);
822 ASSERT_EQ("windows", md_system_info->GetOS());
823 ASSERT_EQ("x86", md_system_info->GetCPU());
824 ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
825 ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
826 }
827
TEST(Dump,BigDump)828 TEST(Dump, BigDump) {
829 Dump dump(0, kLittleEndian);
830
831 // A SystemInfo stream.
832 String csd_version(dump, "Munificent Macaque");
833 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
834 dump.Add(&csd_version);
835 dump.Add(&system_info);
836
837 // Five threads!
838 Memory stack0(dump, 0x70b9ebfc);
839 stack0.Append("stack for thread zero");
840 MDRawContextX86 raw_context0;
841 raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
842 raw_context0.eip = 0xaf0709e4;
843 Context context0(dump, raw_context0);
844 Thread thread0(dump, 0xbbef4432, stack0, context0,
845 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
846 dump.Add(&stack0);
847 dump.Add(&context0);
848 dump.Add(&thread0);
849
850 Memory stack1(dump, 0xf988cc45);
851 stack1.Append("stack for thread one");
852 MDRawContextX86 raw_context1;
853 raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
854 raw_context1.eip = 0xe4f56f81;
855 Context context1(dump, raw_context1);
856 Thread thread1(dump, 0x657c3f58, stack1, context1,
857 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
858 dump.Add(&stack1);
859 dump.Add(&context1);
860 dump.Add(&thread1);
861
862 Memory stack2(dump, 0xc8a92e7c);
863 stack2.Append("stack for thread two");
864 MDRawContextX86 raw_context2;
865 raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
866 raw_context2.eip = 0xb336a438;
867 Context context2(dump, raw_context2);
868 Thread thread2(dump, 0xdf4b8a71, stack2, context2,
869 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
870 dump.Add(&stack2);
871 dump.Add(&context2);
872 dump.Add(&thread2);
873
874 Memory stack3(dump, 0x36d08e08);
875 stack3.Append("stack for thread three");
876 MDRawContextX86 raw_context3;
877 raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
878 raw_context3.eip = 0xdf99a60c;
879 Context context3(dump, raw_context3);
880 Thread thread3(dump, 0x86e6c341, stack3, context3,
881 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
882 dump.Add(&stack3);
883 dump.Add(&context3);
884 dump.Add(&thread3);
885
886 Memory stack4(dump, 0x1e0ab4fa);
887 stack4.Append("stack for thread four");
888 MDRawContextX86 raw_context4;
889 raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
890 raw_context4.eip = 0xaa646267;
891 Context context4(dump, raw_context4);
892 Thread thread4(dump, 0x261a28d4, stack4, context4,
893 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
894 dump.Add(&stack4);
895 dump.Add(&context4);
896 dump.Add(&thread4);
897
898 // Three modules!
899 String module1_name(dump, "module one");
900 Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
901 dump.Add(&module1_name);
902 dump.Add(&module1);
903
904 String module2_name(dump, "module two");
905 Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
906 dump.Add(&module2_name);
907 dump.Add(&module2);
908
909 String module3_name(dump, "module three");
910 Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
911 dump.Add(&module3_name);
912 dump.Add(&module3);
913
914 // Unloaded modules!
915 uint64_t umodule1_base = 0xeb77da57b5d4cbdaULL;
916 uint32_t umodule1_size = 0x83cd5a37;
917 String umodule1_name(dump, "unloaded module one");
918 UnloadedModule unloaded_module1(dump, umodule1_base, umodule1_size,
919 umodule1_name);
920 dump.Add(&umodule1_name);
921 dump.Add(&unloaded_module1);
922
923 uint64_t umodule2_base = 0xeb77da57b5d4cbdaULL;
924 uint32_t umodule2_size = 0x83cd5a37;
925 String umodule2_name(dump, "unloaded module two");
926 UnloadedModule unloaded_module2(dump, umodule2_base, umodule2_size,
927 umodule2_name);
928 dump.Add(&umodule2_name);
929 dump.Add(&unloaded_module2);
930
931 uint64_t umodule3_base = 0xeb77da5839a20000ULL;
932 uint32_t umodule3_size = 0x83cd5a37;
933 String umodule3_name(dump, "unloaded module three");
934 UnloadedModule unloaded_module3(dump, umodule3_base, umodule3_size,
935 umodule3_name);
936 dump.Add(&umodule3_name);
937 dump.Add(&unloaded_module3);
938
939
940 // Add one more memory region, on top of the five stacks.
941 Memory memory5(dump, 0x61979e828040e564ULL);
942 memory5.Append("contents of memory 5");
943 dump.Add(&memory5);
944
945 dump.Finish();
946
947 string contents;
948 ASSERT_TRUE(dump.GetContents(&contents));
949 istringstream minidump_stream(contents);
950 Minidump minidump(minidump_stream);
951 ASSERT_TRUE(minidump.Read());
952 ASSERT_EQ(5U, minidump.GetDirectoryEntryCount());
953
954 // Check the threads.
955 MinidumpThreadList* thread_list = minidump.GetThreadList();
956 ASSERT_TRUE(thread_list != NULL);
957 ASSERT_EQ(5U, thread_list->thread_count());
958 uint32_t thread_id;
959 ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
960 ASSERT_EQ(0xbbef4432U, thread_id);
961 ASSERT_EQ(0x70b9ebfcU,
962 thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
963 ASSERT_EQ(0xaf0709e4U,
964 thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
965 ->eip);
966
967 ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
968 ASSERT_EQ(0x657c3f58U, thread_id);
969 ASSERT_EQ(0xf988cc45U,
970 thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
971 ASSERT_EQ(0xe4f56f81U,
972 thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
973 ->eip);
974
975 ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
976 ASSERT_EQ(0xdf4b8a71U, thread_id);
977 ASSERT_EQ(0xc8a92e7cU,
978 thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
979 ASSERT_EQ(0xb336a438U,
980 thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
981 ->eip);
982
983 ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
984 ASSERT_EQ(0x86e6c341U, thread_id);
985 ASSERT_EQ(0x36d08e08U,
986 thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
987 ASSERT_EQ(0xdf99a60cU,
988 thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
989 ->eip);
990
991 ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
992 ASSERT_EQ(0x261a28d4U, thread_id);
993 ASSERT_EQ(0x1e0ab4faU,
994 thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
995 ASSERT_EQ(0xaa646267U,
996 thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
997 ->eip);
998
999 // Check the modules.
1000 MinidumpModuleList* md_module_list = minidump.GetModuleList();
1001 ASSERT_TRUE(md_module_list != NULL);
1002 ASSERT_EQ(3U, md_module_list->module_count());
1003 EXPECT_EQ(0xeb77da57b5d4cbdaULL,
1004 md_module_list->GetModuleAtIndex(0)->base_address());
1005 EXPECT_EQ(0x8675884adfe5ac90ULL,
1006 md_module_list->GetModuleAtIndex(1)->base_address());
1007 EXPECT_EQ(0x95fc1544da321b6cULL,
1008 md_module_list->GetModuleAtIndex(2)->base_address());
1009
1010 // Check unloaded modules
1011 MinidumpUnloadedModuleList* md_unloaded_module_list =
1012 minidump.GetUnloadedModuleList();
1013 ASSERT_TRUE(md_unloaded_module_list != NULL);
1014 ASSERT_EQ(3U, md_unloaded_module_list->module_count());
1015 EXPECT_EQ(umodule1_base,
1016 md_unloaded_module_list->GetModuleAtIndex(0)->base_address());
1017 EXPECT_EQ(umodule2_base,
1018 md_unloaded_module_list->GetModuleAtIndex(1)->base_address());
1019 EXPECT_EQ(umodule3_base,
1020 md_unloaded_module_list->GetModuleAtIndex(2)->base_address());
1021
1022 const MinidumpUnloadedModule* umodule =
1023 md_unloaded_module_list->GetModuleForAddress(
1024 umodule1_base + umodule1_size / 2);
1025 EXPECT_EQ(umodule1_base, umodule->base_address());
1026
1027 umodule = md_unloaded_module_list->GetModuleAtSequence(0);
1028 EXPECT_EQ(umodule1_base, umodule->base_address());
1029
1030 EXPECT_EQ(NULL, md_unloaded_module_list->GetMainModule());
1031
1032 }
1033
TEST(Dump,OneMemoryInfo)1034 TEST(Dump, OneMemoryInfo) {
1035 Dump dump(0, kBigEndian);
1036 Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
1037
1038 // Add the MDRawMemoryInfoList header.
1039 const uint64_t kNumberOfEntries = 1;
1040 stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header
1041 .D32(sizeof(MDRawMemoryInfo)) // size_of_entry
1042 .D64(kNumberOfEntries); // number_of_entries
1043
1044
1045 // Now add a MDRawMemoryInfo entry.
1046 const uint64_t kBaseAddress = 0x1000;
1047 const uint64_t kRegionSize = 0x2000;
1048 stream.D64(kBaseAddress) // base_address
1049 .D64(kBaseAddress) // allocation_base
1050 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection
1051 .D32(0) // __alignment1
1052 .D64(kRegionSize) // region_size
1053 .D32(MD_MEMORY_STATE_COMMIT) // state
1054 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection
1055 .D32(MD_MEMORY_TYPE_PRIVATE) // type
1056 .D32(0); // __alignment2
1057
1058 dump.Add(&stream);
1059 dump.Finish();
1060
1061 string contents;
1062 ASSERT_TRUE(dump.GetContents(&contents));
1063 istringstream minidump_stream(contents);
1064 Minidump minidump(minidump_stream);
1065 ASSERT_TRUE(minidump.Read());
1066 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1067
1068 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0);
1069 ASSERT_TRUE(dir != NULL);
1070 EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
1071
1072 MinidumpMemoryInfoList* info_list = minidump.GetMemoryInfoList();
1073 ASSERT_TRUE(info_list != NULL);
1074 ASSERT_EQ(1U, info_list->info_count());
1075
1076 const MinidumpMemoryInfo* info1 = info_list->GetMemoryInfoAtIndex(0);
1077 ASSERT_EQ(kBaseAddress, info1->GetBase());
1078 ASSERT_EQ(kRegionSize, info1->GetSize());
1079 ASSERT_TRUE(info1->IsExecutable());
1080 ASSERT_TRUE(info1->IsWritable());
1081
1082 // Should get back the same memory region here.
1083 const MinidumpMemoryInfo* info2 =
1084 info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
1085 ASSERT_EQ(kBaseAddress, info2->GetBase());
1086 ASSERT_EQ(kRegionSize, info2->GetSize());
1087 }
1088
TEST(Dump,OneExceptionX86)1089 TEST(Dump, OneExceptionX86) {
1090 Dump dump(0, kLittleEndian);
1091
1092 MDRawContextX86 raw_context;
1093 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
1094 raw_context.edi = 0x3ecba80d;
1095 raw_context.esi = 0x382583b9;
1096 raw_context.ebx = 0x7fccc03f;
1097 raw_context.edx = 0xf62f8ec2;
1098 raw_context.ecx = 0x46a6a6a8;
1099 raw_context.eax = 0x6a5025e2;
1100 raw_context.ebp = 0xd9fabb4a;
1101 raw_context.eip = 0x6913f540;
1102 raw_context.cs = 0xbffe6eda;
1103 raw_context.eflags = 0xb2ce1e2d;
1104 raw_context.esp = 0x659caaa4;
1105 raw_context.ss = 0x2e951ef7;
1106 Context context(dump, raw_context);
1107
1108 Exception exception(dump, context,
1109 0x1234abcd, // thread id
1110 0xdcba4321, // exception code
1111 0xf0e0d0c0, // exception flags
1112 0x0919a9b9c9d9e9f9ULL); // exception address
1113
1114 dump.Add(&context);
1115 dump.Add(&exception);
1116 dump.Finish();
1117
1118 string contents;
1119 ASSERT_TRUE(dump.GetContents(&contents));
1120
1121 istringstream minidump_stream(contents);
1122 Minidump minidump(minidump_stream);
1123 ASSERT_TRUE(minidump.Read());
1124 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1125
1126 MinidumpException* md_exception = minidump.GetException();
1127 ASSERT_TRUE(md_exception != NULL);
1128
1129 uint32_t thread_id;
1130 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1131 ASSERT_EQ(0x1234abcdU, thread_id);
1132
1133 const MDRawExceptionStream* raw_exception = md_exception->exception();
1134 ASSERT_TRUE(raw_exception != NULL);
1135 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1136 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1137 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1138 raw_exception->exception_record.exception_address);
1139
1140 MinidumpContext* md_context = md_exception->GetContext();
1141 ASSERT_TRUE(md_context != NULL);
1142 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
1143 const MDRawContextX86* md_raw_context = md_context->GetContextX86();
1144 ASSERT_TRUE(md_raw_context != NULL);
1145 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
1146 (md_raw_context->context_flags
1147 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
1148 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
1149 EXPECT_EQ(0x382583b9U, raw_context.esi);
1150 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
1151 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
1152 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
1153 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
1154 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
1155 EXPECT_EQ(0x6913f540U, raw_context.eip);
1156 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
1157 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
1158 EXPECT_EQ(0x659caaa4U, raw_context.esp);
1159 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
1160 }
1161
TEST(Dump,OneExceptionX86XState)1162 TEST(Dump, OneExceptionX86XState) {
1163 Dump dump(0, kLittleEndian);
1164
1165 MDRawContextX86 raw_context;
1166 raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
1167 MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
1168 raw_context.edi = 0x3ecba80d;
1169 raw_context.esi = 0x382583b9;
1170 raw_context.ebx = 0x7fccc03f;
1171 raw_context.edx = 0xf62f8ec2;
1172 raw_context.ecx = 0x46a6a6a8;
1173 raw_context.eax = 0x6a5025e2;
1174 raw_context.ebp = 0xd9fabb4a;
1175 raw_context.eip = 0x6913f540;
1176 raw_context.cs = 0xbffe6eda;
1177 raw_context.eflags = 0xb2ce1e2d;
1178 raw_context.esp = 0x659caaa4;
1179 raw_context.ss = 0x2e951ef7;
1180 Context context(dump, raw_context);
1181
1182 Exception exception(dump, context,
1183 0x1234abcd, // thread id
1184 0xdcba4321, // exception code
1185 0xf0e0d0c0, // exception flags
1186 0x0919a9b9c9d9e9f9ULL); // exception address
1187
1188 dump.Add(&context);
1189 dump.Add(&exception);
1190 dump.Finish();
1191
1192 string contents;
1193 ASSERT_TRUE(dump.GetContents(&contents));
1194
1195 istringstream minidump_stream(contents);
1196 Minidump minidump(minidump_stream);
1197 ASSERT_TRUE(minidump.Read());
1198 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1199
1200 MinidumpException* md_exception = minidump.GetException();
1201 ASSERT_TRUE(md_exception != NULL);
1202
1203 uint32_t thread_id;
1204 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1205 ASSERT_EQ(0x1234abcdU, thread_id);
1206
1207 const MDRawExceptionStream* raw_exception = md_exception->exception();
1208 ASSERT_TRUE(raw_exception != NULL);
1209 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1210 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1211 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1212 raw_exception->exception_record.exception_address);
1213
1214 MinidumpContext* md_context = md_exception->GetContext();
1215 ASSERT_TRUE(md_context != NULL);
1216 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
1217 const MDRawContextX86* md_raw_context = md_context->GetContextX86();
1218 ASSERT_TRUE(md_raw_context != NULL);
1219 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
1220 (md_raw_context->context_flags
1221 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
1222 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
1223 EXPECT_EQ(0x382583b9U, raw_context.esi);
1224 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
1225 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
1226 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
1227 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
1228 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
1229 EXPECT_EQ(0x6913f540U, raw_context.eip);
1230 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
1231 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
1232 EXPECT_EQ(0x659caaa4U, raw_context.esp);
1233 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
1234 }
1235
1236 // Testing that the CPU type can be loaded from a system info stream when
1237 // the CPU flags are missing from the context_flags of an exception record
TEST(Dump,OneExceptionX86NoCPUFlags)1238 TEST(Dump, OneExceptionX86NoCPUFlags) {
1239 Dump dump(0, kLittleEndian);
1240
1241 MDRawContextX86 raw_context;
1242 // Intentionally not setting CPU type in the context_flags
1243 raw_context.context_flags = 0;
1244 raw_context.edi = 0x3ecba80d;
1245 raw_context.esi = 0x382583b9;
1246 raw_context.ebx = 0x7fccc03f;
1247 raw_context.edx = 0xf62f8ec2;
1248 raw_context.ecx = 0x46a6a6a8;
1249 raw_context.eax = 0x6a5025e2;
1250 raw_context.ebp = 0xd9fabb4a;
1251 raw_context.eip = 0x6913f540;
1252 raw_context.cs = 0xbffe6eda;
1253 raw_context.eflags = 0xb2ce1e2d;
1254 raw_context.esp = 0x659caaa4;
1255 raw_context.ss = 0x2e951ef7;
1256 Context context(dump, raw_context);
1257
1258 Exception exception(dump, context,
1259 0x1234abcd, // thread id
1260 0xdcba4321, // exception code
1261 0xf0e0d0c0, // exception flags
1262 0x0919a9b9c9d9e9f9ULL); // exception address
1263
1264 dump.Add(&context);
1265 dump.Add(&exception);
1266
1267 // Add system info. This is needed as an alternative source for CPU type
1268 // information. Note, that the CPU flags were intentionally skipped from
1269 // the context_flags and this alternative source is required.
1270 String csd_version(dump, "Service Pack 2");
1271 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
1272 dump.Add(&system_info);
1273 dump.Add(&csd_version);
1274
1275 dump.Finish();
1276
1277 string contents;
1278 ASSERT_TRUE(dump.GetContents(&contents));
1279
1280 istringstream minidump_stream(contents);
1281 Minidump minidump(minidump_stream);
1282 ASSERT_TRUE(minidump.Read());
1283 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
1284
1285 MinidumpException* md_exception = minidump.GetException();
1286 ASSERT_TRUE(md_exception != NULL);
1287
1288 uint32_t thread_id;
1289 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1290 ASSERT_EQ(0x1234abcdU, thread_id);
1291
1292 const MDRawExceptionStream* raw_exception = md_exception->exception();
1293 ASSERT_TRUE(raw_exception != NULL);
1294 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1295 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1296 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1297 raw_exception->exception_record.exception_address);
1298
1299 MinidumpContext* md_context = md_exception->GetContext();
1300 ASSERT_TRUE(md_context != NULL);
1301
1302 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
1303 const MDRawContextX86* md_raw_context = md_context->GetContextX86();
1304 ASSERT_TRUE(md_raw_context != NULL);
1305
1306 // Even though the CPU flags were missing from the context_flags, the
1307 // GetContext call above is expected to load the missing CPU flags from the
1308 // system info stream and set the CPU type bits in context_flags.
1309 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags);
1310
1311 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
1312 EXPECT_EQ(0x382583b9U, raw_context.esi);
1313 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
1314 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
1315 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
1316 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
1317 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
1318 EXPECT_EQ(0x6913f540U, raw_context.eip);
1319 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
1320 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
1321 EXPECT_EQ(0x659caaa4U, raw_context.esp);
1322 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
1323 }
1324
1325 // This test covers a scenario where a dump contains an exception but the
1326 // context record of the exception is missing the CPU type information in its
1327 // context_flags. The dump has no system info stream so it is imposible to
1328 // deduce the CPU type, hence the context record is unusable.
TEST(Dump,OneExceptionX86NoCPUFlagsNoSystemInfo)1329 TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) {
1330 Dump dump(0, kLittleEndian);
1331
1332 MDRawContextX86 raw_context;
1333 // Intentionally not setting CPU type in the context_flags
1334 raw_context.context_flags = 0;
1335 raw_context.edi = 0x3ecba80d;
1336 raw_context.esi = 0x382583b9;
1337 raw_context.ebx = 0x7fccc03f;
1338 raw_context.edx = 0xf62f8ec2;
1339 raw_context.ecx = 0x46a6a6a8;
1340 raw_context.eax = 0x6a5025e2;
1341 raw_context.ebp = 0xd9fabb4a;
1342 raw_context.eip = 0x6913f540;
1343 raw_context.cs = 0xbffe6eda;
1344 raw_context.eflags = 0xb2ce1e2d;
1345 raw_context.esp = 0x659caaa4;
1346 raw_context.ss = 0x2e951ef7;
1347 Context context(dump, raw_context);
1348
1349 Exception exception(dump, context,
1350 0x1234abcd, // thread id
1351 0xdcba4321, // exception code
1352 0xf0e0d0c0, // exception flags
1353 0x0919a9b9c9d9e9f9ULL); // exception address
1354
1355 dump.Add(&context);
1356 dump.Add(&exception);
1357 dump.Finish();
1358
1359 string contents;
1360 ASSERT_TRUE(dump.GetContents(&contents));
1361
1362 istringstream minidump_stream(contents);
1363 Minidump minidump(minidump_stream);
1364 ASSERT_TRUE(minidump.Read());
1365 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1366
1367 MinidumpException* md_exception = minidump.GetException();
1368 ASSERT_TRUE(md_exception != NULL);
1369
1370 uint32_t thread_id;
1371 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1372 ASSERT_EQ(0x1234abcdU, thread_id);
1373
1374 const MDRawExceptionStream* raw_exception = md_exception->exception();
1375 ASSERT_TRUE(raw_exception != NULL);
1376 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1377 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1378 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1379 raw_exception->exception_record.exception_address);
1380
1381 // The context record of the exception is unusable because the context_flags
1382 // don't have CPU type information and at the same time the minidump lacks
1383 // system info stream so it is impossible to deduce the CPU type.
1384 MinidumpContext* md_context = md_exception->GetContext();
1385 ASSERT_EQ(NULL, md_context);
1386 }
1387
TEST(Dump,OneExceptionARM)1388 TEST(Dump, OneExceptionARM) {
1389 Dump dump(0, kLittleEndian);
1390
1391 MDRawContextARM raw_context;
1392 raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
1393 raw_context.iregs[0] = 0x3ecba80d;
1394 raw_context.iregs[1] = 0x382583b9;
1395 raw_context.iregs[2] = 0x7fccc03f;
1396 raw_context.iregs[3] = 0xf62f8ec2;
1397 raw_context.iregs[4] = 0x46a6a6a8;
1398 raw_context.iregs[5] = 0x6a5025e2;
1399 raw_context.iregs[6] = 0xd9fabb4a;
1400 raw_context.iregs[7] = 0x6913f540;
1401 raw_context.iregs[8] = 0xbffe6eda;
1402 raw_context.iregs[9] = 0xb2ce1e2d;
1403 raw_context.iregs[10] = 0x659caaa4;
1404 raw_context.iregs[11] = 0xf0e0d0c0;
1405 raw_context.iregs[12] = 0xa9b8c7d6;
1406 raw_context.iregs[13] = 0x12345678;
1407 raw_context.iregs[14] = 0xabcd1234;
1408 raw_context.iregs[15] = 0x10203040;
1409 raw_context.cpsr = 0x2e951ef7;
1410 Context context(dump, raw_context);
1411
1412 Exception exception(dump, context,
1413 0x1234abcd, // thread id
1414 0xdcba4321, // exception code
1415 0xf0e0d0c0, // exception flags
1416 0x0919a9b9c9d9e9f9ULL); // exception address
1417
1418 dump.Add(&context);
1419 dump.Add(&exception);
1420 dump.Finish();
1421
1422 string contents;
1423 ASSERT_TRUE(dump.GetContents(&contents));
1424
1425 istringstream minidump_stream(contents);
1426 Minidump minidump(minidump_stream);
1427 ASSERT_TRUE(minidump.Read());
1428 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1429
1430 MinidumpException* md_exception = minidump.GetException();
1431 ASSERT_TRUE(md_exception != NULL);
1432
1433 uint32_t thread_id;
1434 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1435 ASSERT_EQ(0x1234abcdU, thread_id);
1436
1437 const MDRawExceptionStream* raw_exception = md_exception->exception();
1438 ASSERT_TRUE(raw_exception != NULL);
1439 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1440 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1441 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1442 raw_exception->exception_record.exception_address);
1443
1444 MinidumpContext* md_context = md_exception->GetContext();
1445 ASSERT_TRUE(md_context != NULL);
1446 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
1447 const MDRawContextARM* md_raw_context = md_context->GetContextARM();
1448 ASSERT_TRUE(md_raw_context != NULL);
1449 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
1450 (md_raw_context->context_flags
1451 & MD_CONTEXT_ARM_INTEGER));
1452 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1453 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1454 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1455 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1456 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1457 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1458 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1459 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1460 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1461 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1462 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1463 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1464 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1465 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1466 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1467 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1468 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
1469 }
1470
TEST(Dump,OneExceptionARMOldFlags)1471 TEST(Dump, OneExceptionARMOldFlags) {
1472 Dump dump(0, kLittleEndian);
1473
1474 MDRawContextARM raw_context;
1475 // MD_CONTEXT_ARM_INTEGER, but with _OLD
1476 raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
1477 raw_context.iregs[0] = 0x3ecba80d;
1478 raw_context.iregs[1] = 0x382583b9;
1479 raw_context.iregs[2] = 0x7fccc03f;
1480 raw_context.iregs[3] = 0xf62f8ec2;
1481 raw_context.iregs[4] = 0x46a6a6a8;
1482 raw_context.iregs[5] = 0x6a5025e2;
1483 raw_context.iregs[6] = 0xd9fabb4a;
1484 raw_context.iregs[7] = 0x6913f540;
1485 raw_context.iregs[8] = 0xbffe6eda;
1486 raw_context.iregs[9] = 0xb2ce1e2d;
1487 raw_context.iregs[10] = 0x659caaa4;
1488 raw_context.iregs[11] = 0xf0e0d0c0;
1489 raw_context.iregs[12] = 0xa9b8c7d6;
1490 raw_context.iregs[13] = 0x12345678;
1491 raw_context.iregs[14] = 0xabcd1234;
1492 raw_context.iregs[15] = 0x10203040;
1493 raw_context.cpsr = 0x2e951ef7;
1494 Context context(dump, raw_context);
1495
1496 Exception exception(dump, context,
1497 0x1234abcd, // thread id
1498 0xdcba4321, // exception code
1499 0xf0e0d0c0, // exception flags
1500 0x0919a9b9c9d9e9f9ULL); // exception address
1501
1502 dump.Add(&context);
1503 dump.Add(&exception);
1504 dump.Finish();
1505
1506 string contents;
1507 ASSERT_TRUE(dump.GetContents(&contents));
1508
1509 istringstream minidump_stream(contents);
1510 Minidump minidump(minidump_stream);
1511 ASSERT_TRUE(minidump.Read());
1512 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1513
1514 MinidumpException* md_exception = minidump.GetException();
1515 ASSERT_TRUE(md_exception != NULL);
1516
1517 uint32_t thread_id;
1518 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1519 ASSERT_EQ(0x1234abcdU, thread_id);
1520
1521 const MDRawExceptionStream* raw_exception = md_exception->exception();
1522 ASSERT_TRUE(raw_exception != NULL);
1523 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1524 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1525 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1526 raw_exception->exception_record.exception_address);
1527
1528 MinidumpContext* md_context = md_exception->GetContext();
1529 ASSERT_TRUE(md_context != NULL);
1530 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
1531 const MDRawContextARM* md_raw_context = md_context->GetContextARM();
1532 ASSERT_TRUE(md_raw_context != NULL);
1533 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
1534 (md_raw_context->context_flags
1535 & MD_CONTEXT_ARM_INTEGER));
1536 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1537 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1538 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1539 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1540 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1541 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1542 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1543 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1544 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1545 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1546 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1547 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1548 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1549 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1550 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1551 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1552 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
1553 }
1554
TEST(Dump,OneExceptionMIPS)1555 TEST(Dump, OneExceptionMIPS) {
1556 Dump dump(0, kLittleEndian);
1557
1558 MDRawContextMIPS raw_context;
1559 raw_context.context_flags = MD_CONTEXT_MIPS_INTEGER;
1560 raw_context.iregs[0] = 0x3ecba80d;
1561 raw_context.iregs[1] = 0x382583b9;
1562 raw_context.iregs[2] = 0x7fccc03f;
1563 raw_context.iregs[3] = 0xf62f8ec2;
1564 raw_context.iregs[4] = 0x46a6a6a8;
1565 raw_context.iregs[5] = 0x6a5025e2;
1566 raw_context.iregs[6] = 0xd9fabb4a;
1567 raw_context.iregs[7] = 0x6913f540;
1568 raw_context.iregs[8] = 0xbffe6eda;
1569 raw_context.iregs[9] = 0xb2ce1e2d;
1570 raw_context.iregs[10] = 0x659caaa4;
1571 raw_context.iregs[11] = 0xf0e0d0c0;
1572 raw_context.iregs[12] = 0xa9b8c7d6;
1573 raw_context.iregs[13] = 0x12345678;
1574 raw_context.iregs[14] = 0xabcd1234;
1575 raw_context.iregs[15] = 0x10203040;
1576 raw_context.iregs[16] = 0xa80d3ecb;
1577 raw_context.iregs[17] = 0x83b93825;
1578 raw_context.iregs[18] = 0xc03f7fcc;
1579 raw_context.iregs[19] = 0x8ec2f62f;
1580 raw_context.iregs[20] = 0xa6a846a6;
1581 raw_context.iregs[21] = 0x25e26a50;
1582 raw_context.iregs[22] = 0xbb4ad9fa;
1583 raw_context.iregs[23] = 0xf5406913;
1584 raw_context.iregs[24] = 0x6edabffe;
1585 raw_context.iregs[25] = 0x1e2db2ce;
1586 raw_context.iregs[26] = 0xaaa4659c;
1587 raw_context.iregs[27] = 0xd0c0f0e0;
1588 raw_context.iregs[28] = 0xc7d6a9b8;
1589 raw_context.iregs[29] = 0x56781234;
1590 raw_context.iregs[30] = 0x1234abcd;
1591 raw_context.iregs[31] = 0x30401020;
1592
1593 Context context(dump, raw_context);
1594
1595 Exception exception(dump, context,
1596 0x1234abcd, // Thread id.
1597 0xdcba4321, // Exception code.
1598 0xf0e0d0c0, // Exception flags.
1599 0x0919a9b9); // Exception address.
1600
1601 dump.Add(&context);
1602 dump.Add(&exception);
1603 dump.Finish();
1604
1605 string contents;
1606 ASSERT_TRUE(dump.GetContents(&contents));
1607
1608 istringstream minidump_stream(contents);
1609 Minidump minidump(minidump_stream);
1610 ASSERT_TRUE(minidump.Read());
1611 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1612
1613 MinidumpException* md_exception = minidump.GetException();
1614 ASSERT_TRUE(md_exception != NULL);
1615
1616 uint32_t thread_id;
1617 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1618 ASSERT_EQ(0x1234abcdU, thread_id);
1619
1620 const MDRawExceptionStream* raw_exception = md_exception->exception();
1621 ASSERT_TRUE(raw_exception != NULL);
1622 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1623 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1624 EXPECT_EQ(0x0919a9b9U,
1625 raw_exception->exception_record.exception_address);
1626
1627 MinidumpContext* md_context = md_exception->GetContext();
1628 ASSERT_TRUE(md_context != NULL);
1629 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU());
1630 const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS();
1631 ASSERT_TRUE(md_raw_context != NULL);
1632 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER,
1633 (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER));
1634 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1635 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1636 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1637 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1638 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1639 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1640 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1641 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1642 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1643 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1644 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1645 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1646 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1647 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1648 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1649 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1650 EXPECT_EQ(0xa80d3ecbU, raw_context.iregs[16]);
1651 EXPECT_EQ(0x83b93825U, raw_context.iregs[17]);
1652 EXPECT_EQ(0xc03f7fccU, raw_context.iregs[18]);
1653 EXPECT_EQ(0x8ec2f62fU, raw_context.iregs[19]);
1654 EXPECT_EQ(0xa6a846a6U, raw_context.iregs[20]);
1655 EXPECT_EQ(0x25e26a50U, raw_context.iregs[21]);
1656 EXPECT_EQ(0xbb4ad9faU, raw_context.iregs[22]);
1657 EXPECT_EQ(0xf5406913U, raw_context.iregs[23]);
1658 EXPECT_EQ(0x6edabffeU, raw_context.iregs[24]);
1659 EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]);
1660 EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]);
1661 EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]);
1662 EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]);
1663 EXPECT_EQ(0x56781234U, raw_context.iregs[29]);
1664 EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]);
1665 EXPECT_EQ(0x30401020U, raw_context.iregs[31]);
1666 }
1667
1668 } // namespace
1669