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