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