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