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