1 // Copyright (c) 2010, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Unit test for Minidump. Uses a pre-generated minidump and
31 // verifies that certain streams are correct.
32
33 #include <iostream>
34 #include <fstream>
35 #include <sstream>
36 #include <stdlib.h>
37 #include <string>
38 #include <vector>
39
40 #include "breakpad_googletest_includes.h"
41 #include "common/using_std_string.h"
42 #include "google_breakpad/common/minidump_format.h"
43 #include "google_breakpad/processor/minidump.h"
44 #include "processor/logging.h"
45 #include "processor/synth_minidump.h"
46
47 namespace {
48
49 using google_breakpad::Minidump;
50 using google_breakpad::MinidumpContext;
51 using google_breakpad::MinidumpException;
52 using google_breakpad::MinidumpMemoryInfo;
53 using google_breakpad::MinidumpMemoryInfoList;
54 using google_breakpad::MinidumpMemoryList;
55 using google_breakpad::MinidumpMemoryRegion;
56 using google_breakpad::MinidumpModule;
57 using google_breakpad::MinidumpModuleList;
58 using google_breakpad::MinidumpSystemInfo;
59 using google_breakpad::MinidumpThread;
60 using google_breakpad::MinidumpThreadList;
61 using google_breakpad::SynthMinidump::Context;
62 using google_breakpad::SynthMinidump::Dump;
63 using google_breakpad::SynthMinidump::Exception;
64 using google_breakpad::SynthMinidump::Memory;
65 using google_breakpad::SynthMinidump::Module;
66 using google_breakpad::SynthMinidump::Stream;
67 using google_breakpad::SynthMinidump::String;
68 using google_breakpad::SynthMinidump::SystemInfo;
69 using google_breakpad::SynthMinidump::Thread;
70 using google_breakpad::test_assembler::kBigEndian;
71 using google_breakpad::test_assembler::kLittleEndian;
72 using std::ifstream;
73 using std::istringstream;
74 using std::vector;
75 using ::testing::Return;
76
77 class MinidumpTest : public ::testing::Test {
78 public:
SetUp()79 void SetUp() {
80 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
81 "/src/processor/testdata/minidump2.dmp";
82 }
83 string minidump_file_;
84 };
85
TEST_F(MinidumpTest,TestMinidumpFromFile)86 TEST_F(MinidumpTest, TestMinidumpFromFile) {
87 Minidump minidump(minidump_file_);
88 ASSERT_EQ(minidump.path(), minidump_file_);
89 ASSERT_TRUE(minidump.Read());
90 const MDRawHeader* header = minidump.header();
91 ASSERT_NE(header, (MDRawHeader*)NULL);
92 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
93 //TODO: add more checks here
94 }
95
TEST_F(MinidumpTest,TestMinidumpFromStream)96 TEST_F(MinidumpTest, TestMinidumpFromStream) {
97 // read minidump contents into memory, construct a stringstream around them
98 ifstream file_stream(minidump_file_.c_str(), std::ios::in);
99 ASSERT_TRUE(file_stream.good());
100 vector<char> bytes;
101 file_stream.seekg(0, std::ios_base::end);
102 ASSERT_TRUE(file_stream.good());
103 bytes.resize(file_stream.tellg());
104 file_stream.seekg(0, std::ios_base::beg);
105 ASSERT_TRUE(file_stream.good());
106 file_stream.read(&bytes[0], bytes.size());
107 ASSERT_TRUE(file_stream.good());
108 string str(&bytes[0], bytes.size());
109 istringstream stream(str);
110 ASSERT_TRUE(stream.good());
111
112 // now read minidump from stringstream
113 Minidump minidump(stream);
114 ASSERT_EQ(minidump.path(), "");
115 ASSERT_TRUE(minidump.Read());
116 const MDRawHeader* header = minidump.header();
117 ASSERT_NE(header, (MDRawHeader*)NULL);
118 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
119 //TODO: add more checks here
120 }
121
TEST(Dump,ReadBackEmpty)122 TEST(Dump, ReadBackEmpty) {
123 Dump dump(0);
124 dump.Finish();
125 string contents;
126 ASSERT_TRUE(dump.GetContents(&contents));
127 istringstream stream(contents);
128 Minidump minidump(stream);
129 ASSERT_TRUE(minidump.Read());
130 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
131 }
132
TEST(Dump,ReadBackEmptyBigEndian)133 TEST(Dump, ReadBackEmptyBigEndian) {
134 Dump big_minidump(0, kBigEndian);
135 big_minidump.Finish();
136 string contents;
137 ASSERT_TRUE(big_minidump.GetContents(&contents));
138 istringstream stream(contents);
139 Minidump minidump(stream);
140 ASSERT_TRUE(minidump.Read());
141 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
142 }
143
TEST(Dump,OneStream)144 TEST(Dump, OneStream) {
145 Dump dump(0, kBigEndian);
146 Stream stream(dump, 0xfbb7fa2bU);
147 stream.Append("stream contents");
148 dump.Add(&stream);
149 dump.Finish();
150
151 string contents;
152 ASSERT_TRUE(dump.GetContents(&contents));
153 istringstream minidump_stream(contents);
154 Minidump minidump(minidump_stream);
155 ASSERT_TRUE(minidump.Read());
156 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
157
158 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
159 ASSERT_TRUE(dir != NULL);
160 EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
161
162 uint32_t stream_length;
163 ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
164 ASSERT_EQ(15U, stream_length);
165 char stream_contents[15];
166 ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
167 EXPECT_EQ(string("stream contents"),
168 string(stream_contents, sizeof(stream_contents)));
169
170 EXPECT_FALSE(minidump.GetThreadList());
171 EXPECT_FALSE(minidump.GetModuleList());
172 EXPECT_FALSE(minidump.GetMemoryList());
173 EXPECT_FALSE(minidump.GetException());
174 EXPECT_FALSE(minidump.GetAssertion());
175 EXPECT_FALSE(minidump.GetSystemInfo());
176 EXPECT_FALSE(minidump.GetMiscInfo());
177 EXPECT_FALSE(minidump.GetBreakpadInfo());
178 }
179
TEST(Dump,OneMemory)180 TEST(Dump, OneMemory) {
181 Dump dump(0, kBigEndian);
182 Memory memory(dump, 0x309d68010bd21b2cULL);
183 memory.Append("memory contents");
184 dump.Add(&memory);
185 dump.Finish();
186
187 string contents;
188 ASSERT_TRUE(dump.GetContents(&contents));
189 istringstream minidump_stream(contents);
190 Minidump minidump(minidump_stream);
191 ASSERT_TRUE(minidump.Read());
192 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
193
194 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
195 ASSERT_TRUE(dir != NULL);
196 EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
197
198 MinidumpMemoryList *memory_list = minidump.GetMemoryList();
199 ASSERT_TRUE(memory_list != NULL);
200 ASSERT_EQ(1U, memory_list->region_count());
201
202 MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
203 ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
204 ASSERT_EQ(15U, region1->GetSize());
205 const uint8_t *region1_bytes = region1->GetMemory();
206 ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
207 }
208
209 // One thread --- and its requisite entourage.
TEST(Dump,OneThread)210 TEST(Dump, OneThread) {
211 Dump dump(0, kLittleEndian);
212 Memory stack(dump, 0x2326a0fa);
213 stack.Append("stack for thread");
214
215 MDRawContextX86 raw_context;
216 const uint32_t kExpectedEIP = 0x6913f540;
217 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
218 raw_context.edi = 0x3ecba80d;
219 raw_context.esi = 0x382583b9;
220 raw_context.ebx = 0x7fccc03f;
221 raw_context.edx = 0xf62f8ec2;
222 raw_context.ecx = 0x46a6a6a8;
223 raw_context.eax = 0x6a5025e2;
224 raw_context.ebp = 0xd9fabb4a;
225 raw_context.eip = kExpectedEIP;
226 raw_context.cs = 0xbffe6eda;
227 raw_context.eflags = 0xb2ce1e2d;
228 raw_context.esp = 0x659caaa4;
229 raw_context.ss = 0x2e951ef7;
230 Context context(dump, raw_context);
231
232 Thread thread(dump, 0xa898f11b, stack, context,
233 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
234
235 dump.Add(&stack);
236 dump.Add(&context);
237 dump.Add(&thread);
238 dump.Finish();
239
240 string contents;
241 ASSERT_TRUE(dump.GetContents(&contents));
242
243 istringstream minidump_stream(contents);
244 Minidump minidump(minidump_stream);
245 ASSERT_TRUE(minidump.Read());
246 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
247
248 MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
249 ASSERT_TRUE(md_memory_list != NULL);
250 ASSERT_EQ(1U, md_memory_list->region_count());
251
252 MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
253 ASSERT_EQ(0x2326a0faU, md_region->GetBase());
254 ASSERT_EQ(16U, md_region->GetSize());
255 const uint8_t *region_bytes = md_region->GetMemory();
256 ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
257
258 MinidumpThreadList *thread_list = minidump.GetThreadList();
259 ASSERT_TRUE(thread_list != NULL);
260 ASSERT_EQ(1U, thread_list->thread_count());
261
262 MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
263 ASSERT_TRUE(md_thread != NULL);
264 uint32_t thread_id;
265 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
266 ASSERT_EQ(0xa898f11bU, thread_id);
267 MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
268 ASSERT_TRUE(md_stack != NULL);
269 ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
270 ASSERT_EQ(16U, md_stack->GetSize());
271 const uint8_t *md_stack_bytes = md_stack->GetMemory();
272 ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
273
274 MinidumpContext *md_context = md_thread->GetContext();
275 ASSERT_TRUE(md_context != NULL);
276 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
277
278 uint64_t eip;
279 ASSERT_TRUE(md_context->GetInstructionPointer(&eip));
280 EXPECT_EQ(kExpectedEIP, eip);
281
282 const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
283 ASSERT_TRUE(md_raw_context != NULL);
284 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
285 (md_raw_context->context_flags
286 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
287 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
288 EXPECT_EQ(0x382583b9U, raw_context.esi);
289 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
290 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
291 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
292 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
293 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
294 EXPECT_EQ(kExpectedEIP, raw_context.eip);
295 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
296 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
297 EXPECT_EQ(0x659caaa4U, raw_context.esp);
298 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
299 }
300
TEST(Dump,ThreadMissingMemory)301 TEST(Dump, ThreadMissingMemory) {
302 Dump dump(0, kLittleEndian);
303 Memory stack(dump, 0x2326a0fa);
304 // Stack has no contents.
305
306 MDRawContextX86 raw_context;
307 memset(&raw_context, 0, sizeof(raw_context));
308 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
309 Context context(dump, raw_context);
310
311 Thread thread(dump, 0xa898f11b, stack, context,
312 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
313
314 dump.Add(&stack);
315 dump.Add(&context);
316 dump.Add(&thread);
317 dump.Finish();
318
319 string contents;
320 ASSERT_TRUE(dump.GetContents(&contents));
321
322 istringstream minidump_stream(contents);
323 Minidump minidump(minidump_stream);
324 ASSERT_TRUE(minidump.Read());
325 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
326
327 // This should succeed even though the thread has no stack memory.
328 MinidumpThreadList* thread_list = minidump.GetThreadList();
329 ASSERT_TRUE(thread_list != NULL);
330 ASSERT_EQ(1U, thread_list->thread_count());
331
332 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
333 ASSERT_TRUE(md_thread != NULL);
334
335 uint32_t thread_id;
336 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
337 ASSERT_EQ(0xa898f11bU, thread_id);
338
339 MinidumpContext* md_context = md_thread->GetContext();
340 ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context);
341
342 MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
343 ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
344 }
345
TEST(Dump,ThreadMissingContext)346 TEST(Dump, ThreadMissingContext) {
347 Dump dump(0, kLittleEndian);
348 Memory stack(dump, 0x2326a0fa);
349 stack.Append("stack for thread");
350
351 // Context is empty.
352 Context context(dump);
353
354 Thread thread(dump, 0xa898f11b, stack, context,
355 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
356
357 dump.Add(&stack);
358 dump.Add(&context);
359 dump.Add(&thread);
360 dump.Finish();
361
362 string contents;
363 ASSERT_TRUE(dump.GetContents(&contents));
364
365 istringstream minidump_stream(contents);
366 Minidump minidump(minidump_stream);
367 ASSERT_TRUE(minidump.Read());
368 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
369
370 // This should succeed even though the thread has no stack memory.
371 MinidumpThreadList* thread_list = minidump.GetThreadList();
372 ASSERT_TRUE(thread_list != NULL);
373 ASSERT_EQ(1U, thread_list->thread_count());
374
375 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
376 ASSERT_TRUE(md_thread != NULL);
377
378 uint32_t thread_id;
379 ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
380 ASSERT_EQ(0xa898f11bU, thread_id);
381 MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
382 ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
383
384 MinidumpContext* md_context = md_thread->GetContext();
385 ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context);
386 }
387
TEST(Dump,OneModule)388 TEST(Dump, OneModule) {
389 static const MDVSFixedFileInfo fixed_file_info = {
390 0xb2fba33a, // signature
391 0x33d7a728, // struct_version
392 0x31afcb20, // file_version_hi
393 0xe51cdab1, // file_version_lo
394 0xd1ea6907, // product_version_hi
395 0x03032857, // product_version_lo
396 0x11bf71d7, // file_flags_mask
397 0x5fb8cdbf, // file_flags
398 0xe45d0d5d, // file_os
399 0x107d9562, // file_type
400 0x5a8844d4, // file_subtype
401 0xa8d30b20, // file_date_hi
402 0x651c3e4e // file_date_lo
403 };
404
405 Dump dump(0, kBigEndian);
406 String module_name(dump, "single module");
407 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
408 module_name,
409 0xb1054d2a,
410 0x34571371,
411 fixed_file_info, // from synth_minidump_unittest_data.h
412 NULL, NULL);
413
414 dump.Add(&module);
415 dump.Add(&module_name);
416 dump.Finish();
417
418 string contents;
419 ASSERT_TRUE(dump.GetContents(&contents));
420 istringstream minidump_stream(contents);
421 Minidump minidump(minidump_stream);
422 ASSERT_TRUE(minidump.Read());
423 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
424
425 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
426 ASSERT_TRUE(dir != NULL);
427 EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
428
429 MinidumpModuleList *md_module_list = minidump.GetModuleList();
430 ASSERT_TRUE(md_module_list != NULL);
431 ASSERT_EQ(1U, md_module_list->module_count());
432
433 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
434 ASSERT_TRUE(md_module != NULL);
435 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
436 ASSERT_EQ(0xada542bd, md_module->size());
437 ASSERT_EQ("single module", md_module->code_file());
438
439 const MDRawModule *md_raw_module = md_module->module();
440 ASSERT_TRUE(md_raw_module != NULL);
441 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
442 ASSERT_EQ(0x34571371U, md_raw_module->checksum);
443 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
444 sizeof(fixed_file_info)) == 0);
445 }
446
TEST(Dump,OneSystemInfo)447 TEST(Dump, OneSystemInfo) {
448 Dump dump(0, kLittleEndian);
449 String csd_version(dump, "Petulant Pierogi");
450 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
451
452 dump.Add(&system_info);
453 dump.Add(&csd_version);
454 dump.Finish();
455
456 string contents;
457 ASSERT_TRUE(dump.GetContents(&contents));
458 istringstream minidump_stream(contents);
459 Minidump minidump(minidump_stream);
460 ASSERT_TRUE(minidump.Read());
461 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
462
463 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
464 ASSERT_TRUE(dir != NULL);
465 EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
466
467 MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
468 ASSERT_TRUE(md_system_info != NULL);
469 ASSERT_EQ("windows", md_system_info->GetOS());
470 ASSERT_EQ("x86", md_system_info->GetCPU());
471 ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
472 ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
473 }
474
TEST(Dump,BigDump)475 TEST(Dump, BigDump) {
476 Dump dump(0, kLittleEndian);
477
478 // A SystemInfo stream.
479 String csd_version(dump, "Munificent Macaque");
480 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
481 dump.Add(&csd_version);
482 dump.Add(&system_info);
483
484 // Five threads!
485 Memory stack0(dump, 0x70b9ebfc);
486 stack0.Append("stack for thread zero");
487 MDRawContextX86 raw_context0;
488 raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
489 raw_context0.eip = 0xaf0709e4;
490 Context context0(dump, raw_context0);
491 Thread thread0(dump, 0xbbef4432, stack0, context0,
492 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
493 dump.Add(&stack0);
494 dump.Add(&context0);
495 dump.Add(&thread0);
496
497 Memory stack1(dump, 0xf988cc45);
498 stack1.Append("stack for thread one");
499 MDRawContextX86 raw_context1;
500 raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
501 raw_context1.eip = 0xe4f56f81;
502 Context context1(dump, raw_context1);
503 Thread thread1(dump, 0x657c3f58, stack1, context1,
504 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
505 dump.Add(&stack1);
506 dump.Add(&context1);
507 dump.Add(&thread1);
508
509 Memory stack2(dump, 0xc8a92e7c);
510 stack2.Append("stack for thread two");
511 MDRawContextX86 raw_context2;
512 raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
513 raw_context2.eip = 0xb336a438;
514 Context context2(dump, raw_context2);
515 Thread thread2(dump, 0xdf4b8a71, stack2, context2,
516 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
517 dump.Add(&stack2);
518 dump.Add(&context2);
519 dump.Add(&thread2);
520
521 Memory stack3(dump, 0x36d08e08);
522 stack3.Append("stack for thread three");
523 MDRawContextX86 raw_context3;
524 raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
525 raw_context3.eip = 0xdf99a60c;
526 Context context3(dump, raw_context3);
527 Thread thread3(dump, 0x86e6c341, stack3, context3,
528 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
529 dump.Add(&stack3);
530 dump.Add(&context3);
531 dump.Add(&thread3);
532
533 Memory stack4(dump, 0x1e0ab4fa);
534 stack4.Append("stack for thread four");
535 MDRawContextX86 raw_context4;
536 raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
537 raw_context4.eip = 0xaa646267;
538 Context context4(dump, raw_context4);
539 Thread thread4(dump, 0x261a28d4, stack4, context4,
540 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
541 dump.Add(&stack4);
542 dump.Add(&context4);
543 dump.Add(&thread4);
544
545 // Three modules!
546 String module1_name(dump, "module one");
547 Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
548 dump.Add(&module1_name);
549 dump.Add(&module1);
550
551 String module2_name(dump, "module two");
552 Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
553 dump.Add(&module2_name);
554 dump.Add(&module2);
555
556 String module3_name(dump, "module three");
557 Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
558 dump.Add(&module3_name);
559 dump.Add(&module3);
560
561 // Add one more memory region, on top of the five stacks.
562 Memory memory5(dump, 0x61979e828040e564ULL);
563 memory5.Append("contents of memory 5");
564 dump.Add(&memory5);
565
566 dump.Finish();
567
568 string contents;
569 ASSERT_TRUE(dump.GetContents(&contents));
570 istringstream minidump_stream(contents);
571 Minidump minidump(minidump_stream);
572 ASSERT_TRUE(minidump.Read());
573 ASSERT_EQ(4U, minidump.GetDirectoryEntryCount());
574
575 // Check the threads.
576 MinidumpThreadList *thread_list = minidump.GetThreadList();
577 ASSERT_TRUE(thread_list != NULL);
578 ASSERT_EQ(5U, thread_list->thread_count());
579 uint32_t thread_id;
580 ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
581 ASSERT_EQ(0xbbef4432U, thread_id);
582 ASSERT_EQ(0x70b9ebfcU,
583 thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
584 ASSERT_EQ(0xaf0709e4U,
585 thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
586 ->eip);
587
588 ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
589 ASSERT_EQ(0x657c3f58U, thread_id);
590 ASSERT_EQ(0xf988cc45U,
591 thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
592 ASSERT_EQ(0xe4f56f81U,
593 thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
594 ->eip);
595
596 ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
597 ASSERT_EQ(0xdf4b8a71U, thread_id);
598 ASSERT_EQ(0xc8a92e7cU,
599 thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
600 ASSERT_EQ(0xb336a438U,
601 thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
602 ->eip);
603
604 ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
605 ASSERT_EQ(0x86e6c341U, thread_id);
606 ASSERT_EQ(0x36d08e08U,
607 thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
608 ASSERT_EQ(0xdf99a60cU,
609 thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
610 ->eip);
611
612 ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
613 ASSERT_EQ(0x261a28d4U, thread_id);
614 ASSERT_EQ(0x1e0ab4faU,
615 thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
616 ASSERT_EQ(0xaa646267U,
617 thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
618 ->eip);
619
620 // Check the modules.
621 MinidumpModuleList *md_module_list = minidump.GetModuleList();
622 ASSERT_TRUE(md_module_list != NULL);
623 ASSERT_EQ(3U, md_module_list->module_count());
624 EXPECT_EQ(0xeb77da57b5d4cbdaULL,
625 md_module_list->GetModuleAtIndex(0)->base_address());
626 EXPECT_EQ(0x8675884adfe5ac90ULL,
627 md_module_list->GetModuleAtIndex(1)->base_address());
628 EXPECT_EQ(0x95fc1544da321b6cULL,
629 md_module_list->GetModuleAtIndex(2)->base_address());
630 }
631
TEST(Dump,OneMemoryInfo)632 TEST(Dump, OneMemoryInfo) {
633 Dump dump(0, kBigEndian);
634 Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
635
636 // Add the MDRawMemoryInfoList header.
637 const uint64_t kNumberOfEntries = 1;
638 stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header
639 .D32(sizeof(MDRawMemoryInfo)) // size_of_entry
640 .D64(kNumberOfEntries); // number_of_entries
641
642
643 // Now add a MDRawMemoryInfo entry.
644 const uint64_t kBaseAddress = 0x1000;
645 const uint64_t kRegionSize = 0x2000;
646 stream.D64(kBaseAddress) // base_address
647 .D64(kBaseAddress) // allocation_base
648 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection
649 .D32(0) // __alignment1
650 .D64(kRegionSize) // region_size
651 .D32(MD_MEMORY_STATE_COMMIT) // state
652 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection
653 .D32(MD_MEMORY_TYPE_PRIVATE) // type
654 .D32(0); // __alignment2
655
656 dump.Add(&stream);
657 dump.Finish();
658
659 string contents;
660 ASSERT_TRUE(dump.GetContents(&contents));
661 istringstream minidump_stream(contents);
662 Minidump minidump(minidump_stream);
663 ASSERT_TRUE(minidump.Read());
664 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
665
666 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
667 ASSERT_TRUE(dir != NULL);
668 EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
669
670 MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
671 ASSERT_TRUE(info_list != NULL);
672 ASSERT_EQ(1U, info_list->info_count());
673
674 const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
675 ASSERT_EQ(kBaseAddress, info1->GetBase());
676 ASSERT_EQ(kRegionSize, info1->GetSize());
677 ASSERT_TRUE(info1->IsExecutable());
678 ASSERT_TRUE(info1->IsWritable());
679
680 // Should get back the same memory region here.
681 const MinidumpMemoryInfo *info2 =
682 info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
683 ASSERT_EQ(kBaseAddress, info2->GetBase());
684 ASSERT_EQ(kRegionSize, info2->GetSize());
685 }
686
TEST(Dump,OneExceptionX86)687 TEST(Dump, OneExceptionX86) {
688 Dump dump(0, kLittleEndian);
689
690 MDRawContextX86 raw_context;
691 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
692 raw_context.edi = 0x3ecba80d;
693 raw_context.esi = 0x382583b9;
694 raw_context.ebx = 0x7fccc03f;
695 raw_context.edx = 0xf62f8ec2;
696 raw_context.ecx = 0x46a6a6a8;
697 raw_context.eax = 0x6a5025e2;
698 raw_context.ebp = 0xd9fabb4a;
699 raw_context.eip = 0x6913f540;
700 raw_context.cs = 0xbffe6eda;
701 raw_context.eflags = 0xb2ce1e2d;
702 raw_context.esp = 0x659caaa4;
703 raw_context.ss = 0x2e951ef7;
704 Context context(dump, raw_context);
705
706 Exception exception(dump, context,
707 0x1234abcd, // thread id
708 0xdcba4321, // exception code
709 0xf0e0d0c0, // exception flags
710 0x0919a9b9c9d9e9f9ULL); // exception address
711
712 dump.Add(&context);
713 dump.Add(&exception);
714 dump.Finish();
715
716 string contents;
717 ASSERT_TRUE(dump.GetContents(&contents));
718
719 istringstream minidump_stream(contents);
720 Minidump minidump(minidump_stream);
721 ASSERT_TRUE(minidump.Read());
722 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
723
724 MinidumpException *md_exception = minidump.GetException();
725 ASSERT_TRUE(md_exception != NULL);
726
727 uint32_t thread_id;
728 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
729 ASSERT_EQ(0x1234abcdU, thread_id);
730
731 const MDRawExceptionStream* raw_exception = md_exception->exception();
732 ASSERT_TRUE(raw_exception != NULL);
733 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
734 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
735 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
736 raw_exception->exception_record.exception_address);
737
738 MinidumpContext *md_context = md_exception->GetContext();
739 ASSERT_TRUE(md_context != NULL);
740 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
741 const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
742 ASSERT_TRUE(md_raw_context != NULL);
743 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
744 (md_raw_context->context_flags
745 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
746 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
747 EXPECT_EQ(0x382583b9U, raw_context.esi);
748 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
749 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
750 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
751 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
752 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
753 EXPECT_EQ(0x6913f540U, raw_context.eip);
754 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
755 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
756 EXPECT_EQ(0x659caaa4U, raw_context.esp);
757 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
758 }
759
TEST(Dump,OneExceptionX86XState)760 TEST(Dump, OneExceptionX86XState) {
761 Dump dump(0, kLittleEndian);
762
763 MDRawContextX86 raw_context;
764 raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
765 MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
766 raw_context.edi = 0x3ecba80d;
767 raw_context.esi = 0x382583b9;
768 raw_context.ebx = 0x7fccc03f;
769 raw_context.edx = 0xf62f8ec2;
770 raw_context.ecx = 0x46a6a6a8;
771 raw_context.eax = 0x6a5025e2;
772 raw_context.ebp = 0xd9fabb4a;
773 raw_context.eip = 0x6913f540;
774 raw_context.cs = 0xbffe6eda;
775 raw_context.eflags = 0xb2ce1e2d;
776 raw_context.esp = 0x659caaa4;
777 raw_context.ss = 0x2e951ef7;
778 Context context(dump, raw_context);
779
780 Exception exception(dump, context,
781 0x1234abcd, // thread id
782 0xdcba4321, // exception code
783 0xf0e0d0c0, // exception flags
784 0x0919a9b9c9d9e9f9ULL); // exception address
785
786 dump.Add(&context);
787 dump.Add(&exception);
788 dump.Finish();
789
790 string contents;
791 ASSERT_TRUE(dump.GetContents(&contents));
792
793 istringstream minidump_stream(contents);
794 Minidump minidump(minidump_stream);
795 ASSERT_TRUE(minidump.Read());
796 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
797
798 MinidumpException *md_exception = minidump.GetException();
799 ASSERT_TRUE(md_exception != NULL);
800
801 uint32_t thread_id;
802 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
803 ASSERT_EQ(0x1234abcdU, thread_id);
804
805 const MDRawExceptionStream* raw_exception = md_exception->exception();
806 ASSERT_TRUE(raw_exception != NULL);
807 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
808 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
809 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
810 raw_exception->exception_record.exception_address);
811
812 MinidumpContext *md_context = md_exception->GetContext();
813 ASSERT_TRUE(md_context != NULL);
814 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
815 const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
816 ASSERT_TRUE(md_raw_context != NULL);
817 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
818 (md_raw_context->context_flags
819 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
820 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
821 EXPECT_EQ(0x382583b9U, raw_context.esi);
822 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
823 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
824 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
825 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
826 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
827 EXPECT_EQ(0x6913f540U, raw_context.eip);
828 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
829 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
830 EXPECT_EQ(0x659caaa4U, raw_context.esp);
831 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
832 }
833
834 // Testing that the CPU type can be loaded from a system info stream when
835 // the CPU flags are missing from the context_flags of an exception record
TEST(Dump,OneExceptionX86NoCPUFlags)836 TEST(Dump, OneExceptionX86NoCPUFlags) {
837 Dump dump(0, kLittleEndian);
838
839 MDRawContextX86 raw_context;
840 // Intentionally not setting CPU type in the context_flags
841 raw_context.context_flags = 0;
842 raw_context.edi = 0x3ecba80d;
843 raw_context.esi = 0x382583b9;
844 raw_context.ebx = 0x7fccc03f;
845 raw_context.edx = 0xf62f8ec2;
846 raw_context.ecx = 0x46a6a6a8;
847 raw_context.eax = 0x6a5025e2;
848 raw_context.ebp = 0xd9fabb4a;
849 raw_context.eip = 0x6913f540;
850 raw_context.cs = 0xbffe6eda;
851 raw_context.eflags = 0xb2ce1e2d;
852 raw_context.esp = 0x659caaa4;
853 raw_context.ss = 0x2e951ef7;
854 Context context(dump, raw_context);
855
856 Exception exception(dump, context,
857 0x1234abcd, // thread id
858 0xdcba4321, // exception code
859 0xf0e0d0c0, // exception flags
860 0x0919a9b9c9d9e9f9ULL); // exception address
861
862 dump.Add(&context);
863 dump.Add(&exception);
864
865 // Add system info. This is needed as an alternative source for CPU type
866 // information. Note, that the CPU flags were intentionally skipped from
867 // the context_flags and this alternative source is required.
868 String csd_version(dump, "Service Pack 2");
869 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
870 dump.Add(&system_info);
871 dump.Add(&csd_version);
872
873 dump.Finish();
874
875 string contents;
876 ASSERT_TRUE(dump.GetContents(&contents));
877
878 istringstream minidump_stream(contents);
879 Minidump minidump(minidump_stream);
880 ASSERT_TRUE(minidump.Read());
881 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
882
883 MinidumpException *md_exception = minidump.GetException();
884 ASSERT_TRUE(md_exception != NULL);
885
886 uint32_t thread_id;
887 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
888 ASSERT_EQ(0x1234abcdU, thread_id);
889
890 const MDRawExceptionStream* raw_exception = md_exception->exception();
891 ASSERT_TRUE(raw_exception != NULL);
892 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
893 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
894 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
895 raw_exception->exception_record.exception_address);
896
897 MinidumpContext *md_context = md_exception->GetContext();
898 ASSERT_TRUE(md_context != NULL);
899
900 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
901 const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
902 ASSERT_TRUE(md_raw_context != NULL);
903
904 // Even though the CPU flags were missing from the context_flags, the
905 // GetContext call above is expected to load the missing CPU flags from the
906 // system info stream and set the CPU type bits in context_flags.
907 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags);
908
909 EXPECT_EQ(0x3ecba80dU, raw_context.edi);
910 EXPECT_EQ(0x382583b9U, raw_context.esi);
911 EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
912 EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
913 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
914 EXPECT_EQ(0x6a5025e2U, raw_context.eax);
915 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
916 EXPECT_EQ(0x6913f540U, raw_context.eip);
917 EXPECT_EQ(0xbffe6edaU, raw_context.cs);
918 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
919 EXPECT_EQ(0x659caaa4U, raw_context.esp);
920 EXPECT_EQ(0x2e951ef7U, raw_context.ss);
921 }
922
923 // This test covers a scenario where a dump contains an exception but the
924 // context record of the exception is missing the CPU type information in its
925 // context_flags. The dump has no system info stream so it is imposible to
926 // deduce the CPU type, hence the context record is unusable.
TEST(Dump,OneExceptionX86NoCPUFlagsNoSystemInfo)927 TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) {
928 Dump dump(0, kLittleEndian);
929
930 MDRawContextX86 raw_context;
931 // Intentionally not setting CPU type in the context_flags
932 raw_context.context_flags = 0;
933 raw_context.edi = 0x3ecba80d;
934 raw_context.esi = 0x382583b9;
935 raw_context.ebx = 0x7fccc03f;
936 raw_context.edx = 0xf62f8ec2;
937 raw_context.ecx = 0x46a6a6a8;
938 raw_context.eax = 0x6a5025e2;
939 raw_context.ebp = 0xd9fabb4a;
940 raw_context.eip = 0x6913f540;
941 raw_context.cs = 0xbffe6eda;
942 raw_context.eflags = 0xb2ce1e2d;
943 raw_context.esp = 0x659caaa4;
944 raw_context.ss = 0x2e951ef7;
945 Context context(dump, raw_context);
946
947 Exception exception(dump, context,
948 0x1234abcd, // thread id
949 0xdcba4321, // exception code
950 0xf0e0d0c0, // exception flags
951 0x0919a9b9c9d9e9f9ULL); // exception address
952
953 dump.Add(&context);
954 dump.Add(&exception);
955 dump.Finish();
956
957 string contents;
958 ASSERT_TRUE(dump.GetContents(&contents));
959
960 istringstream minidump_stream(contents);
961 Minidump minidump(minidump_stream);
962 ASSERT_TRUE(minidump.Read());
963 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
964
965 MinidumpException *md_exception = minidump.GetException();
966 ASSERT_TRUE(md_exception != NULL);
967
968 uint32_t thread_id;
969 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
970 ASSERT_EQ(0x1234abcdU, thread_id);
971
972 const MDRawExceptionStream* raw_exception = md_exception->exception();
973 ASSERT_TRUE(raw_exception != NULL);
974 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
975 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
976 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
977 raw_exception->exception_record.exception_address);
978
979 // The context record of the exception is unusable because the context_flags
980 // don't have CPU type information and at the same time the minidump lacks
981 // system info stream so it is impossible to deduce the CPU type.
982 MinidumpContext *md_context = md_exception->GetContext();
983 ASSERT_EQ(NULL, md_context);
984 }
985
TEST(Dump,OneExceptionARM)986 TEST(Dump, OneExceptionARM) {
987 Dump dump(0, kLittleEndian);
988
989 MDRawContextARM raw_context;
990 raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
991 raw_context.iregs[0] = 0x3ecba80d;
992 raw_context.iregs[1] = 0x382583b9;
993 raw_context.iregs[2] = 0x7fccc03f;
994 raw_context.iregs[3] = 0xf62f8ec2;
995 raw_context.iregs[4] = 0x46a6a6a8;
996 raw_context.iregs[5] = 0x6a5025e2;
997 raw_context.iregs[6] = 0xd9fabb4a;
998 raw_context.iregs[7] = 0x6913f540;
999 raw_context.iregs[8] = 0xbffe6eda;
1000 raw_context.iregs[9] = 0xb2ce1e2d;
1001 raw_context.iregs[10] = 0x659caaa4;
1002 raw_context.iregs[11] = 0xf0e0d0c0;
1003 raw_context.iregs[12] = 0xa9b8c7d6;
1004 raw_context.iregs[13] = 0x12345678;
1005 raw_context.iregs[14] = 0xabcd1234;
1006 raw_context.iregs[15] = 0x10203040;
1007 raw_context.cpsr = 0x2e951ef7;
1008 Context context(dump, raw_context);
1009
1010 Exception exception(dump, context,
1011 0x1234abcd, // thread id
1012 0xdcba4321, // exception code
1013 0xf0e0d0c0, // exception flags
1014 0x0919a9b9c9d9e9f9ULL); // exception address
1015
1016 dump.Add(&context);
1017 dump.Add(&exception);
1018 dump.Finish();
1019
1020 string contents;
1021 ASSERT_TRUE(dump.GetContents(&contents));
1022
1023 istringstream minidump_stream(contents);
1024 Minidump minidump(minidump_stream);
1025 ASSERT_TRUE(minidump.Read());
1026 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1027
1028 MinidumpException *md_exception = minidump.GetException();
1029 ASSERT_TRUE(md_exception != NULL);
1030
1031 uint32_t thread_id;
1032 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1033 ASSERT_EQ(0x1234abcdU, thread_id);
1034
1035 const MDRawExceptionStream* raw_exception = md_exception->exception();
1036 ASSERT_TRUE(raw_exception != NULL);
1037 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1038 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1039 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1040 raw_exception->exception_record.exception_address);
1041
1042 MinidumpContext *md_context = md_exception->GetContext();
1043 ASSERT_TRUE(md_context != NULL);
1044 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
1045 const MDRawContextARM *md_raw_context = md_context->GetContextARM();
1046 ASSERT_TRUE(md_raw_context != NULL);
1047 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
1048 (md_raw_context->context_flags
1049 & MD_CONTEXT_ARM_INTEGER));
1050 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1051 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1052 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1053 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1054 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1055 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1056 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1057 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1058 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1059 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1060 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1061 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1062 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1063 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1064 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1065 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1066 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
1067 }
1068
TEST(Dump,OneExceptionARMOldFlags)1069 TEST(Dump, OneExceptionARMOldFlags) {
1070 Dump dump(0, kLittleEndian);
1071
1072 MDRawContextARM raw_context;
1073 // MD_CONTEXT_ARM_INTEGER, but with _OLD
1074 raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
1075 raw_context.iregs[0] = 0x3ecba80d;
1076 raw_context.iregs[1] = 0x382583b9;
1077 raw_context.iregs[2] = 0x7fccc03f;
1078 raw_context.iregs[3] = 0xf62f8ec2;
1079 raw_context.iregs[4] = 0x46a6a6a8;
1080 raw_context.iregs[5] = 0x6a5025e2;
1081 raw_context.iregs[6] = 0xd9fabb4a;
1082 raw_context.iregs[7] = 0x6913f540;
1083 raw_context.iregs[8] = 0xbffe6eda;
1084 raw_context.iregs[9] = 0xb2ce1e2d;
1085 raw_context.iregs[10] = 0x659caaa4;
1086 raw_context.iregs[11] = 0xf0e0d0c0;
1087 raw_context.iregs[12] = 0xa9b8c7d6;
1088 raw_context.iregs[13] = 0x12345678;
1089 raw_context.iregs[14] = 0xabcd1234;
1090 raw_context.iregs[15] = 0x10203040;
1091 raw_context.cpsr = 0x2e951ef7;
1092 Context context(dump, raw_context);
1093
1094 Exception exception(dump, context,
1095 0x1234abcd, // thread id
1096 0xdcba4321, // exception code
1097 0xf0e0d0c0, // exception flags
1098 0x0919a9b9c9d9e9f9ULL); // exception address
1099
1100 dump.Add(&context);
1101 dump.Add(&exception);
1102 dump.Finish();
1103
1104 string contents;
1105 ASSERT_TRUE(dump.GetContents(&contents));
1106
1107 istringstream minidump_stream(contents);
1108 Minidump minidump(minidump_stream);
1109 ASSERT_TRUE(minidump.Read());
1110 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1111
1112 MinidumpException *md_exception = minidump.GetException();
1113 ASSERT_TRUE(md_exception != NULL);
1114
1115 uint32_t thread_id;
1116 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1117 ASSERT_EQ(0x1234abcdU, thread_id);
1118
1119 const MDRawExceptionStream* raw_exception = md_exception->exception();
1120 ASSERT_TRUE(raw_exception != NULL);
1121 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1122 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1123 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
1124 raw_exception->exception_record.exception_address);
1125
1126 MinidumpContext *md_context = md_exception->GetContext();
1127 ASSERT_TRUE(md_context != NULL);
1128 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
1129 const MDRawContextARM *md_raw_context = md_context->GetContextARM();
1130 ASSERT_TRUE(md_raw_context != NULL);
1131 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
1132 (md_raw_context->context_flags
1133 & MD_CONTEXT_ARM_INTEGER));
1134 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1135 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1136 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1137 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1138 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1139 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1140 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1141 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1142 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1143 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1144 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1145 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1146 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1147 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1148 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1149 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1150 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
1151 }
1152
TEST(Dump,OneExceptionMIPS)1153 TEST(Dump, OneExceptionMIPS) {
1154 Dump dump(0, kLittleEndian);
1155
1156 MDRawContextMIPS raw_context;
1157 raw_context.context_flags = MD_CONTEXT_MIPS_INTEGER;
1158 raw_context.iregs[0] = 0x3ecba80d;
1159 raw_context.iregs[1] = 0x382583b9;
1160 raw_context.iregs[2] = 0x7fccc03f;
1161 raw_context.iregs[3] = 0xf62f8ec2;
1162 raw_context.iregs[4] = 0x46a6a6a8;
1163 raw_context.iregs[5] = 0x6a5025e2;
1164 raw_context.iregs[6] = 0xd9fabb4a;
1165 raw_context.iregs[7] = 0x6913f540;
1166 raw_context.iregs[8] = 0xbffe6eda;
1167 raw_context.iregs[9] = 0xb2ce1e2d;
1168 raw_context.iregs[10] = 0x659caaa4;
1169 raw_context.iregs[11] = 0xf0e0d0c0;
1170 raw_context.iregs[12] = 0xa9b8c7d6;
1171 raw_context.iregs[13] = 0x12345678;
1172 raw_context.iregs[14] = 0xabcd1234;
1173 raw_context.iregs[15] = 0x10203040;
1174 raw_context.iregs[16] = 0xa80d3ecb;
1175 raw_context.iregs[17] = 0x83b93825;
1176 raw_context.iregs[18] = 0xc03f7fcc;
1177 raw_context.iregs[19] = 0x8ec2f62f;
1178 raw_context.iregs[20] = 0xa6a846a6;
1179 raw_context.iregs[21] = 0x25e26a50;
1180 raw_context.iregs[22] = 0xbb4ad9fa;
1181 raw_context.iregs[23] = 0xf5406913;
1182 raw_context.iregs[24] = 0x6edabffe;
1183 raw_context.iregs[25] = 0x1e2db2ce;
1184 raw_context.iregs[26] = 0xaaa4659c;
1185 raw_context.iregs[27] = 0xd0c0f0e0;
1186 raw_context.iregs[28] = 0xc7d6a9b8;
1187 raw_context.iregs[29] = 0x56781234;
1188 raw_context.iregs[30] = 0x1234abcd;
1189 raw_context.iregs[31] = 0x30401020;
1190
1191 Context context(dump, raw_context);
1192
1193 Exception exception(dump, context,
1194 0x1234abcd, // Thread id.
1195 0xdcba4321, // Exception code.
1196 0xf0e0d0c0, // Exception flags.
1197 0x0919a9b9); // Exception address.
1198
1199 dump.Add(&context);
1200 dump.Add(&exception);
1201 dump.Finish();
1202
1203 string contents;
1204 ASSERT_TRUE(dump.GetContents(&contents));
1205
1206 istringstream minidump_stream(contents);
1207 Minidump minidump(minidump_stream);
1208 ASSERT_TRUE(minidump.Read());
1209 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
1210
1211 MinidumpException *md_exception = minidump.GetException();
1212 ASSERT_TRUE(md_exception != NULL);
1213
1214 uint32_t thread_id;
1215 ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
1216 ASSERT_EQ(0x1234abcdU, thread_id);
1217
1218 const MDRawExceptionStream* raw_exception = md_exception->exception();
1219 ASSERT_TRUE(raw_exception != NULL);
1220 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
1221 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
1222 EXPECT_EQ(0x0919a9b9U,
1223 raw_exception->exception_record.exception_address);
1224
1225 MinidumpContext* md_context = md_exception->GetContext();
1226 ASSERT_TRUE(md_context != NULL);
1227 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU());
1228 const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS();
1229 ASSERT_TRUE(md_raw_context != NULL);
1230 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER,
1231 (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER));
1232 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
1233 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
1234 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
1235 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
1236 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
1237 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
1238 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
1239 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
1240 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
1241 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
1242 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
1243 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
1244 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
1245 EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
1246 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
1247 EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
1248 EXPECT_EQ(0xa80d3ecbU, raw_context.iregs[16]);
1249 EXPECT_EQ(0x83b93825U, raw_context.iregs[17]);
1250 EXPECT_EQ(0xc03f7fccU, raw_context.iregs[18]);
1251 EXPECT_EQ(0x8ec2f62fU, raw_context.iregs[19]);
1252 EXPECT_EQ(0xa6a846a6U, raw_context.iregs[20]);
1253 EXPECT_EQ(0x25e26a50U, raw_context.iregs[21]);
1254 EXPECT_EQ(0xbb4ad9faU, raw_context.iregs[22]);
1255 EXPECT_EQ(0xf5406913U, raw_context.iregs[23]);
1256 EXPECT_EQ(0x6edabffeU, raw_context.iregs[24]);
1257 EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]);
1258 EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]);
1259 EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]);
1260 EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]);
1261 EXPECT_EQ(0x56781234U, raw_context.iregs[29]);
1262 EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]);
1263 EXPECT_EQ(0x30401020U, raw_context.iregs[31]);
1264 }
1265
1266 } // namespace
1267