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