/ src / processor / minidump_unittest.cc
minidump_unittest.cc
   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:
  87    void SetUp() {
  88      minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
  89        "/src/processor/testdata/minidump2.dmp";
  90    }
  91    string minidump_file_;
  92  };
  93  
  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  
 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  
 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  
 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  
 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  
 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  
 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.
 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  
 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  
 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  
 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  
 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.
 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.
 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.
 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  
 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  
 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  
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  
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  
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
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.
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  
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  
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  
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