toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1153 @@
     1.4 +// Copyright (c) 2010, Google Inc.
     1.5 +// All rights reserved.
     1.6 +//
     1.7 +// Redistribution and use in source and binary forms, with or without
     1.8 +// modification, are permitted provided that the following conditions are
     1.9 +// met:
    1.10 +//
    1.11 +//     * Redistributions of source code must retain the above copyright
    1.12 +// notice, this list of conditions and the following disclaimer.
    1.13 +//     * Redistributions in binary form must reproduce the above
    1.14 +// copyright notice, this list of conditions and the following disclaimer
    1.15 +// in the documentation and/or other materials provided with the
    1.16 +// distribution.
    1.17 +//     * Neither the name of Google Inc. nor the names of its
    1.18 +// contributors may be used to endorse or promote products derived from
    1.19 +// this software without specific prior written permission.
    1.20 +//
    1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.32 +
    1.33 +// Unit test for Minidump.  Uses a pre-generated minidump and
    1.34 +// verifies that certain streams are correct.
    1.35 +
    1.36 +#include <iostream>
    1.37 +#include <fstream>
    1.38 +#include <sstream>
    1.39 +#include <stdlib.h>
    1.40 +#include <string>
    1.41 +#include <vector>
    1.42 +
    1.43 +#include "breakpad_googletest_includes.h"
    1.44 +#include "common/using_std_string.h"
    1.45 +#include "google_breakpad/common/minidump_format.h"
    1.46 +#include "google_breakpad/processor/minidump.h"
    1.47 +#include "processor/logging.h"
    1.48 +#include "processor/synth_minidump.h"
    1.49 +
    1.50 +namespace {
    1.51 +
    1.52 +using google_breakpad::Minidump;
    1.53 +using google_breakpad::MinidumpContext;
    1.54 +using google_breakpad::MinidumpException;
    1.55 +using google_breakpad::MinidumpMemoryInfo;
    1.56 +using google_breakpad::MinidumpMemoryInfoList;
    1.57 +using google_breakpad::MinidumpMemoryList;
    1.58 +using google_breakpad::MinidumpMemoryRegion;
    1.59 +using google_breakpad::MinidumpModule;
    1.60 +using google_breakpad::MinidumpModuleList;
    1.61 +using google_breakpad::MinidumpSystemInfo;
    1.62 +using google_breakpad::MinidumpThread;
    1.63 +using google_breakpad::MinidumpThreadList;
    1.64 +using google_breakpad::SynthMinidump::Context;
    1.65 +using google_breakpad::SynthMinidump::Dump;
    1.66 +using google_breakpad::SynthMinidump::Exception;
    1.67 +using google_breakpad::SynthMinidump::Memory;
    1.68 +using google_breakpad::SynthMinidump::Module;
    1.69 +using google_breakpad::SynthMinidump::Stream;
    1.70 +using google_breakpad::SynthMinidump::String;
    1.71 +using google_breakpad::SynthMinidump::SystemInfo;
    1.72 +using google_breakpad::SynthMinidump::Thread;
    1.73 +using google_breakpad::test_assembler::kBigEndian;
    1.74 +using google_breakpad::test_assembler::kLittleEndian;
    1.75 +using std::ifstream;
    1.76 +using std::istringstream;
    1.77 +using std::vector;
    1.78 +using ::testing::Return;
    1.79 +
    1.80 +class MinidumpTest : public ::testing::Test {
    1.81 +public:
    1.82 +  void SetUp() {
    1.83 +    minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
    1.84 +      "/src/processor/testdata/minidump2.dmp";
    1.85 +  }
    1.86 +  string minidump_file_;
    1.87 +};
    1.88 +
    1.89 +TEST_F(MinidumpTest, TestMinidumpFromFile) {
    1.90 +  Minidump minidump(minidump_file_);
    1.91 +  ASSERT_EQ(minidump.path(), minidump_file_);
    1.92 +  ASSERT_TRUE(minidump.Read());
    1.93 +  const MDRawHeader* header = minidump.header();
    1.94 +  ASSERT_NE(header, (MDRawHeader*)NULL);
    1.95 +  ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
    1.96 +  //TODO: add more checks here
    1.97 +}
    1.98 +
    1.99 +TEST_F(MinidumpTest, TestMinidumpFromStream) {
   1.100 +  // read minidump contents into memory, construct a stringstream around them
   1.101 +  ifstream file_stream(minidump_file_.c_str(), std::ios::in);
   1.102 +  ASSERT_TRUE(file_stream.good());
   1.103 +  vector<char> bytes;
   1.104 +  file_stream.seekg(0, std::ios_base::end);
   1.105 +  ASSERT_TRUE(file_stream.good());
   1.106 +  bytes.resize(file_stream.tellg());
   1.107 +  file_stream.seekg(0, std::ios_base::beg);
   1.108 +  ASSERT_TRUE(file_stream.good());
   1.109 +  file_stream.read(&bytes[0], bytes.size());
   1.110 +  ASSERT_TRUE(file_stream.good());
   1.111 +  string str(&bytes[0], bytes.size());
   1.112 +  istringstream stream(str);
   1.113 +  ASSERT_TRUE(stream.good());
   1.114 +
   1.115 +  // now read minidump from stringstream
   1.116 +  Minidump minidump(stream);
   1.117 +  ASSERT_EQ(minidump.path(), "");
   1.118 +  ASSERT_TRUE(minidump.Read());
   1.119 +  const MDRawHeader* header = minidump.header();
   1.120 +  ASSERT_NE(header, (MDRawHeader*)NULL);
   1.121 +  ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
   1.122 +  //TODO: add more checks here
   1.123 +}
   1.124 +
   1.125 +TEST(Dump, ReadBackEmpty) {
   1.126 +  Dump dump(0);
   1.127 +  dump.Finish();
   1.128 +  string contents;
   1.129 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.130 +  istringstream stream(contents);
   1.131 +  Minidump minidump(stream);
   1.132 +  ASSERT_TRUE(minidump.Read());
   1.133 +  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
   1.134 +}
   1.135 +
   1.136 +TEST(Dump, ReadBackEmptyBigEndian) {
   1.137 +  Dump big_minidump(0, kBigEndian);
   1.138 +  big_minidump.Finish();
   1.139 +  string contents;
   1.140 +  ASSERT_TRUE(big_minidump.GetContents(&contents));
   1.141 +  istringstream stream(contents);
   1.142 +  Minidump minidump(stream);
   1.143 +  ASSERT_TRUE(minidump.Read());
   1.144 +  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
   1.145 +}
   1.146 +
   1.147 +TEST(Dump, OneStream) {
   1.148 +  Dump dump(0, kBigEndian);
   1.149 +  Stream stream(dump, 0xfbb7fa2bU);
   1.150 +  stream.Append("stream contents");
   1.151 +  dump.Add(&stream);
   1.152 +  dump.Finish();
   1.153 +  
   1.154 +  string contents;
   1.155 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.156 +  istringstream minidump_stream(contents);
   1.157 +  Minidump minidump(minidump_stream);
   1.158 +  ASSERT_TRUE(minidump.Read());
   1.159 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.160 +
   1.161 +  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
   1.162 +  ASSERT_TRUE(dir != NULL);
   1.163 +  EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
   1.164 +
   1.165 +  uint32_t stream_length;
   1.166 +  ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
   1.167 +  ASSERT_EQ(15U, stream_length);
   1.168 +  char stream_contents[15];
   1.169 +  ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
   1.170 +  EXPECT_EQ(string("stream contents"),
   1.171 +            string(stream_contents, sizeof(stream_contents)));
   1.172 +
   1.173 +  EXPECT_FALSE(minidump.GetThreadList());
   1.174 +  EXPECT_FALSE(minidump.GetModuleList());
   1.175 +  EXPECT_FALSE(minidump.GetMemoryList());
   1.176 +  EXPECT_FALSE(minidump.GetException());
   1.177 +  EXPECT_FALSE(minidump.GetAssertion());
   1.178 +  EXPECT_FALSE(minidump.GetSystemInfo());
   1.179 +  EXPECT_FALSE(minidump.GetMiscInfo());
   1.180 +  EXPECT_FALSE(minidump.GetBreakpadInfo());
   1.181 +}
   1.182 +
   1.183 +TEST(Dump, OneMemory) {
   1.184 +  Dump dump(0, kBigEndian);
   1.185 +  Memory memory(dump, 0x309d68010bd21b2cULL);
   1.186 +  memory.Append("memory contents");
   1.187 +  dump.Add(&memory);
   1.188 +  dump.Finish();
   1.189 +
   1.190 +  string contents;
   1.191 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.192 +  istringstream minidump_stream(contents);
   1.193 +  Minidump minidump(minidump_stream);
   1.194 +  ASSERT_TRUE(minidump.Read());
   1.195 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.196 +
   1.197 +  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
   1.198 +  ASSERT_TRUE(dir != NULL);
   1.199 +  EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
   1.200 +
   1.201 +  MinidumpMemoryList *memory_list = minidump.GetMemoryList();
   1.202 +  ASSERT_TRUE(memory_list != NULL);
   1.203 +  ASSERT_EQ(1U, memory_list->region_count());
   1.204 +
   1.205 +  MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
   1.206 +  ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
   1.207 +  ASSERT_EQ(15U, region1->GetSize());
   1.208 +  const uint8_t *region1_bytes = region1->GetMemory();
   1.209 +  ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
   1.210 +}
   1.211 +
   1.212 +// One thread --- and its requisite entourage.
   1.213 +TEST(Dump, OneThread) {
   1.214 +  Dump dump(0, kLittleEndian);
   1.215 +  Memory stack(dump, 0x2326a0fa);
   1.216 +  stack.Append("stack for thread");
   1.217 +
   1.218 +  MDRawContextX86 raw_context;
   1.219 +  const uint32_t kExpectedEIP = 0x6913f540;
   1.220 +  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
   1.221 +  raw_context.edi = 0x3ecba80d;
   1.222 +  raw_context.esi = 0x382583b9;
   1.223 +  raw_context.ebx = 0x7fccc03f;
   1.224 +  raw_context.edx = 0xf62f8ec2;
   1.225 +  raw_context.ecx = 0x46a6a6a8;
   1.226 +  raw_context.eax = 0x6a5025e2;
   1.227 +  raw_context.ebp = 0xd9fabb4a;
   1.228 +  raw_context.eip = kExpectedEIP;
   1.229 +  raw_context.cs = 0xbffe6eda;
   1.230 +  raw_context.eflags = 0xb2ce1e2d;
   1.231 +  raw_context.esp = 0x659caaa4;
   1.232 +  raw_context.ss = 0x2e951ef7;
   1.233 +  Context context(dump, raw_context);
   1.234 +  
   1.235 +  Thread thread(dump, 0xa898f11b, stack, context,
   1.236 +                0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
   1.237 +  
   1.238 +  dump.Add(&stack);
   1.239 +  dump.Add(&context);
   1.240 +  dump.Add(&thread);
   1.241 +  dump.Finish();
   1.242 +
   1.243 +  string contents;
   1.244 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.245 +
   1.246 +  istringstream minidump_stream(contents);
   1.247 +  Minidump minidump(minidump_stream);
   1.248 +  ASSERT_TRUE(minidump.Read());
   1.249 +  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
   1.250 +
   1.251 +  MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
   1.252 +  ASSERT_TRUE(md_memory_list != NULL);
   1.253 +  ASSERT_EQ(1U, md_memory_list->region_count());
   1.254 +
   1.255 +  MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
   1.256 +  ASSERT_EQ(0x2326a0faU, md_region->GetBase());
   1.257 +  ASSERT_EQ(16U, md_region->GetSize());
   1.258 +  const uint8_t *region_bytes = md_region->GetMemory();
   1.259 +  ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
   1.260 +
   1.261 +  MinidumpThreadList *thread_list = minidump.GetThreadList();
   1.262 +  ASSERT_TRUE(thread_list != NULL);
   1.263 +  ASSERT_EQ(1U, thread_list->thread_count());
   1.264 +
   1.265 +  MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
   1.266 +  ASSERT_TRUE(md_thread != NULL);
   1.267 +  uint32_t thread_id;
   1.268 +  ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
   1.269 +  ASSERT_EQ(0xa898f11bU, thread_id);
   1.270 +  MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
   1.271 +  ASSERT_TRUE(md_stack != NULL);
   1.272 +  ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
   1.273 +  ASSERT_EQ(16U, md_stack->GetSize());
   1.274 +  const uint8_t *md_stack_bytes = md_stack->GetMemory();
   1.275 +  ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
   1.276 +
   1.277 +  MinidumpContext *md_context = md_thread->GetContext();
   1.278 +  ASSERT_TRUE(md_context != NULL);
   1.279 +  ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
   1.280 +
   1.281 +  uint64_t eip;
   1.282 +  ASSERT_TRUE(md_context->GetInstructionPointer(&eip));
   1.283 +  EXPECT_EQ(kExpectedEIP, eip);
   1.284 +
   1.285 +  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
   1.286 +  ASSERT_TRUE(md_raw_context != NULL);
   1.287 +  ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
   1.288 +            (md_raw_context->context_flags
   1.289 +             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
   1.290 +  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
   1.291 +  EXPECT_EQ(0x382583b9U, raw_context.esi);
   1.292 +  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
   1.293 +  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
   1.294 +  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
   1.295 +  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
   1.296 +  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
   1.297 +  EXPECT_EQ(kExpectedEIP, raw_context.eip);
   1.298 +  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
   1.299 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
   1.300 +  EXPECT_EQ(0x659caaa4U, raw_context.esp);
   1.301 +  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
   1.302 +}
   1.303 +
   1.304 +TEST(Dump, ThreadMissingMemory) {
   1.305 +  Dump dump(0, kLittleEndian);
   1.306 +  Memory stack(dump, 0x2326a0fa);
   1.307 +  // Stack has no contents.
   1.308 +
   1.309 +  MDRawContextX86 raw_context;
   1.310 +  memset(&raw_context, 0, sizeof(raw_context));
   1.311 +  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
   1.312 +  Context context(dump, raw_context);
   1.313 +
   1.314 +  Thread thread(dump, 0xa898f11b, stack, context,
   1.315 +                0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
   1.316 +
   1.317 +  dump.Add(&stack);
   1.318 +  dump.Add(&context);
   1.319 +  dump.Add(&thread);
   1.320 +  dump.Finish();
   1.321 +
   1.322 +  string contents;
   1.323 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.324 +
   1.325 +  istringstream minidump_stream(contents);
   1.326 +  Minidump minidump(minidump_stream);
   1.327 +  ASSERT_TRUE(minidump.Read());
   1.328 +  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
   1.329 +
   1.330 +  // This should succeed even though the thread has no stack memory.
   1.331 +  MinidumpThreadList* thread_list = minidump.GetThreadList();
   1.332 +  ASSERT_TRUE(thread_list != NULL);
   1.333 +  ASSERT_EQ(1U, thread_list->thread_count());
   1.334 +
   1.335 +  MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
   1.336 +  ASSERT_TRUE(md_thread != NULL);
   1.337 +
   1.338 +  uint32_t thread_id;
   1.339 +  ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
   1.340 +  ASSERT_EQ(0xa898f11bU, thread_id);
   1.341 +
   1.342 +  MinidumpContext* md_context = md_thread->GetContext();
   1.343 +  ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context);
   1.344 +
   1.345 +  MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
   1.346 +  ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
   1.347 +}
   1.348 +
   1.349 +TEST(Dump, ThreadMissingContext) {
   1.350 +  Dump dump(0, kLittleEndian);
   1.351 +  Memory stack(dump, 0x2326a0fa);
   1.352 +  stack.Append("stack for thread");
   1.353 +
   1.354 +  // Context is empty.
   1.355 +  Context context(dump);
   1.356 +
   1.357 +  Thread thread(dump, 0xa898f11b, stack, context,
   1.358 +                0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
   1.359 +
   1.360 +  dump.Add(&stack);
   1.361 +  dump.Add(&context);
   1.362 +  dump.Add(&thread);
   1.363 +  dump.Finish();
   1.364 +
   1.365 +  string contents;
   1.366 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.367 +
   1.368 +  istringstream minidump_stream(contents);
   1.369 +  Minidump minidump(minidump_stream);
   1.370 +  ASSERT_TRUE(minidump.Read());
   1.371 +  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
   1.372 +
   1.373 +  // This should succeed even though the thread has no stack memory.
   1.374 +  MinidumpThreadList* thread_list = minidump.GetThreadList();
   1.375 +  ASSERT_TRUE(thread_list != NULL);
   1.376 +  ASSERT_EQ(1U, thread_list->thread_count());
   1.377 +
   1.378 +  MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
   1.379 +  ASSERT_TRUE(md_thread != NULL);
   1.380 +
   1.381 +  uint32_t thread_id;
   1.382 +  ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
   1.383 +  ASSERT_EQ(0xa898f11bU, thread_id);
   1.384 +  MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
   1.385 +  ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
   1.386 +
   1.387 +  MinidumpContext* md_context = md_thread->GetContext();
   1.388 +  ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context);
   1.389 +}
   1.390 +
   1.391 +TEST(Dump, OneModule) {
   1.392 +  static const MDVSFixedFileInfo fixed_file_info = {
   1.393 +    0xb2fba33a,                           // signature
   1.394 +    0x33d7a728,                           // struct_version
   1.395 +    0x31afcb20,                           // file_version_hi
   1.396 +    0xe51cdab1,                           // file_version_lo
   1.397 +    0xd1ea6907,                           // product_version_hi
   1.398 +    0x03032857,                           // product_version_lo
   1.399 +    0x11bf71d7,                           // file_flags_mask
   1.400 +    0x5fb8cdbf,                           // file_flags
   1.401 +    0xe45d0d5d,                           // file_os
   1.402 +    0x107d9562,                           // file_type
   1.403 +    0x5a8844d4,                           // file_subtype
   1.404 +    0xa8d30b20,                           // file_date_hi
   1.405 +    0x651c3e4e                            // file_date_lo
   1.406 +  };
   1.407 +
   1.408 +  Dump dump(0, kBigEndian);
   1.409 +  String module_name(dump, "single module");
   1.410 +  Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
   1.411 +                module_name,
   1.412 +                0xb1054d2a,
   1.413 +                0x34571371,
   1.414 +                fixed_file_info, // from synth_minidump_unittest_data.h
   1.415 +                NULL, NULL);
   1.416 +
   1.417 +  dump.Add(&module);
   1.418 +  dump.Add(&module_name);
   1.419 +  dump.Finish();
   1.420 +  
   1.421 +  string contents;
   1.422 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.423 +  istringstream minidump_stream(contents);
   1.424 +  Minidump minidump(minidump_stream);
   1.425 +  ASSERT_TRUE(minidump.Read());
   1.426 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.427 +
   1.428 +  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
   1.429 +  ASSERT_TRUE(dir != NULL);
   1.430 +  EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
   1.431 +
   1.432 +  MinidumpModuleList *md_module_list = minidump.GetModuleList();
   1.433 +  ASSERT_TRUE(md_module_list != NULL);
   1.434 +  ASSERT_EQ(1U, md_module_list->module_count());
   1.435 +
   1.436 +  const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
   1.437 +  ASSERT_TRUE(md_module != NULL);
   1.438 +  ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
   1.439 +  ASSERT_EQ(0xada542bd, md_module->size());
   1.440 +  ASSERT_EQ("single module", md_module->code_file());
   1.441 +
   1.442 +  const MDRawModule *md_raw_module = md_module->module();
   1.443 +  ASSERT_TRUE(md_raw_module != NULL);
   1.444 +  ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
   1.445 +  ASSERT_EQ(0x34571371U, md_raw_module->checksum);
   1.446 +  ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
   1.447 +                     sizeof(fixed_file_info)) == 0);
   1.448 +}
   1.449 +
   1.450 +TEST(Dump, OneSystemInfo) {
   1.451 +  Dump dump(0, kLittleEndian);
   1.452 +  String csd_version(dump, "Petulant Pierogi");
   1.453 +  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
   1.454 +
   1.455 +  dump.Add(&system_info);
   1.456 +  dump.Add(&csd_version);
   1.457 +  dump.Finish();
   1.458 +                         
   1.459 +  string contents;
   1.460 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.461 +  istringstream minidump_stream(contents);
   1.462 +  Minidump minidump(minidump_stream);
   1.463 +  ASSERT_TRUE(minidump.Read());
   1.464 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.465 +
   1.466 +  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
   1.467 +  ASSERT_TRUE(dir != NULL);
   1.468 +  EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
   1.469 +
   1.470 +  MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
   1.471 +  ASSERT_TRUE(md_system_info != NULL);
   1.472 +  ASSERT_EQ("windows", md_system_info->GetOS());
   1.473 +  ASSERT_EQ("x86", md_system_info->GetCPU());
   1.474 +  ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
   1.475 +  ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
   1.476 +}
   1.477 +
   1.478 +TEST(Dump, BigDump) {
   1.479 +  Dump dump(0, kLittleEndian);
   1.480 +
   1.481 +  // A SystemInfo stream.
   1.482 +  String csd_version(dump, "Munificent Macaque");
   1.483 +  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
   1.484 +  dump.Add(&csd_version);
   1.485 +  dump.Add(&system_info);
   1.486 +
   1.487 +  // Five threads!
   1.488 +  Memory stack0(dump, 0x70b9ebfc);
   1.489 +  stack0.Append("stack for thread zero");
   1.490 +  MDRawContextX86 raw_context0;
   1.491 +  raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
   1.492 +  raw_context0.eip = 0xaf0709e4;
   1.493 +  Context context0(dump, raw_context0);
   1.494 +  Thread thread0(dump, 0xbbef4432, stack0, context0,
   1.495 +                 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
   1.496 +  dump.Add(&stack0);
   1.497 +  dump.Add(&context0);
   1.498 +  dump.Add(&thread0);
   1.499 +
   1.500 +  Memory stack1(dump, 0xf988cc45);
   1.501 +  stack1.Append("stack for thread one");
   1.502 +  MDRawContextX86 raw_context1;
   1.503 +  raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
   1.504 +  raw_context1.eip = 0xe4f56f81;
   1.505 +  Context context1(dump, raw_context1);
   1.506 +  Thread thread1(dump, 0x657c3f58, stack1, context1,
   1.507 +                 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
   1.508 +  dump.Add(&stack1);
   1.509 +  dump.Add(&context1);
   1.510 +  dump.Add(&thread1);
   1.511 +
   1.512 +  Memory stack2(dump, 0xc8a92e7c);
   1.513 +  stack2.Append("stack for thread two");
   1.514 +  MDRawContextX86 raw_context2;
   1.515 +  raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
   1.516 +  raw_context2.eip = 0xb336a438;
   1.517 +  Context context2(dump, raw_context2);
   1.518 +  Thread thread2(dump, 0xdf4b8a71, stack2, context2,
   1.519 +                 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
   1.520 +  dump.Add(&stack2);
   1.521 +  dump.Add(&context2);
   1.522 +  dump.Add(&thread2);
   1.523 +
   1.524 +  Memory stack3(dump, 0x36d08e08);
   1.525 +  stack3.Append("stack for thread three");
   1.526 +  MDRawContextX86 raw_context3;
   1.527 +  raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
   1.528 +  raw_context3.eip = 0xdf99a60c;
   1.529 +  Context context3(dump, raw_context3);
   1.530 +  Thread thread3(dump, 0x86e6c341, stack3, context3,
   1.531 +                 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
   1.532 +  dump.Add(&stack3);
   1.533 +  dump.Add(&context3);
   1.534 +  dump.Add(&thread3);
   1.535 +
   1.536 +  Memory stack4(dump, 0x1e0ab4fa);
   1.537 +  stack4.Append("stack for thread four");
   1.538 +  MDRawContextX86 raw_context4;
   1.539 +  raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
   1.540 +  raw_context4.eip = 0xaa646267;
   1.541 +  Context context4(dump, raw_context4);
   1.542 +  Thread thread4(dump, 0x261a28d4, stack4, context4,
   1.543 +                 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
   1.544 +  dump.Add(&stack4);
   1.545 +  dump.Add(&context4);
   1.546 +  dump.Add(&thread4);
   1.547 +
   1.548 +  // Three modules!
   1.549 +  String module1_name(dump, "module one");
   1.550 +  Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
   1.551 +  dump.Add(&module1_name);
   1.552 +  dump.Add(&module1);
   1.553 +
   1.554 +  String module2_name(dump, "module two");
   1.555 +  Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
   1.556 +  dump.Add(&module2_name);
   1.557 +  dump.Add(&module2);
   1.558 +
   1.559 +  String module3_name(dump, "module three");
   1.560 +  Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
   1.561 +  dump.Add(&module3_name);
   1.562 +  dump.Add(&module3);
   1.563 +
   1.564 +  // Add one more memory region, on top of the five stacks.
   1.565 +  Memory memory5(dump, 0x61979e828040e564ULL);
   1.566 +  memory5.Append("contents of memory 5");
   1.567 +  dump.Add(&memory5);
   1.568 +
   1.569 +  dump.Finish();
   1.570 +
   1.571 +  string contents;
   1.572 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.573 +  istringstream minidump_stream(contents);
   1.574 +  Minidump minidump(minidump_stream);
   1.575 +  ASSERT_TRUE(minidump.Read());
   1.576 +  ASSERT_EQ(4U, minidump.GetDirectoryEntryCount());
   1.577 +
   1.578 +  // Check the threads.
   1.579 +  MinidumpThreadList *thread_list = minidump.GetThreadList();
   1.580 +  ASSERT_TRUE(thread_list != NULL);
   1.581 +  ASSERT_EQ(5U, thread_list->thread_count());
   1.582 +  uint32_t thread_id;
   1.583 +  ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
   1.584 +  ASSERT_EQ(0xbbef4432U, thread_id);
   1.585 +  ASSERT_EQ(0x70b9ebfcU,
   1.586 +            thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
   1.587 +  ASSERT_EQ(0xaf0709e4U,
   1.588 +            thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
   1.589 +            ->eip);
   1.590 +
   1.591 +  ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
   1.592 +  ASSERT_EQ(0x657c3f58U, thread_id);
   1.593 +  ASSERT_EQ(0xf988cc45U,
   1.594 +            thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
   1.595 +  ASSERT_EQ(0xe4f56f81U,
   1.596 +            thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
   1.597 +            ->eip);
   1.598 +
   1.599 +  ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
   1.600 +  ASSERT_EQ(0xdf4b8a71U, thread_id);
   1.601 +  ASSERT_EQ(0xc8a92e7cU,
   1.602 +            thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
   1.603 +  ASSERT_EQ(0xb336a438U,
   1.604 +            thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
   1.605 +            ->eip);
   1.606 +
   1.607 +  ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
   1.608 +  ASSERT_EQ(0x86e6c341U, thread_id);
   1.609 +  ASSERT_EQ(0x36d08e08U,
   1.610 +            thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
   1.611 +  ASSERT_EQ(0xdf99a60cU,
   1.612 +            thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
   1.613 +            ->eip);
   1.614 +
   1.615 +  ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
   1.616 +  ASSERT_EQ(0x261a28d4U, thread_id);
   1.617 +  ASSERT_EQ(0x1e0ab4faU,
   1.618 +            thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
   1.619 +  ASSERT_EQ(0xaa646267U,
   1.620 +            thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
   1.621 +            ->eip);
   1.622 +
   1.623 +  // Check the modules.
   1.624 +  MinidumpModuleList *md_module_list = minidump.GetModuleList();
   1.625 +  ASSERT_TRUE(md_module_list != NULL);
   1.626 +  ASSERT_EQ(3U, md_module_list->module_count());
   1.627 +  EXPECT_EQ(0xeb77da57b5d4cbdaULL,
   1.628 +            md_module_list->GetModuleAtIndex(0)->base_address());
   1.629 +  EXPECT_EQ(0x8675884adfe5ac90ULL,
   1.630 +            md_module_list->GetModuleAtIndex(1)->base_address());
   1.631 +  EXPECT_EQ(0x95fc1544da321b6cULL,
   1.632 +            md_module_list->GetModuleAtIndex(2)->base_address());
   1.633 +}
   1.634 +
   1.635 +TEST(Dump, OneMemoryInfo) {
   1.636 +  Dump dump(0, kBigEndian);
   1.637 +  Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
   1.638 +
   1.639 +  // Add the MDRawMemoryInfoList header.
   1.640 +  const uint64_t kNumberOfEntries = 1;
   1.641 +  stream.D32(sizeof(MDRawMemoryInfoList))  // size_of_header
   1.642 +        .D32(sizeof(MDRawMemoryInfo))      // size_of_entry
   1.643 +        .D64(kNumberOfEntries);            // number_of_entries
   1.644 +
   1.645 +  
   1.646 +  // Now add a MDRawMemoryInfo entry.
   1.647 +  const uint64_t kBaseAddress = 0x1000;
   1.648 +  const uint64_t kRegionSize = 0x2000;
   1.649 +  stream.D64(kBaseAddress)                         // base_address
   1.650 +        .D64(kBaseAddress)                         // allocation_base
   1.651 +        .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE)  // allocation_protection
   1.652 +        .D32(0)                                    // __alignment1
   1.653 +        .D64(kRegionSize)                          // region_size
   1.654 +        .D32(MD_MEMORY_STATE_COMMIT)               // state
   1.655 +        .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE)  // protection
   1.656 +        .D32(MD_MEMORY_TYPE_PRIVATE)               // type
   1.657 +        .D32(0);                                   // __alignment2
   1.658 +
   1.659 +  dump.Add(&stream);
   1.660 +  dump.Finish();
   1.661 +
   1.662 +  string contents;
   1.663 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.664 +  istringstream minidump_stream(contents);
   1.665 +  Minidump minidump(minidump_stream);
   1.666 +  ASSERT_TRUE(minidump.Read());
   1.667 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.668 +
   1.669 +  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
   1.670 +  ASSERT_TRUE(dir != NULL);
   1.671 +  EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
   1.672 +
   1.673 +  MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
   1.674 +  ASSERT_TRUE(info_list != NULL);
   1.675 +  ASSERT_EQ(1U, info_list->info_count());
   1.676 +
   1.677 +  const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
   1.678 +  ASSERT_EQ(kBaseAddress, info1->GetBase());
   1.679 +  ASSERT_EQ(kRegionSize, info1->GetSize());
   1.680 +  ASSERT_TRUE(info1->IsExecutable());
   1.681 +  ASSERT_TRUE(info1->IsWritable());
   1.682 +
   1.683 +  // Should get back the same memory region here.
   1.684 +  const MinidumpMemoryInfo *info2 =
   1.685 +      info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
   1.686 +  ASSERT_EQ(kBaseAddress, info2->GetBase());
   1.687 +  ASSERT_EQ(kRegionSize, info2->GetSize());
   1.688 +}
   1.689 +
   1.690 +TEST(Dump, OneExceptionX86) {
   1.691 +  Dump dump(0, kLittleEndian);
   1.692 +
   1.693 +  MDRawContextX86 raw_context;
   1.694 +  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
   1.695 +  raw_context.edi = 0x3ecba80d;
   1.696 +  raw_context.esi = 0x382583b9;
   1.697 +  raw_context.ebx = 0x7fccc03f;
   1.698 +  raw_context.edx = 0xf62f8ec2;
   1.699 +  raw_context.ecx = 0x46a6a6a8;
   1.700 +  raw_context.eax = 0x6a5025e2;
   1.701 +  raw_context.ebp = 0xd9fabb4a;
   1.702 +  raw_context.eip = 0x6913f540;
   1.703 +  raw_context.cs = 0xbffe6eda;
   1.704 +  raw_context.eflags = 0xb2ce1e2d;
   1.705 +  raw_context.esp = 0x659caaa4;
   1.706 +  raw_context.ss = 0x2e951ef7;
   1.707 +  Context context(dump, raw_context);
   1.708 +
   1.709 +  Exception exception(dump, context,
   1.710 +                      0x1234abcd, // thread id
   1.711 +                      0xdcba4321, // exception code
   1.712 +                      0xf0e0d0c0, // exception flags
   1.713 +                      0x0919a9b9c9d9e9f9ULL); // exception address
   1.714 +  
   1.715 +  dump.Add(&context);
   1.716 +  dump.Add(&exception);
   1.717 +  dump.Finish();
   1.718 +
   1.719 +  string contents;
   1.720 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.721 +
   1.722 +  istringstream minidump_stream(contents);
   1.723 +  Minidump minidump(minidump_stream);
   1.724 +  ASSERT_TRUE(minidump.Read());
   1.725 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.726 +
   1.727 +  MinidumpException *md_exception = minidump.GetException();
   1.728 +  ASSERT_TRUE(md_exception != NULL);
   1.729 +
   1.730 +  uint32_t thread_id;
   1.731 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
   1.732 +  ASSERT_EQ(0x1234abcdU, thread_id);
   1.733 +
   1.734 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
   1.735 +  ASSERT_TRUE(raw_exception != NULL);
   1.736 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
   1.737 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
   1.738 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
   1.739 +            raw_exception->exception_record.exception_address);
   1.740 +
   1.741 +  MinidumpContext *md_context = md_exception->GetContext();
   1.742 +  ASSERT_TRUE(md_context != NULL);
   1.743 +  ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
   1.744 +  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
   1.745 +  ASSERT_TRUE(md_raw_context != NULL);
   1.746 +  ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
   1.747 +            (md_raw_context->context_flags
   1.748 +             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
   1.749 +  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
   1.750 +  EXPECT_EQ(0x382583b9U, raw_context.esi);
   1.751 +  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
   1.752 +  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
   1.753 +  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
   1.754 +  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
   1.755 +  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
   1.756 +  EXPECT_EQ(0x6913f540U, raw_context.eip);
   1.757 +  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
   1.758 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
   1.759 +  EXPECT_EQ(0x659caaa4U, raw_context.esp);
   1.760 +  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
   1.761 +}
   1.762 +
   1.763 +TEST(Dump, OneExceptionX86XState) {
   1.764 +  Dump dump(0, kLittleEndian);
   1.765 +
   1.766 +  MDRawContextX86 raw_context;
   1.767 +  raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
   1.768 +    MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
   1.769 +  raw_context.edi = 0x3ecba80d;
   1.770 +  raw_context.esi = 0x382583b9;
   1.771 +  raw_context.ebx = 0x7fccc03f;
   1.772 +  raw_context.edx = 0xf62f8ec2;
   1.773 +  raw_context.ecx = 0x46a6a6a8;
   1.774 +  raw_context.eax = 0x6a5025e2;
   1.775 +  raw_context.ebp = 0xd9fabb4a;
   1.776 +  raw_context.eip = 0x6913f540;
   1.777 +  raw_context.cs = 0xbffe6eda;
   1.778 +  raw_context.eflags = 0xb2ce1e2d;
   1.779 +  raw_context.esp = 0x659caaa4;
   1.780 +  raw_context.ss = 0x2e951ef7;
   1.781 +  Context context(dump, raw_context);
   1.782 +
   1.783 +  Exception exception(dump, context,
   1.784 +                      0x1234abcd, // thread id
   1.785 +                      0xdcba4321, // exception code
   1.786 +                      0xf0e0d0c0, // exception flags
   1.787 +                      0x0919a9b9c9d9e9f9ULL); // exception address
   1.788 +  
   1.789 +  dump.Add(&context);
   1.790 +  dump.Add(&exception);
   1.791 +  dump.Finish();
   1.792 +
   1.793 +  string contents;
   1.794 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.795 +
   1.796 +  istringstream minidump_stream(contents);
   1.797 +  Minidump minidump(minidump_stream);
   1.798 +  ASSERT_TRUE(minidump.Read());
   1.799 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.800 +
   1.801 +  MinidumpException *md_exception = minidump.GetException();
   1.802 +  ASSERT_TRUE(md_exception != NULL);
   1.803 +
   1.804 +  uint32_t thread_id;
   1.805 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
   1.806 +  ASSERT_EQ(0x1234abcdU, thread_id);
   1.807 +
   1.808 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
   1.809 +  ASSERT_TRUE(raw_exception != NULL);
   1.810 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
   1.811 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
   1.812 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
   1.813 +            raw_exception->exception_record.exception_address);
   1.814 +
   1.815 +  MinidumpContext *md_context = md_exception->GetContext();
   1.816 +  ASSERT_TRUE(md_context != NULL);
   1.817 +  ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
   1.818 +  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
   1.819 +  ASSERT_TRUE(md_raw_context != NULL);
   1.820 +  ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
   1.821 +            (md_raw_context->context_flags
   1.822 +             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
   1.823 +  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
   1.824 +  EXPECT_EQ(0x382583b9U, raw_context.esi);
   1.825 +  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
   1.826 +  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
   1.827 +  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
   1.828 +  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
   1.829 +  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
   1.830 +  EXPECT_EQ(0x6913f540U, raw_context.eip);
   1.831 +  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
   1.832 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
   1.833 +  EXPECT_EQ(0x659caaa4U, raw_context.esp);
   1.834 +  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
   1.835 +}
   1.836 +
   1.837 +// Testing that the CPU type can be loaded from a system info stream when
   1.838 +// the CPU flags are missing from the context_flags of an exception record
   1.839 +TEST(Dump, OneExceptionX86NoCPUFlags) {
   1.840 +  Dump dump(0, kLittleEndian);
   1.841 +
   1.842 +  MDRawContextX86 raw_context;
   1.843 +  // Intentionally not setting CPU type in the context_flags
   1.844 +  raw_context.context_flags = 0;
   1.845 +  raw_context.edi = 0x3ecba80d;
   1.846 +  raw_context.esi = 0x382583b9;
   1.847 +  raw_context.ebx = 0x7fccc03f;
   1.848 +  raw_context.edx = 0xf62f8ec2;
   1.849 +  raw_context.ecx = 0x46a6a6a8;
   1.850 +  raw_context.eax = 0x6a5025e2;
   1.851 +  raw_context.ebp = 0xd9fabb4a;
   1.852 +  raw_context.eip = 0x6913f540;
   1.853 +  raw_context.cs = 0xbffe6eda;
   1.854 +  raw_context.eflags = 0xb2ce1e2d;
   1.855 +  raw_context.esp = 0x659caaa4;
   1.856 +  raw_context.ss = 0x2e951ef7;
   1.857 +  Context context(dump, raw_context);
   1.858 +
   1.859 +  Exception exception(dump, context,
   1.860 +                      0x1234abcd, // thread id
   1.861 +                      0xdcba4321, // exception code
   1.862 +                      0xf0e0d0c0, // exception flags
   1.863 +                      0x0919a9b9c9d9e9f9ULL); // exception address
   1.864 +  
   1.865 +  dump.Add(&context);
   1.866 +  dump.Add(&exception);
   1.867 +
   1.868 +  // Add system info.  This is needed as an alternative source for CPU type
   1.869 +  // information.  Note, that the CPU flags were intentionally skipped from
   1.870 +  // the context_flags and this alternative source is required.
   1.871 +  String csd_version(dump, "Service Pack 2");
   1.872 +  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
   1.873 +  dump.Add(&system_info);
   1.874 +  dump.Add(&csd_version);
   1.875 +
   1.876 +  dump.Finish();
   1.877 +
   1.878 +  string contents;
   1.879 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.880 +
   1.881 +  istringstream minidump_stream(contents);
   1.882 +  Minidump minidump(minidump_stream);
   1.883 +  ASSERT_TRUE(minidump.Read());
   1.884 +  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
   1.885 +
   1.886 +  MinidumpException *md_exception = minidump.GetException();
   1.887 +  ASSERT_TRUE(md_exception != NULL);
   1.888 +
   1.889 +  uint32_t thread_id;
   1.890 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
   1.891 +  ASSERT_EQ(0x1234abcdU, thread_id);
   1.892 +
   1.893 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
   1.894 +  ASSERT_TRUE(raw_exception != NULL);
   1.895 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
   1.896 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
   1.897 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
   1.898 +            raw_exception->exception_record.exception_address);
   1.899 +
   1.900 +  MinidumpContext *md_context = md_exception->GetContext();
   1.901 +  ASSERT_TRUE(md_context != NULL);
   1.902 +
   1.903 +  ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
   1.904 +  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
   1.905 +  ASSERT_TRUE(md_raw_context != NULL);
   1.906 +
   1.907 +  // Even though the CPU flags were missing from the context_flags, the
   1.908 +  // GetContext call above is expected to load the missing CPU flags from the
   1.909 +  // system info stream and set the CPU type bits in context_flags.
   1.910 +  ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags);
   1.911 +
   1.912 +  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
   1.913 +  EXPECT_EQ(0x382583b9U, raw_context.esi);
   1.914 +  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
   1.915 +  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
   1.916 +  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
   1.917 +  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
   1.918 +  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
   1.919 +  EXPECT_EQ(0x6913f540U, raw_context.eip);
   1.920 +  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
   1.921 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
   1.922 +  EXPECT_EQ(0x659caaa4U, raw_context.esp);
   1.923 +  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
   1.924 +}
   1.925 +
   1.926 +// This test covers a scenario where a dump contains an exception but the
   1.927 +// context record of the exception is missing the CPU type information in its
   1.928 +// context_flags.  The dump has no system info stream so it is imposible to
   1.929 +// deduce the CPU type, hence the context record is unusable.
   1.930 +TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) {
   1.931 +  Dump dump(0, kLittleEndian);
   1.932 +
   1.933 +  MDRawContextX86 raw_context;
   1.934 +  // Intentionally not setting CPU type in the context_flags
   1.935 +  raw_context.context_flags = 0;
   1.936 +  raw_context.edi = 0x3ecba80d;
   1.937 +  raw_context.esi = 0x382583b9;
   1.938 +  raw_context.ebx = 0x7fccc03f;
   1.939 +  raw_context.edx = 0xf62f8ec2;
   1.940 +  raw_context.ecx = 0x46a6a6a8;
   1.941 +  raw_context.eax = 0x6a5025e2;
   1.942 +  raw_context.ebp = 0xd9fabb4a;
   1.943 +  raw_context.eip = 0x6913f540;
   1.944 +  raw_context.cs = 0xbffe6eda;
   1.945 +  raw_context.eflags = 0xb2ce1e2d;
   1.946 +  raw_context.esp = 0x659caaa4;
   1.947 +  raw_context.ss = 0x2e951ef7;
   1.948 +  Context context(dump, raw_context);
   1.949 +
   1.950 +  Exception exception(dump, context,
   1.951 +                      0x1234abcd, // thread id
   1.952 +                      0xdcba4321, // exception code
   1.953 +                      0xf0e0d0c0, // exception flags
   1.954 +                      0x0919a9b9c9d9e9f9ULL); // exception address
   1.955 +  
   1.956 +  dump.Add(&context);
   1.957 +  dump.Add(&exception);
   1.958 +  dump.Finish();
   1.959 +
   1.960 +  string contents;
   1.961 +  ASSERT_TRUE(dump.GetContents(&contents));
   1.962 +
   1.963 +  istringstream minidump_stream(contents);
   1.964 +  Minidump minidump(minidump_stream);
   1.965 +  ASSERT_TRUE(minidump.Read());
   1.966 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
   1.967 +
   1.968 +  MinidumpException *md_exception = minidump.GetException();
   1.969 +  ASSERT_TRUE(md_exception != NULL);
   1.970 +
   1.971 +  uint32_t thread_id;
   1.972 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
   1.973 +  ASSERT_EQ(0x1234abcdU, thread_id);
   1.974 +
   1.975 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
   1.976 +  ASSERT_TRUE(raw_exception != NULL);
   1.977 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
   1.978 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
   1.979 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
   1.980 +            raw_exception->exception_record.exception_address);
   1.981 +
   1.982 +  // The context record of the exception is unusable because the context_flags
   1.983 +  // don't have CPU type information and at the same time the minidump lacks
   1.984 +  // system info stream so it is impossible to deduce the CPU type.
   1.985 +  MinidumpContext *md_context = md_exception->GetContext();
   1.986 +  ASSERT_EQ(NULL, md_context);
   1.987 +}
   1.988 +
   1.989 +TEST(Dump, OneExceptionARM) {
   1.990 +  Dump dump(0, kLittleEndian);
   1.991 +
   1.992 +  MDRawContextARM raw_context;
   1.993 +  raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
   1.994 +  raw_context.iregs[0] = 0x3ecba80d;
   1.995 +  raw_context.iregs[1] = 0x382583b9;
   1.996 +  raw_context.iregs[2] = 0x7fccc03f;
   1.997 +  raw_context.iregs[3] = 0xf62f8ec2;
   1.998 +  raw_context.iregs[4] = 0x46a6a6a8;
   1.999 +  raw_context.iregs[5] = 0x6a5025e2;
  1.1000 +  raw_context.iregs[6] = 0xd9fabb4a;
  1.1001 +  raw_context.iregs[7] = 0x6913f540;
  1.1002 +  raw_context.iregs[8] = 0xbffe6eda;
  1.1003 +  raw_context.iregs[9] = 0xb2ce1e2d;
  1.1004 +  raw_context.iregs[10] = 0x659caaa4;
  1.1005 +  raw_context.iregs[11] = 0xf0e0d0c0;
  1.1006 +  raw_context.iregs[12] = 0xa9b8c7d6;
  1.1007 +  raw_context.iregs[13] = 0x12345678;
  1.1008 +  raw_context.iregs[14] = 0xabcd1234;
  1.1009 +  raw_context.iregs[15] = 0x10203040;
  1.1010 +  raw_context.cpsr = 0x2e951ef7;
  1.1011 +  Context context(dump, raw_context);
  1.1012 +
  1.1013 +  Exception exception(dump, context,
  1.1014 +                      0x1234abcd, // thread id
  1.1015 +                      0xdcba4321, // exception code
  1.1016 +                      0xf0e0d0c0, // exception flags
  1.1017 +                      0x0919a9b9c9d9e9f9ULL); // exception address
  1.1018 +  
  1.1019 +  dump.Add(&context);
  1.1020 +  dump.Add(&exception);
  1.1021 +  dump.Finish();
  1.1022 +
  1.1023 +  string contents;
  1.1024 +  ASSERT_TRUE(dump.GetContents(&contents));
  1.1025 +
  1.1026 +  istringstream minidump_stream(contents);
  1.1027 +  Minidump minidump(minidump_stream);
  1.1028 +  ASSERT_TRUE(minidump.Read());
  1.1029 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  1.1030 +
  1.1031 +  MinidumpException *md_exception = minidump.GetException();
  1.1032 +  ASSERT_TRUE(md_exception != NULL);
  1.1033 +
  1.1034 +  uint32_t thread_id;
  1.1035 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  1.1036 +  ASSERT_EQ(0x1234abcdU, thread_id);
  1.1037 +
  1.1038 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
  1.1039 +  ASSERT_TRUE(raw_exception != NULL);
  1.1040 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  1.1041 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  1.1042 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  1.1043 +            raw_exception->exception_record.exception_address);
  1.1044 +
  1.1045 +  MinidumpContext *md_context = md_exception->GetContext();
  1.1046 +  ASSERT_TRUE(md_context != NULL);
  1.1047 +  ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
  1.1048 +  const MDRawContextARM *md_raw_context = md_context->GetContextARM();
  1.1049 +  ASSERT_TRUE(md_raw_context != NULL);
  1.1050 +  ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
  1.1051 +            (md_raw_context->context_flags
  1.1052 +             & MD_CONTEXT_ARM_INTEGER));
  1.1053 +  EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
  1.1054 +  EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
  1.1055 +  EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
  1.1056 +  EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
  1.1057 +  EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
  1.1058 +  EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
  1.1059 +  EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
  1.1060 +  EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
  1.1061 +  EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
  1.1062 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
  1.1063 +  EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
  1.1064 +  EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
  1.1065 +  EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
  1.1066 +  EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
  1.1067 +  EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
  1.1068 +  EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
  1.1069 +  EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
  1.1070 +}
  1.1071 +
  1.1072 +TEST(Dump, OneExceptionARMOldFlags) {
  1.1073 +  Dump dump(0, kLittleEndian);
  1.1074 +
  1.1075 +  MDRawContextARM raw_context;
  1.1076 +  // MD_CONTEXT_ARM_INTEGER, but with _OLD
  1.1077 +  raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
  1.1078 +  raw_context.iregs[0] = 0x3ecba80d;
  1.1079 +  raw_context.iregs[1] = 0x382583b9;
  1.1080 +  raw_context.iregs[2] = 0x7fccc03f;
  1.1081 +  raw_context.iregs[3] = 0xf62f8ec2;
  1.1082 +  raw_context.iregs[4] = 0x46a6a6a8;
  1.1083 +  raw_context.iregs[5] = 0x6a5025e2;
  1.1084 +  raw_context.iregs[6] = 0xd9fabb4a;
  1.1085 +  raw_context.iregs[7] = 0x6913f540;
  1.1086 +  raw_context.iregs[8] = 0xbffe6eda;
  1.1087 +  raw_context.iregs[9] = 0xb2ce1e2d;
  1.1088 +  raw_context.iregs[10] = 0x659caaa4;
  1.1089 +  raw_context.iregs[11] = 0xf0e0d0c0;
  1.1090 +  raw_context.iregs[12] = 0xa9b8c7d6;
  1.1091 +  raw_context.iregs[13] = 0x12345678;
  1.1092 +  raw_context.iregs[14] = 0xabcd1234;
  1.1093 +  raw_context.iregs[15] = 0x10203040;
  1.1094 +  raw_context.cpsr = 0x2e951ef7;
  1.1095 +  Context context(dump, raw_context);
  1.1096 +
  1.1097 +  Exception exception(dump, context,
  1.1098 +                      0x1234abcd, // thread id
  1.1099 +                      0xdcba4321, // exception code
  1.1100 +                      0xf0e0d0c0, // exception flags
  1.1101 +                      0x0919a9b9c9d9e9f9ULL); // exception address
  1.1102 +  
  1.1103 +  dump.Add(&context);
  1.1104 +  dump.Add(&exception);
  1.1105 +  dump.Finish();
  1.1106 +
  1.1107 +  string contents;
  1.1108 +  ASSERT_TRUE(dump.GetContents(&contents));
  1.1109 +
  1.1110 +  istringstream minidump_stream(contents);
  1.1111 +  Minidump minidump(minidump_stream);
  1.1112 +  ASSERT_TRUE(minidump.Read());
  1.1113 +  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  1.1114 +
  1.1115 +  MinidumpException *md_exception = minidump.GetException();
  1.1116 +  ASSERT_TRUE(md_exception != NULL);
  1.1117 +
  1.1118 +  uint32_t thread_id;
  1.1119 +  ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  1.1120 +  ASSERT_EQ(0x1234abcdU, thread_id);
  1.1121 +
  1.1122 +  const MDRawExceptionStream* raw_exception = md_exception->exception();
  1.1123 +  ASSERT_TRUE(raw_exception != NULL);
  1.1124 +  EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  1.1125 +  EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  1.1126 +  EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  1.1127 +            raw_exception->exception_record.exception_address);
  1.1128 +
  1.1129 +  MinidumpContext *md_context = md_exception->GetContext();
  1.1130 +  ASSERT_TRUE(md_context != NULL);
  1.1131 +  ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
  1.1132 +  const MDRawContextARM *md_raw_context = md_context->GetContextARM();
  1.1133 +  ASSERT_TRUE(md_raw_context != NULL);
  1.1134 +  ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
  1.1135 +            (md_raw_context->context_flags
  1.1136 +             & MD_CONTEXT_ARM_INTEGER));
  1.1137 +  EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
  1.1138 +  EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
  1.1139 +  EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
  1.1140 +  EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
  1.1141 +  EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
  1.1142 +  EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
  1.1143 +  EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
  1.1144 +  EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
  1.1145 +  EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
  1.1146 +  EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
  1.1147 +  EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
  1.1148 +  EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
  1.1149 +  EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
  1.1150 +  EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
  1.1151 +  EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
  1.1152 +  EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
  1.1153 +  EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
  1.1154 +}
  1.1155 +
  1.1156 +}  // namespace

mercurial