• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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