minidump_unittest.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // Unit test for Minidump. Uses a pre-generated minidump and 30 // verifies that certain streams are correct. 31 32 #ifdef HAVE_CONFIG_H 33 #include <config.h> // Must come first 34 #endif 35 36 #include <iostream> 37 #include <fstream> 38 #include <sstream> 39 #include <stdlib.h> 40 #include <string> 41 #include <vector> 42 43 #include "breakpad_googletest_includes.h" 44 #include "common/using_std_string.h" 45 #include "google_breakpad/common/minidump_format.h" 46 #include "google_breakpad/processor/minidump.h" 47 #include "processor/logging.h" 48 #include "processor/synth_minidump.h" 49 50 namespace { 51 52 using google_breakpad::Minidump; 53 using google_breakpad::MinidumpContext; 54 using google_breakpad::MinidumpCrashpadInfo; 55 using google_breakpad::MinidumpException; 56 using google_breakpad::MinidumpMemoryInfo; 57 using google_breakpad::MinidumpMemoryInfoList; 58 using google_breakpad::MinidumpMemoryList; 59 using google_breakpad::MinidumpMemoryRegion; 60 using google_breakpad::MinidumpModule; 61 using google_breakpad::MinidumpModuleList; 62 using google_breakpad::MinidumpSystemInfo; 63 using google_breakpad::MinidumpUnloadedModule; 64 using google_breakpad::MinidumpUnloadedModuleList; 65 using google_breakpad::MinidumpThread; 66 using google_breakpad::MinidumpThreadList; 67 using google_breakpad::SynthMinidump::Context; 68 using google_breakpad::SynthMinidump::Dump; 69 using google_breakpad::SynthMinidump::Exception; 70 using google_breakpad::SynthMinidump::Memory; 71 using google_breakpad::SynthMinidump::Module; 72 using google_breakpad::SynthMinidump::UnloadedModule; 73 using google_breakpad::SynthMinidump::Section; 74 using google_breakpad::SynthMinidump::Stream; 75 using google_breakpad::SynthMinidump::String; 76 using google_breakpad::SynthMinidump::SystemInfo; 77 using google_breakpad::SynthMinidump::Thread; 78 using google_breakpad::test_assembler::kBigEndian; 79 using google_breakpad::test_assembler::kLittleEndian; 80 using std::ifstream; 81 using std::istringstream; 82 using std::vector; 83 using ::testing::Return; 84 85 class MinidumpTest : public ::testing::Test { 86 public: 87 void SetUp() { 88 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + 89 "/src/processor/testdata/minidump2.dmp"; 90 } 91 string minidump_file_; 92 }; 93 94 TEST_F(MinidumpTest, TestMinidumpFromFile) { 95 Minidump minidump(minidump_file_); 96 ASSERT_EQ(minidump.path(), minidump_file_); 97 ASSERT_TRUE(minidump.Read()); 98 const MDRawHeader* header = minidump.header(); 99 ASSERT_NE(header, (MDRawHeader*)NULL); 100 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); 101 102 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 103 ASSERT_TRUE(md_module_list != NULL); 104 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); 105 ASSERT_TRUE(md_module != NULL); 106 ASSERT_EQ("c:\\test_app.exe", md_module->code_file()); 107 ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file()); 108 ASSERT_EQ("45D35F6C2d000", md_module->code_identifier()); 109 ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier()); 110 } 111 112 TEST_F(MinidumpTest, TestMinidumpFromStream) { 113 // read minidump contents into memory, construct a stringstream around them 114 ifstream file_stream(minidump_file_.c_str(), std::ios::in); 115 ASSERT_TRUE(file_stream.good()); 116 vector<char> bytes; 117 file_stream.seekg(0, std::ios_base::end); 118 ASSERT_TRUE(file_stream.good()); 119 bytes.resize(file_stream.tellg()); 120 file_stream.seekg(0, std::ios_base::beg); 121 ASSERT_TRUE(file_stream.good()); 122 file_stream.read(&bytes[0], bytes.size()); 123 ASSERT_TRUE(file_stream.good()); 124 string str(&bytes[0], bytes.size()); 125 istringstream stream(str); 126 ASSERT_TRUE(stream.good()); 127 128 // now read minidump from stringstream 129 Minidump minidump(stream); 130 ASSERT_EQ(minidump.path(), ""); 131 ASSERT_TRUE(minidump.Read()); 132 const MDRawHeader* header = minidump.header(); 133 ASSERT_NE(header, (MDRawHeader*)NULL); 134 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); 135 //TODO: add more checks here 136 } 137 138 TEST_F(MinidumpTest, TestMinidumpWithCrashpadAnnotations) { 139 string crashpad_minidump_file = 140 string(getenv("srcdir") ? getenv("srcdir") : ".") + 141 "/src/processor/testdata/minidump_crashpad_annotation.dmp"; 142 143 Minidump minidump(crashpad_minidump_file); 144 ASSERT_EQ(minidump.path(), crashpad_minidump_file); 145 ASSERT_TRUE(minidump.Read()); 146 147 MinidumpCrashpadInfo* crashpad_info = minidump.GetCrashpadInfo(); 148 ASSERT_TRUE(crashpad_info != NULL); 149 150 const std::vector<std::vector<MinidumpCrashpadInfo::AnnotationObject>>* 151 annotation_objects_list = 152 crashpad_info->GetModuleCrashpadInfoAnnotationObjects(); 153 ASSERT_EQ(2U, annotation_objects_list->size()); 154 155 std::vector<MinidumpCrashpadInfo::AnnotationObject> annotation_objects = 156 annotation_objects_list->at(0); 157 ASSERT_EQ(5U, annotation_objects.size()); 158 159 std::vector<std::string> annotation_names; 160 for (size_t i = 0; i < annotation_objects.size(); i++) { 161 MinidumpCrashpadInfo::AnnotationObject annotation_object = 162 annotation_objects.at(i); 163 annotation_names.push_back(annotation_object.name); 164 ASSERT_TRUE(annotation_object.type > 0); 165 ASSERT_TRUE(annotation_object.value.size() > 0); 166 } 167 168 std::vector<std::string> expected_strings{ 169 "exceptionReason", "exceptionName", "firstexception_bt", "firstexception", 170 "CounterAnnotation"}; 171 ASSERT_EQ(annotation_names, expected_strings); 172 } 173 174 TEST(Dump, ReadBackEmpty) { 175 Dump dump(0); 176 dump.Finish(); 177 string contents; 178 ASSERT_TRUE(dump.GetContents(&contents)); 179 istringstream stream(contents); 180 Minidump minidump(stream); 181 ASSERT_TRUE(minidump.Read()); 182 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); 183 } 184 185 TEST(Dump, ReadBackEmptyBigEndian) { 186 Dump big_minidump(0, kBigEndian); 187 big_minidump.Finish(); 188 string contents; 189 ASSERT_TRUE(big_minidump.GetContents(&contents)); 190 istringstream stream(contents); 191 Minidump minidump(stream); 192 ASSERT_TRUE(minidump.Read()); 193 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); 194 } 195 196 TEST(Dump, OneStream) { 197 Dump dump(0, kBigEndian); 198 Stream stream(dump, 0xfbb7fa2bU); 199 stream.Append("stream contents"); 200 dump.Add(&stream); 201 dump.Finish(); 202 203 string contents; 204 ASSERT_TRUE(dump.GetContents(&contents)); 205 istringstream minidump_stream(contents); 206 Minidump minidump(minidump_stream); 207 ASSERT_TRUE(minidump.Read()); 208 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 209 210 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); 211 ASSERT_TRUE(dir != NULL); 212 EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); 213 214 uint32_t stream_length; 215 ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length)); 216 ASSERT_EQ(15U, stream_length); 217 char stream_contents[15]; 218 ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents))); 219 EXPECT_EQ(string("stream contents"), 220 string(stream_contents, sizeof(stream_contents))); 221 222 EXPECT_FALSE(minidump.GetThreadList()); 223 EXPECT_FALSE(minidump.GetModuleList()); 224 EXPECT_FALSE(minidump.GetMemoryList()); 225 EXPECT_FALSE(minidump.GetException()); 226 EXPECT_FALSE(minidump.GetAssertion()); 227 EXPECT_FALSE(minidump.GetSystemInfo()); 228 EXPECT_FALSE(minidump.GetMiscInfo()); 229 EXPECT_FALSE(minidump.GetBreakpadInfo()); 230 } 231 232 TEST(Dump, OneMemory) { 233 Dump dump(0, kBigEndian); 234 Memory memory(dump, 0x309d68010bd21b2cULL); 235 memory.Append("memory contents"); 236 dump.Add(&memory); 237 dump.Finish(); 238 239 string contents; 240 ASSERT_TRUE(dump.GetContents(&contents)); 241 istringstream minidump_stream(contents); 242 Minidump minidump(minidump_stream); 243 ASSERT_TRUE(minidump.Read()); 244 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 245 246 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); 247 ASSERT_TRUE(dir != NULL); 248 EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); 249 250 MinidumpMemoryList* memory_list = minidump.GetMemoryList(); 251 ASSERT_TRUE(memory_list != NULL); 252 ASSERT_EQ(1U, memory_list->region_count()); 253 254 MinidumpMemoryRegion* region1 = memory_list->GetMemoryRegionAtIndex(0); 255 ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase()); 256 ASSERT_EQ(15U, region1->GetSize()); 257 const uint8_t* region1_bytes = region1->GetMemory(); 258 ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0); 259 } 260 261 // One thread --- and its requisite entourage. 262 TEST(Dump, OneThread) { 263 Dump dump(0, kLittleEndian); 264 Memory stack(dump, 0x2326a0fa); 265 stack.Append("stack for thread"); 266 267 MDRawContextX86 raw_context; 268 const uint32_t kExpectedEIP = 0x6913f540; 269 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; 270 raw_context.edi = 0x3ecba80d; 271 raw_context.esi = 0x382583b9; 272 raw_context.ebx = 0x7fccc03f; 273 raw_context.edx = 0xf62f8ec2; 274 raw_context.ecx = 0x46a6a6a8; 275 raw_context.eax = 0x6a5025e2; 276 raw_context.ebp = 0xd9fabb4a; 277 raw_context.eip = kExpectedEIP; 278 raw_context.cs = 0xbffe6eda; 279 raw_context.eflags = 0xb2ce1e2d; 280 raw_context.esp = 0x659caaa4; 281 raw_context.ss = 0x2e951ef7; 282 Context context(dump, raw_context); 283 284 Thread thread(dump, 0xa898f11b, stack, context, 285 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); 286 287 dump.Add(&stack); 288 dump.Add(&context); 289 dump.Add(&thread); 290 dump.Finish(); 291 292 string contents; 293 ASSERT_TRUE(dump.GetContents(&contents)); 294 295 istringstream minidump_stream(contents); 296 Minidump minidump(minidump_stream); 297 ASSERT_TRUE(minidump.Read()); 298 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 299 300 MinidumpMemoryList* md_memory_list = minidump.GetMemoryList(); 301 ASSERT_TRUE(md_memory_list != NULL); 302 ASSERT_EQ(1U, md_memory_list->region_count()); 303 304 MinidumpMemoryRegion* md_region = md_memory_list->GetMemoryRegionAtIndex(0); 305 ASSERT_EQ(0x2326a0faU, md_region->GetBase()); 306 ASSERT_EQ(16U, md_region->GetSize()); 307 const uint8_t* region_bytes = md_region->GetMemory(); 308 ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); 309 310 MinidumpThreadList* thread_list = minidump.GetThreadList(); 311 ASSERT_TRUE(thread_list != NULL); 312 ASSERT_EQ(1U, thread_list->thread_count()); 313 314 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); 315 ASSERT_TRUE(md_thread != NULL); 316 uint32_t thread_id; 317 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); 318 ASSERT_EQ(0xa898f11bU, thread_id); 319 MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); 320 ASSERT_TRUE(md_stack != NULL); 321 ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); 322 ASSERT_EQ(16U, md_stack->GetSize()); 323 const uint8_t* md_stack_bytes = md_stack->GetMemory(); 324 ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); 325 326 MinidumpContext* md_context = md_thread->GetContext(); 327 ASSERT_TRUE(md_context != NULL); 328 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); 329 330 uint64_t eip; 331 ASSERT_TRUE(md_context->GetInstructionPointer(&eip)); 332 EXPECT_EQ(kExpectedEIP, eip); 333 334 const MDRawContextX86* md_raw_context = md_context->GetContextX86(); 335 ASSERT_TRUE(md_raw_context != NULL); 336 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), 337 (md_raw_context->context_flags 338 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); 339 EXPECT_EQ(0x3ecba80dU, raw_context.edi); 340 EXPECT_EQ(0x382583b9U, raw_context.esi); 341 EXPECT_EQ(0x7fccc03fU, raw_context.ebx); 342 EXPECT_EQ(0xf62f8ec2U, raw_context.edx); 343 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); 344 EXPECT_EQ(0x6a5025e2U, raw_context.eax); 345 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); 346 EXPECT_EQ(kExpectedEIP, raw_context.eip); 347 EXPECT_EQ(0xbffe6edaU, raw_context.cs); 348 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); 349 EXPECT_EQ(0x659caaa4U, raw_context.esp); 350 EXPECT_EQ(0x2e951ef7U, raw_context.ss); 351 } 352 353 TEST(Dump, ThreadMissingMemory) { 354 Dump dump(0, kLittleEndian); 355 Memory stack(dump, 0x2326a0fa); 356 // Stack has no contents. 357 358 MDRawContextX86 raw_context; 359 memset(&raw_context, 0, sizeof(raw_context)); 360 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; 361 Context context(dump, raw_context); 362 363 Thread thread(dump, 0xa898f11b, stack, context, 364 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); 365 366 dump.Add(&stack); 367 dump.Add(&context); 368 dump.Add(&thread); 369 dump.Finish(); 370 371 string contents; 372 ASSERT_TRUE(dump.GetContents(&contents)); 373 374 istringstream minidump_stream(contents); 375 Minidump minidump(minidump_stream); 376 ASSERT_TRUE(minidump.Read()); 377 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 378 379 // This should succeed even though the thread has no stack memory. 380 MinidumpThreadList* thread_list = minidump.GetThreadList(); 381 ASSERT_TRUE(thread_list != NULL); 382 ASSERT_EQ(1U, thread_list->thread_count()); 383 384 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); 385 ASSERT_TRUE(md_thread != NULL); 386 387 uint32_t thread_id; 388 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); 389 ASSERT_EQ(0xa898f11bU, thread_id); 390 391 MinidumpContext* md_context = md_thread->GetContext(); 392 ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context); 393 394 MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); 395 ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); 396 } 397 398 TEST(Dump, ThreadMissingContext) { 399 Dump dump(0, kLittleEndian); 400 Memory stack(dump, 0x2326a0fa); 401 stack.Append("stack for thread"); 402 403 // Context is empty. 404 Context context(dump); 405 406 Thread thread(dump, 0xa898f11b, stack, context, 407 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); 408 409 dump.Add(&stack); 410 dump.Add(&context); 411 dump.Add(&thread); 412 dump.Finish(); 413 414 string contents; 415 ASSERT_TRUE(dump.GetContents(&contents)); 416 417 istringstream minidump_stream(contents); 418 Minidump minidump(minidump_stream); 419 ASSERT_TRUE(minidump.Read()); 420 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 421 422 // This should succeed even though the thread has no stack memory. 423 MinidumpThreadList* thread_list = minidump.GetThreadList(); 424 ASSERT_TRUE(thread_list != NULL); 425 ASSERT_EQ(1U, thread_list->thread_count()); 426 427 MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); 428 ASSERT_TRUE(md_thread != NULL); 429 430 uint32_t thread_id; 431 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); 432 ASSERT_EQ(0xa898f11bU, thread_id); 433 MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); 434 ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); 435 436 MinidumpContext* md_context = md_thread->GetContext(); 437 ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context); 438 } 439 440 TEST(Dump, OneUnloadedModule) { 441 Dump dump(0, kBigEndian); 442 String module_name(dump, "unloaded module"); 443 444 String csd_version(dump, "Windows 9000"); 445 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 446 447 UnloadedModule unloaded_module( 448 dump, 449 0xa90206ca83eb2852ULL, 450 0xada542bd, 451 module_name, 452 0x34571371, 453 0xb1054d2a); 454 455 dump.Add(&unloaded_module); 456 dump.Add(&module_name); 457 dump.Add(&system_info); 458 dump.Add(&csd_version); 459 dump.Finish(); 460 461 string contents; 462 ASSERT_TRUE(dump.GetContents(&contents)); 463 istringstream minidump_stream(contents); 464 Minidump minidump(minidump_stream); 465 ASSERT_TRUE(minidump.Read()); 466 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 467 468 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1); 469 ASSERT_TRUE(dir != NULL); 470 EXPECT_EQ((uint32_t) MD_UNLOADED_MODULE_LIST_STREAM, dir->stream_type); 471 472 MinidumpUnloadedModuleList* md_unloaded_module_list = 473 minidump.GetUnloadedModuleList(); 474 ASSERT_TRUE(md_unloaded_module_list != NULL); 475 ASSERT_EQ(1U, md_unloaded_module_list->module_count()); 476 477 const MinidumpUnloadedModule* md_unloaded_module = 478 md_unloaded_module_list->GetModuleAtIndex(0); 479 ASSERT_TRUE(md_unloaded_module != NULL); 480 ASSERT_EQ(0xa90206ca83eb2852ULL, md_unloaded_module->base_address()); 481 ASSERT_EQ(0xada542bd, md_unloaded_module->size()); 482 ASSERT_EQ("unloaded module", md_unloaded_module->code_file()); 483 ASSERT_EQ("", md_unloaded_module->debug_file()); 484 // time_date_stamp and size_of_image concatenated 485 ASSERT_EQ("B1054D2Aada542bd", md_unloaded_module->code_identifier()); 486 ASSERT_EQ("", md_unloaded_module->debug_identifier()); 487 488 const MDRawUnloadedModule* md_raw_unloaded_module = 489 md_unloaded_module->module(); 490 ASSERT_TRUE(md_raw_unloaded_module != NULL); 491 ASSERT_EQ(0xb1054d2aU, md_raw_unloaded_module->time_date_stamp); 492 ASSERT_EQ(0x34571371U, md_raw_unloaded_module->checksum); 493 } 494 495 static const MDVSFixedFileInfo fixed_file_info = { 496 0xb2fba33a, // signature 497 0x33d7a728, // struct_version 498 0x31afcb20, // file_version_hi 499 0xe51cdab1, // file_version_lo 500 0xd1ea6907, // product_version_hi 501 0x03032857, // product_version_lo 502 0x11bf71d7, // file_flags_mask 503 0x5fb8cdbf, // file_flags 504 0xe45d0d5d, // file_os 505 0x107d9562, // file_type 506 0x5a8844d4, // file_subtype 507 0xa8d30b20, // file_date_hi 508 0x651c3e4e // file_date_lo 509 }; 510 511 TEST(Dump, OneModule) { 512 Dump dump(0, kBigEndian); 513 String module_name(dump, "single module"); 514 Section cv_info(dump); 515 cv_info 516 .D32(MD_CVINFOPDB70_SIGNATURE) // signature 517 // signature, a MDGUID 518 .D32(0xabcd1234) 519 .D16(0xf00d) 520 .D16(0xbeef) 521 .Append("\x01\x02\x03\x04\x05\x06\x07\x08") 522 .D32(1) // age 523 .AppendCString("c:\\foo\\file.pdb"); // pdb_file_name 524 525 String csd_version(dump, "Windows 9000"); 526 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 527 528 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, 529 module_name, 530 0xb1054d2a, 531 0x34571371, 532 fixed_file_info, // from synth_minidump_unittest_data.h 533 &cv_info, nullptr); 534 535 dump.Add(&module); 536 dump.Add(&module_name); 537 dump.Add(&cv_info); 538 dump.Add(&system_info); 539 dump.Add(&csd_version); 540 dump.Finish(); 541 542 string contents; 543 ASSERT_TRUE(dump.GetContents(&contents)); 544 istringstream minidump_stream(contents); 545 Minidump minidump(minidump_stream); 546 ASSERT_TRUE(minidump.Read()); 547 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 548 549 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1); 550 ASSERT_TRUE(dir != NULL); 551 EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); 552 553 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 554 ASSERT_TRUE(md_module_list != NULL); 555 ASSERT_EQ(1U, md_module_list->module_count()); 556 557 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); 558 ASSERT_TRUE(md_module != NULL); 559 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); 560 ASSERT_EQ(0xada542bd, md_module->size()); 561 ASSERT_EQ("single module", md_module->code_file()); 562 ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file()); 563 // time_date_stamp and size_of_image concatenated 564 ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier()); 565 ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier()); 566 567 const MDRawModule* md_raw_module = md_module->module(); 568 ASSERT_TRUE(md_raw_module != NULL); 569 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); 570 ASSERT_EQ(0x34571371U, md_raw_module->checksum); 571 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, 572 sizeof(fixed_file_info)) == 0); 573 } 574 575 // Test that a module with a MDCVInfoELF CV record is handled properly. 576 TEST(Dump, OneModuleCVELF) { 577 Dump dump(0, kLittleEndian); 578 String module_name(dump, "elf module"); 579 Section cv_info(dump); 580 cv_info 581 .D32(MD_CVINFOELF_SIGNATURE) // signature 582 // build_id 583 .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf" 584 "\x37\x38\xce\xa3\x4a\x87"); 585 586 const MDRawSystemInfo linux_x86 = { 587 MD_CPU_ARCHITECTURE_X86, // processor_architecture 588 6, // processor_level 589 0xd08, // processor_revision 590 1, // number_of_processors 591 0, // product_type 592 0, // major_version 593 0, // minor_version 594 0, // build_number 595 MD_OS_LINUX, // platform_id 596 0xdeadbeef, // csd_version_rva 597 0x100, // suite_mask 598 0, // reserved2 599 { // cpu 600 { // x86_cpu_info 601 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id 602 0x6d8, // version_information 603 0xafe9fbff, // feature_information 604 0xffffffff // amd_extended_cpu_features 605 } 606 } 607 }; 608 String csd_version(dump, "Literally Linux"); 609 SystemInfo system_info(dump, linux_x86, csd_version); 610 611 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, 612 module_name, 613 0xb1054d2a, 614 0x34571371, 615 fixed_file_info, // from synth_minidump_unittest_data.h 616 &cv_info, nullptr); 617 618 dump.Add(&module); 619 dump.Add(&module_name); 620 dump.Add(&cv_info); 621 dump.Add(&system_info); 622 dump.Add(&csd_version); 623 dump.Finish(); 624 625 string contents; 626 ASSERT_TRUE(dump.GetContents(&contents)); 627 istringstream minidump_stream(contents); 628 Minidump minidump(minidump_stream); 629 ASSERT_TRUE(minidump.Read()); 630 631 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 632 ASSERT_TRUE(md_module_list != NULL); 633 ASSERT_EQ(1U, md_module_list->module_count()); 634 635 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); 636 ASSERT_TRUE(md_module != NULL); 637 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); 638 ASSERT_EQ(0xada542bd, md_module->size()); 639 ASSERT_EQ("elf module", md_module->code_file()); 640 // debug_file == code_file 641 ASSERT_EQ("elf module", md_module->debug_file()); 642 // just the build_id, directly 643 ASSERT_EQ("5fa9cdb41053df1b86fab733b4df3738cea34a87", 644 md_module->code_identifier()); 645 // build_id truncted to GUID length and treated as such, with zero 646 // age appended 647 ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); 648 649 const MDRawModule* md_raw_module = md_module->module(); 650 ASSERT_TRUE(md_raw_module != NULL); 651 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); 652 ASSERT_EQ(0x34571371U, md_raw_module->checksum); 653 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, 654 sizeof(fixed_file_info)) == 0); 655 } 656 657 // Test that a build_id that's shorter than a GUID is handled properly. 658 TEST(Dump, CVELFShort) { 659 Dump dump(0, kLittleEndian); 660 String module_name(dump, "elf module"); 661 Section cv_info(dump); 662 cv_info 663 .D32(MD_CVINFOELF_SIGNATURE) // signature 664 // build_id, shorter than a GUID 665 .Append("\x5f\xa9\xcd\xb4"); 666 667 const MDRawSystemInfo linux_x86 = { 668 MD_CPU_ARCHITECTURE_X86, // processor_architecture 669 6, // processor_level 670 0xd08, // processor_revision 671 1, // number_of_processors 672 0, // product_type 673 0, // major_version 674 0, // minor_version 675 0, // build_number 676 MD_OS_LINUX, // platform_id 677 0xdeadbeef, // csd_version_rva 678 0x100, // suite_mask 679 0, // reserved2 680 { // cpu 681 { // x86_cpu_info 682 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id 683 0x6d8, // version_information 684 0xafe9fbff, // feature_information 685 0xffffffff // amd_extended_cpu_features 686 } 687 } 688 }; 689 String csd_version(dump, "Literally Linux"); 690 SystemInfo system_info(dump, linux_x86, csd_version); 691 692 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, 693 module_name, 694 0xb1054d2a, 695 0x34571371, 696 fixed_file_info, // from synth_minidump_unittest_data.h 697 &cv_info, nullptr); 698 699 dump.Add(&module); 700 dump.Add(&module_name); 701 dump.Add(&cv_info); 702 dump.Add(&system_info); 703 dump.Add(&csd_version); 704 dump.Finish(); 705 706 string contents; 707 ASSERT_TRUE(dump.GetContents(&contents)); 708 istringstream minidump_stream(contents); 709 Minidump minidump(minidump_stream); 710 ASSERT_TRUE(minidump.Read()); 711 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 712 713 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 714 ASSERT_TRUE(md_module_list != NULL); 715 ASSERT_EQ(1U, md_module_list->module_count()); 716 717 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); 718 ASSERT_TRUE(md_module != NULL); 719 // just the build_id, directly 720 ASSERT_EQ("5fa9cdb4", md_module->code_identifier()); 721 // build_id expanded to GUID length and treated as such, with zero 722 // age appended 723 ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier()); 724 } 725 726 // Test that a build_id that's very long is handled properly. 727 TEST(Dump, CVELFLong) { 728 Dump dump(0, kLittleEndian); 729 String module_name(dump, "elf module"); 730 Section cv_info(dump); 731 cv_info 732 .D32(MD_CVINFOELF_SIGNATURE) // signature 733 // build_id, lots of bytes 734 .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf" 735 "\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08" 736 "\x09\x0a\x0b\x0c\x0d\x0e\x0f"); 737 738 739 const MDRawSystemInfo linux_x86 = { 740 MD_CPU_ARCHITECTURE_X86, // processor_architecture 741 6, // processor_level 742 0xd08, // processor_revision 743 1, // number_of_processors 744 0, // product_type 745 0, // major_version 746 0, // minor_version 747 0, // build_number 748 MD_OS_LINUX, // platform_id 749 0xdeadbeef, // csd_version_rva 750 0x100, // suite_mask 751 0, // reserved2 752 { // cpu 753 { // x86_cpu_info 754 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id 755 0x6d8, // version_information 756 0xafe9fbff, // feature_information 757 0xffffffff // amd_extended_cpu_features 758 } 759 } 760 }; 761 String csd_version(dump, "Literally Linux"); 762 SystemInfo system_info(dump, linux_x86, csd_version); 763 764 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, 765 module_name, 766 0xb1054d2a, 767 0x34571371, 768 fixed_file_info, // from synth_minidump_unittest_data.h 769 &cv_info, nullptr); 770 771 dump.Add(&module); 772 dump.Add(&module_name); 773 dump.Add(&cv_info); 774 dump.Add(&system_info); 775 dump.Add(&csd_version); 776 dump.Finish(); 777 778 string contents; 779 ASSERT_TRUE(dump.GetContents(&contents)); 780 istringstream minidump_stream(contents); 781 Minidump minidump(minidump_stream); 782 ASSERT_TRUE(minidump.Read()); 783 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 784 785 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 786 ASSERT_TRUE(md_module_list != NULL); 787 ASSERT_EQ(1U, md_module_list->module_count()); 788 789 const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); 790 ASSERT_TRUE(md_module != NULL); 791 // just the build_id, directly 792 ASSERT_EQ( 793 "5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f", 794 md_module->code_identifier()); 795 // build_id truncated to GUID length and treated as such, with zero 796 // age appended. 797 ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); 798 } 799 800 TEST(Dump, OneSystemInfo) { 801 Dump dump(0, kLittleEndian); 802 String csd_version(dump, "Petulant Pierogi"); 803 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 804 805 dump.Add(&system_info); 806 dump.Add(&csd_version); 807 dump.Finish(); 808 809 string contents; 810 ASSERT_TRUE(dump.GetContents(&contents)); 811 istringstream minidump_stream(contents); 812 Minidump minidump(minidump_stream); 813 ASSERT_TRUE(minidump.Read()); 814 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 815 816 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); 817 ASSERT_TRUE(dir != NULL); 818 EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); 819 820 MinidumpSystemInfo* md_system_info = minidump.GetSystemInfo(); 821 ASSERT_TRUE(md_system_info != NULL); 822 ASSERT_EQ("windows", md_system_info->GetOS()); 823 ASSERT_EQ("x86", md_system_info->GetCPU()); 824 ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); 825 ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor()); 826 } 827 828 TEST(Dump, BigDump) { 829 Dump dump(0, kLittleEndian); 830 831 // A SystemInfo stream. 832 String csd_version(dump, "Munificent Macaque"); 833 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 834 dump.Add(&csd_version); 835 dump.Add(&system_info); 836 837 // Five threads! 838 Memory stack0(dump, 0x70b9ebfc); 839 stack0.Append("stack for thread zero"); 840 MDRawContextX86 raw_context0; 841 raw_context0.context_flags = MD_CONTEXT_X86_INTEGER; 842 raw_context0.eip = 0xaf0709e4; 843 Context context0(dump, raw_context0); 844 Thread thread0(dump, 0xbbef4432, stack0, context0, 845 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL); 846 dump.Add(&stack0); 847 dump.Add(&context0); 848 dump.Add(&thread0); 849 850 Memory stack1(dump, 0xf988cc45); 851 stack1.Append("stack for thread one"); 852 MDRawContextX86 raw_context1; 853 raw_context1.context_flags = MD_CONTEXT_X86_INTEGER; 854 raw_context1.eip = 0xe4f56f81; 855 Context context1(dump, raw_context1); 856 Thread thread1(dump, 0x657c3f58, stack1, context1, 857 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL); 858 dump.Add(&stack1); 859 dump.Add(&context1); 860 dump.Add(&thread1); 861 862 Memory stack2(dump, 0xc8a92e7c); 863 stack2.Append("stack for thread two"); 864 MDRawContextX86 raw_context2; 865 raw_context2.context_flags = MD_CONTEXT_X86_INTEGER; 866 raw_context2.eip = 0xb336a438; 867 Context context2(dump, raw_context2); 868 Thread thread2(dump, 0xdf4b8a71, stack2, context2, 869 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL); 870 dump.Add(&stack2); 871 dump.Add(&context2); 872 dump.Add(&thread2); 873 874 Memory stack3(dump, 0x36d08e08); 875 stack3.Append("stack for thread three"); 876 MDRawContextX86 raw_context3; 877 raw_context3.context_flags = MD_CONTEXT_X86_INTEGER; 878 raw_context3.eip = 0xdf99a60c; 879 Context context3(dump, raw_context3); 880 Thread thread3(dump, 0x86e6c341, stack3, context3, 881 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL); 882 dump.Add(&stack3); 883 dump.Add(&context3); 884 dump.Add(&thread3); 885 886 Memory stack4(dump, 0x1e0ab4fa); 887 stack4.Append("stack for thread four"); 888 MDRawContextX86 raw_context4; 889 raw_context4.context_flags = MD_CONTEXT_X86_INTEGER; 890 raw_context4.eip = 0xaa646267; 891 Context context4(dump, raw_context4); 892 Thread thread4(dump, 0x261a28d4, stack4, context4, 893 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL); 894 dump.Add(&stack4); 895 dump.Add(&context4); 896 dump.Add(&thread4); 897 898 // Three modules! 899 String module1_name(dump, "module one"); 900 Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name); 901 dump.Add(&module1_name); 902 dump.Add(&module1); 903 904 String module2_name(dump, "module two"); 905 Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name); 906 dump.Add(&module2_name); 907 dump.Add(&module2); 908 909 String module3_name(dump, "module three"); 910 Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name); 911 dump.Add(&module3_name); 912 dump.Add(&module3); 913 914 // Unloaded modules! 915 uint64_t umodule1_base = 0xeb77da57b5d4cbdaULL; 916 uint32_t umodule1_size = 0x83cd5a37; 917 String umodule1_name(dump, "unloaded module one"); 918 UnloadedModule unloaded_module1(dump, umodule1_base, umodule1_size, 919 umodule1_name); 920 dump.Add(&umodule1_name); 921 dump.Add(&unloaded_module1); 922 923 uint64_t umodule2_base = 0xeb77da57b5d4cbdaULL; 924 uint32_t umodule2_size = 0x83cd5a37; 925 String umodule2_name(dump, "unloaded module two"); 926 UnloadedModule unloaded_module2(dump, umodule2_base, umodule2_size, 927 umodule2_name); 928 dump.Add(&umodule2_name); 929 dump.Add(&unloaded_module2); 930 931 uint64_t umodule3_base = 0xeb77da5839a20000ULL; 932 uint32_t umodule3_size = 0x83cd5a37; 933 String umodule3_name(dump, "unloaded module three"); 934 UnloadedModule unloaded_module3(dump, umodule3_base, umodule3_size, 935 umodule3_name); 936 dump.Add(&umodule3_name); 937 dump.Add(&unloaded_module3); 938 939 940 // Add one more memory region, on top of the five stacks. 941 Memory memory5(dump, 0x61979e828040e564ULL); 942 memory5.Append("contents of memory 5"); 943 dump.Add(&memory5); 944 945 dump.Finish(); 946 947 string contents; 948 ASSERT_TRUE(dump.GetContents(&contents)); 949 istringstream minidump_stream(contents); 950 Minidump minidump(minidump_stream); 951 ASSERT_TRUE(minidump.Read()); 952 ASSERT_EQ(5U, minidump.GetDirectoryEntryCount()); 953 954 // Check the threads. 955 MinidumpThreadList* thread_list = minidump.GetThreadList(); 956 ASSERT_TRUE(thread_list != NULL); 957 ASSERT_EQ(5U, thread_list->thread_count()); 958 uint32_t thread_id; 959 ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); 960 ASSERT_EQ(0xbbef4432U, thread_id); 961 ASSERT_EQ(0x70b9ebfcU, 962 thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase()); 963 ASSERT_EQ(0xaf0709e4U, 964 thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86() 965 ->eip); 966 967 ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id)); 968 ASSERT_EQ(0x657c3f58U, thread_id); 969 ASSERT_EQ(0xf988cc45U, 970 thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase()); 971 ASSERT_EQ(0xe4f56f81U, 972 thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86() 973 ->eip); 974 975 ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id)); 976 ASSERT_EQ(0xdf4b8a71U, thread_id); 977 ASSERT_EQ(0xc8a92e7cU, 978 thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase()); 979 ASSERT_EQ(0xb336a438U, 980 thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86() 981 ->eip); 982 983 ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id)); 984 ASSERT_EQ(0x86e6c341U, thread_id); 985 ASSERT_EQ(0x36d08e08U, 986 thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase()); 987 ASSERT_EQ(0xdf99a60cU, 988 thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86() 989 ->eip); 990 991 ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id)); 992 ASSERT_EQ(0x261a28d4U, thread_id); 993 ASSERT_EQ(0x1e0ab4faU, 994 thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase()); 995 ASSERT_EQ(0xaa646267U, 996 thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86() 997 ->eip); 998 999 // Check the modules. 1000 MinidumpModuleList* md_module_list = minidump.GetModuleList(); 1001 ASSERT_TRUE(md_module_list != NULL); 1002 ASSERT_EQ(3U, md_module_list->module_count()); 1003 EXPECT_EQ(0xeb77da57b5d4cbdaULL, 1004 md_module_list->GetModuleAtIndex(0)->base_address()); 1005 EXPECT_EQ(0x8675884adfe5ac90ULL, 1006 md_module_list->GetModuleAtIndex(1)->base_address()); 1007 EXPECT_EQ(0x95fc1544da321b6cULL, 1008 md_module_list->GetModuleAtIndex(2)->base_address()); 1009 1010 // Check unloaded modules 1011 MinidumpUnloadedModuleList* md_unloaded_module_list = 1012 minidump.GetUnloadedModuleList(); 1013 ASSERT_TRUE(md_unloaded_module_list != NULL); 1014 ASSERT_EQ(3U, md_unloaded_module_list->module_count()); 1015 EXPECT_EQ(umodule1_base, 1016 md_unloaded_module_list->GetModuleAtIndex(0)->base_address()); 1017 EXPECT_EQ(umodule2_base, 1018 md_unloaded_module_list->GetModuleAtIndex(1)->base_address()); 1019 EXPECT_EQ(umodule3_base, 1020 md_unloaded_module_list->GetModuleAtIndex(2)->base_address()); 1021 1022 const MinidumpUnloadedModule* umodule = 1023 md_unloaded_module_list->GetModuleForAddress( 1024 umodule1_base + umodule1_size / 2); 1025 EXPECT_EQ(umodule1_base, umodule->base_address()); 1026 1027 umodule = md_unloaded_module_list->GetModuleAtSequence(0); 1028 EXPECT_EQ(umodule1_base, umodule->base_address()); 1029 1030 EXPECT_EQ(NULL, md_unloaded_module_list->GetMainModule()); 1031 1032 } 1033 1034 TEST(Dump, OneMemoryInfo) { 1035 Dump dump(0, kBigEndian); 1036 Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM); 1037 1038 // Add the MDRawMemoryInfoList header. 1039 const uint64_t kNumberOfEntries = 1; 1040 stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header 1041 .D32(sizeof(MDRawMemoryInfo)) // size_of_entry 1042 .D64(kNumberOfEntries); // number_of_entries 1043 1044 1045 // Now add a MDRawMemoryInfo entry. 1046 const uint64_t kBaseAddress = 0x1000; 1047 const uint64_t kRegionSize = 0x2000; 1048 stream.D64(kBaseAddress) // base_address 1049 .D64(kBaseAddress) // allocation_base 1050 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection 1051 .D32(0) // __alignment1 1052 .D64(kRegionSize) // region_size 1053 .D32(MD_MEMORY_STATE_COMMIT) // state 1054 .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection 1055 .D32(MD_MEMORY_TYPE_PRIVATE) // type 1056 .D32(0); // __alignment2 1057 1058 dump.Add(&stream); 1059 dump.Finish(); 1060 1061 string contents; 1062 ASSERT_TRUE(dump.GetContents(&contents)); 1063 istringstream minidump_stream(contents); 1064 Minidump minidump(minidump_stream); 1065 ASSERT_TRUE(minidump.Read()); 1066 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1067 1068 const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); 1069 ASSERT_TRUE(dir != NULL); 1070 EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type); 1071 1072 MinidumpMemoryInfoList* info_list = minidump.GetMemoryInfoList(); 1073 ASSERT_TRUE(info_list != NULL); 1074 ASSERT_EQ(1U, info_list->info_count()); 1075 1076 const MinidumpMemoryInfo* info1 = info_list->GetMemoryInfoAtIndex(0); 1077 ASSERT_EQ(kBaseAddress, info1->GetBase()); 1078 ASSERT_EQ(kRegionSize, info1->GetSize()); 1079 ASSERT_TRUE(info1->IsExecutable()); 1080 ASSERT_TRUE(info1->IsWritable()); 1081 1082 // Should get back the same memory region here. 1083 const MinidumpMemoryInfo* info2 = 1084 info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2); 1085 ASSERT_EQ(kBaseAddress, info2->GetBase()); 1086 ASSERT_EQ(kRegionSize, info2->GetSize()); 1087 } 1088 1089 TEST(Dump, OneExceptionX86) { 1090 Dump dump(0, kLittleEndian); 1091 1092 MDRawContextX86 raw_context; 1093 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; 1094 raw_context.edi = 0x3ecba80d; 1095 raw_context.esi = 0x382583b9; 1096 raw_context.ebx = 0x7fccc03f; 1097 raw_context.edx = 0xf62f8ec2; 1098 raw_context.ecx = 0x46a6a6a8; 1099 raw_context.eax = 0x6a5025e2; 1100 raw_context.ebp = 0xd9fabb4a; 1101 raw_context.eip = 0x6913f540; 1102 raw_context.cs = 0xbffe6eda; 1103 raw_context.eflags = 0xb2ce1e2d; 1104 raw_context.esp = 0x659caaa4; 1105 raw_context.ss = 0x2e951ef7; 1106 Context context(dump, raw_context); 1107 1108 Exception exception(dump, context, 1109 0x1234abcd, // thread id 1110 0xdcba4321, // exception code 1111 0xf0e0d0c0, // exception flags 1112 0x0919a9b9c9d9e9f9ULL); // exception address 1113 1114 dump.Add(&context); 1115 dump.Add(&exception); 1116 dump.Finish(); 1117 1118 string contents; 1119 ASSERT_TRUE(dump.GetContents(&contents)); 1120 1121 istringstream minidump_stream(contents); 1122 Minidump minidump(minidump_stream); 1123 ASSERT_TRUE(minidump.Read()); 1124 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1125 1126 MinidumpException* md_exception = minidump.GetException(); 1127 ASSERT_TRUE(md_exception != NULL); 1128 1129 uint32_t thread_id; 1130 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1131 ASSERT_EQ(0x1234abcdU, thread_id); 1132 1133 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1134 ASSERT_TRUE(raw_exception != NULL); 1135 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1136 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1137 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1138 raw_exception->exception_record.exception_address); 1139 1140 MinidumpContext* md_context = md_exception->GetContext(); 1141 ASSERT_TRUE(md_context != NULL); 1142 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); 1143 const MDRawContextX86* md_raw_context = md_context->GetContextX86(); 1144 ASSERT_TRUE(md_raw_context != NULL); 1145 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), 1146 (md_raw_context->context_flags 1147 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); 1148 EXPECT_EQ(0x3ecba80dU, raw_context.edi); 1149 EXPECT_EQ(0x382583b9U, raw_context.esi); 1150 EXPECT_EQ(0x7fccc03fU, raw_context.ebx); 1151 EXPECT_EQ(0xf62f8ec2U, raw_context.edx); 1152 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); 1153 EXPECT_EQ(0x6a5025e2U, raw_context.eax); 1154 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); 1155 EXPECT_EQ(0x6913f540U, raw_context.eip); 1156 EXPECT_EQ(0xbffe6edaU, raw_context.cs); 1157 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); 1158 EXPECT_EQ(0x659caaa4U, raw_context.esp); 1159 EXPECT_EQ(0x2e951ef7U, raw_context.ss); 1160 } 1161 1162 TEST(Dump, OneExceptionX86XState) { 1163 Dump dump(0, kLittleEndian); 1164 1165 MDRawContextX86 raw_context; 1166 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | 1167 MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE; 1168 raw_context.edi = 0x3ecba80d; 1169 raw_context.esi = 0x382583b9; 1170 raw_context.ebx = 0x7fccc03f; 1171 raw_context.edx = 0xf62f8ec2; 1172 raw_context.ecx = 0x46a6a6a8; 1173 raw_context.eax = 0x6a5025e2; 1174 raw_context.ebp = 0xd9fabb4a; 1175 raw_context.eip = 0x6913f540; 1176 raw_context.cs = 0xbffe6eda; 1177 raw_context.eflags = 0xb2ce1e2d; 1178 raw_context.esp = 0x659caaa4; 1179 raw_context.ss = 0x2e951ef7; 1180 Context context(dump, raw_context); 1181 1182 Exception exception(dump, context, 1183 0x1234abcd, // thread id 1184 0xdcba4321, // exception code 1185 0xf0e0d0c0, // exception flags 1186 0x0919a9b9c9d9e9f9ULL); // exception address 1187 1188 dump.Add(&context); 1189 dump.Add(&exception); 1190 dump.Finish(); 1191 1192 string contents; 1193 ASSERT_TRUE(dump.GetContents(&contents)); 1194 1195 istringstream minidump_stream(contents); 1196 Minidump minidump(minidump_stream); 1197 ASSERT_TRUE(minidump.Read()); 1198 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1199 1200 MinidumpException* md_exception = minidump.GetException(); 1201 ASSERT_TRUE(md_exception != NULL); 1202 1203 uint32_t thread_id; 1204 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1205 ASSERT_EQ(0x1234abcdU, thread_id); 1206 1207 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1208 ASSERT_TRUE(raw_exception != NULL); 1209 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1210 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1211 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1212 raw_exception->exception_record.exception_address); 1213 1214 MinidumpContext* md_context = md_exception->GetContext(); 1215 ASSERT_TRUE(md_context != NULL); 1216 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); 1217 const MDRawContextX86* md_raw_context = md_context->GetContextX86(); 1218 ASSERT_TRUE(md_raw_context != NULL); 1219 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), 1220 (md_raw_context->context_flags 1221 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); 1222 EXPECT_EQ(0x3ecba80dU, raw_context.edi); 1223 EXPECT_EQ(0x382583b9U, raw_context.esi); 1224 EXPECT_EQ(0x7fccc03fU, raw_context.ebx); 1225 EXPECT_EQ(0xf62f8ec2U, raw_context.edx); 1226 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); 1227 EXPECT_EQ(0x6a5025e2U, raw_context.eax); 1228 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); 1229 EXPECT_EQ(0x6913f540U, raw_context.eip); 1230 EXPECT_EQ(0xbffe6edaU, raw_context.cs); 1231 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); 1232 EXPECT_EQ(0x659caaa4U, raw_context.esp); 1233 EXPECT_EQ(0x2e951ef7U, raw_context.ss); 1234 } 1235 1236 // Testing that the CPU type can be loaded from a system info stream when 1237 // the CPU flags are missing from the context_flags of an exception record 1238 TEST(Dump, OneExceptionX86NoCPUFlags) { 1239 Dump dump(0, kLittleEndian); 1240 1241 MDRawContextX86 raw_context; 1242 // Intentionally not setting CPU type in the context_flags 1243 raw_context.context_flags = 0; 1244 raw_context.edi = 0x3ecba80d; 1245 raw_context.esi = 0x382583b9; 1246 raw_context.ebx = 0x7fccc03f; 1247 raw_context.edx = 0xf62f8ec2; 1248 raw_context.ecx = 0x46a6a6a8; 1249 raw_context.eax = 0x6a5025e2; 1250 raw_context.ebp = 0xd9fabb4a; 1251 raw_context.eip = 0x6913f540; 1252 raw_context.cs = 0xbffe6eda; 1253 raw_context.eflags = 0xb2ce1e2d; 1254 raw_context.esp = 0x659caaa4; 1255 raw_context.ss = 0x2e951ef7; 1256 Context context(dump, raw_context); 1257 1258 Exception exception(dump, context, 1259 0x1234abcd, // thread id 1260 0xdcba4321, // exception code 1261 0xf0e0d0c0, // exception flags 1262 0x0919a9b9c9d9e9f9ULL); // exception address 1263 1264 dump.Add(&context); 1265 dump.Add(&exception); 1266 1267 // Add system info. This is needed as an alternative source for CPU type 1268 // information. Note, that the CPU flags were intentionally skipped from 1269 // the context_flags and this alternative source is required. 1270 String csd_version(dump, "Service Pack 2"); 1271 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 1272 dump.Add(&system_info); 1273 dump.Add(&csd_version); 1274 1275 dump.Finish(); 1276 1277 string contents; 1278 ASSERT_TRUE(dump.GetContents(&contents)); 1279 1280 istringstream minidump_stream(contents); 1281 Minidump minidump(minidump_stream); 1282 ASSERT_TRUE(minidump.Read()); 1283 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 1284 1285 MinidumpException* md_exception = minidump.GetException(); 1286 ASSERT_TRUE(md_exception != NULL); 1287 1288 uint32_t thread_id; 1289 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1290 ASSERT_EQ(0x1234abcdU, thread_id); 1291 1292 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1293 ASSERT_TRUE(raw_exception != NULL); 1294 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1295 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1296 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1297 raw_exception->exception_record.exception_address); 1298 1299 MinidumpContext* md_context = md_exception->GetContext(); 1300 ASSERT_TRUE(md_context != NULL); 1301 1302 ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); 1303 const MDRawContextX86* md_raw_context = md_context->GetContextX86(); 1304 ASSERT_TRUE(md_raw_context != NULL); 1305 1306 // Even though the CPU flags were missing from the context_flags, the 1307 // GetContext call above is expected to load the missing CPU flags from the 1308 // system info stream and set the CPU type bits in context_flags. 1309 ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags); 1310 1311 EXPECT_EQ(0x3ecba80dU, raw_context.edi); 1312 EXPECT_EQ(0x382583b9U, raw_context.esi); 1313 EXPECT_EQ(0x7fccc03fU, raw_context.ebx); 1314 EXPECT_EQ(0xf62f8ec2U, raw_context.edx); 1315 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); 1316 EXPECT_EQ(0x6a5025e2U, raw_context.eax); 1317 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); 1318 EXPECT_EQ(0x6913f540U, raw_context.eip); 1319 EXPECT_EQ(0xbffe6edaU, raw_context.cs); 1320 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); 1321 EXPECT_EQ(0x659caaa4U, raw_context.esp); 1322 EXPECT_EQ(0x2e951ef7U, raw_context.ss); 1323 } 1324 1325 // This test covers a scenario where a dump contains an exception but the 1326 // context record of the exception is missing the CPU type information in its 1327 // context_flags. The dump has no system info stream so it is imposible to 1328 // deduce the CPU type, hence the context record is unusable. 1329 TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) { 1330 Dump dump(0, kLittleEndian); 1331 1332 MDRawContextX86 raw_context; 1333 // Intentionally not setting CPU type in the context_flags 1334 raw_context.context_flags = 0; 1335 raw_context.edi = 0x3ecba80d; 1336 raw_context.esi = 0x382583b9; 1337 raw_context.ebx = 0x7fccc03f; 1338 raw_context.edx = 0xf62f8ec2; 1339 raw_context.ecx = 0x46a6a6a8; 1340 raw_context.eax = 0x6a5025e2; 1341 raw_context.ebp = 0xd9fabb4a; 1342 raw_context.eip = 0x6913f540; 1343 raw_context.cs = 0xbffe6eda; 1344 raw_context.eflags = 0xb2ce1e2d; 1345 raw_context.esp = 0x659caaa4; 1346 raw_context.ss = 0x2e951ef7; 1347 Context context(dump, raw_context); 1348 1349 Exception exception(dump, context, 1350 0x1234abcd, // thread id 1351 0xdcba4321, // exception code 1352 0xf0e0d0c0, // exception flags 1353 0x0919a9b9c9d9e9f9ULL); // exception address 1354 1355 dump.Add(&context); 1356 dump.Add(&exception); 1357 dump.Finish(); 1358 1359 string contents; 1360 ASSERT_TRUE(dump.GetContents(&contents)); 1361 1362 istringstream minidump_stream(contents); 1363 Minidump minidump(minidump_stream); 1364 ASSERT_TRUE(minidump.Read()); 1365 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1366 1367 MinidumpException* md_exception = minidump.GetException(); 1368 ASSERT_TRUE(md_exception != NULL); 1369 1370 uint32_t thread_id; 1371 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1372 ASSERT_EQ(0x1234abcdU, thread_id); 1373 1374 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1375 ASSERT_TRUE(raw_exception != NULL); 1376 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1377 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1378 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1379 raw_exception->exception_record.exception_address); 1380 1381 // The context record of the exception is unusable because the context_flags 1382 // don't have CPU type information and at the same time the minidump lacks 1383 // system info stream so it is impossible to deduce the CPU type. 1384 MinidumpContext* md_context = md_exception->GetContext(); 1385 ASSERT_EQ(NULL, md_context); 1386 } 1387 1388 TEST(Dump, OneExceptionARM) { 1389 Dump dump(0, kLittleEndian); 1390 1391 MDRawContextARM raw_context; 1392 raw_context.context_flags = MD_CONTEXT_ARM_INTEGER; 1393 raw_context.iregs[0] = 0x3ecba80d; 1394 raw_context.iregs[1] = 0x382583b9; 1395 raw_context.iregs[2] = 0x7fccc03f; 1396 raw_context.iregs[3] = 0xf62f8ec2; 1397 raw_context.iregs[4] = 0x46a6a6a8; 1398 raw_context.iregs[5] = 0x6a5025e2; 1399 raw_context.iregs[6] = 0xd9fabb4a; 1400 raw_context.iregs[7] = 0x6913f540; 1401 raw_context.iregs[8] = 0xbffe6eda; 1402 raw_context.iregs[9] = 0xb2ce1e2d; 1403 raw_context.iregs[10] = 0x659caaa4; 1404 raw_context.iregs[11] = 0xf0e0d0c0; 1405 raw_context.iregs[12] = 0xa9b8c7d6; 1406 raw_context.iregs[13] = 0x12345678; 1407 raw_context.iregs[14] = 0xabcd1234; 1408 raw_context.iregs[15] = 0x10203040; 1409 raw_context.cpsr = 0x2e951ef7; 1410 Context context(dump, raw_context); 1411 1412 Exception exception(dump, context, 1413 0x1234abcd, // thread id 1414 0xdcba4321, // exception code 1415 0xf0e0d0c0, // exception flags 1416 0x0919a9b9c9d9e9f9ULL); // exception address 1417 1418 dump.Add(&context); 1419 dump.Add(&exception); 1420 dump.Finish(); 1421 1422 string contents; 1423 ASSERT_TRUE(dump.GetContents(&contents)); 1424 1425 istringstream minidump_stream(contents); 1426 Minidump minidump(minidump_stream); 1427 ASSERT_TRUE(minidump.Read()); 1428 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1429 1430 MinidumpException* md_exception = minidump.GetException(); 1431 ASSERT_TRUE(md_exception != NULL); 1432 1433 uint32_t thread_id; 1434 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1435 ASSERT_EQ(0x1234abcdU, thread_id); 1436 1437 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1438 ASSERT_TRUE(raw_exception != NULL); 1439 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1440 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1441 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1442 raw_exception->exception_record.exception_address); 1443 1444 MinidumpContext* md_context = md_exception->GetContext(); 1445 ASSERT_TRUE(md_context != NULL); 1446 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); 1447 const MDRawContextARM* md_raw_context = md_context->GetContextARM(); 1448 ASSERT_TRUE(md_raw_context != NULL); 1449 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, 1450 (md_raw_context->context_flags 1451 & MD_CONTEXT_ARM_INTEGER)); 1452 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); 1453 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); 1454 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); 1455 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); 1456 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); 1457 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); 1458 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); 1459 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); 1460 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); 1461 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); 1462 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); 1463 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); 1464 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); 1465 EXPECT_EQ(0x12345678U, raw_context.iregs[13]); 1466 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); 1467 EXPECT_EQ(0x10203040U, raw_context.iregs[15]); 1468 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); 1469 } 1470 1471 TEST(Dump, OneExceptionARMOldFlags) { 1472 Dump dump(0, kLittleEndian); 1473 1474 MDRawContextARM raw_context; 1475 // MD_CONTEXT_ARM_INTEGER, but with _OLD 1476 raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002; 1477 raw_context.iregs[0] = 0x3ecba80d; 1478 raw_context.iregs[1] = 0x382583b9; 1479 raw_context.iregs[2] = 0x7fccc03f; 1480 raw_context.iregs[3] = 0xf62f8ec2; 1481 raw_context.iregs[4] = 0x46a6a6a8; 1482 raw_context.iregs[5] = 0x6a5025e2; 1483 raw_context.iregs[6] = 0xd9fabb4a; 1484 raw_context.iregs[7] = 0x6913f540; 1485 raw_context.iregs[8] = 0xbffe6eda; 1486 raw_context.iregs[9] = 0xb2ce1e2d; 1487 raw_context.iregs[10] = 0x659caaa4; 1488 raw_context.iregs[11] = 0xf0e0d0c0; 1489 raw_context.iregs[12] = 0xa9b8c7d6; 1490 raw_context.iregs[13] = 0x12345678; 1491 raw_context.iregs[14] = 0xabcd1234; 1492 raw_context.iregs[15] = 0x10203040; 1493 raw_context.cpsr = 0x2e951ef7; 1494 Context context(dump, raw_context); 1495 1496 Exception exception(dump, context, 1497 0x1234abcd, // thread id 1498 0xdcba4321, // exception code 1499 0xf0e0d0c0, // exception flags 1500 0x0919a9b9c9d9e9f9ULL); // exception address 1501 1502 dump.Add(&context); 1503 dump.Add(&exception); 1504 dump.Finish(); 1505 1506 string contents; 1507 ASSERT_TRUE(dump.GetContents(&contents)); 1508 1509 istringstream minidump_stream(contents); 1510 Minidump minidump(minidump_stream); 1511 ASSERT_TRUE(minidump.Read()); 1512 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1513 1514 MinidumpException* md_exception = minidump.GetException(); 1515 ASSERT_TRUE(md_exception != NULL); 1516 1517 uint32_t thread_id; 1518 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1519 ASSERT_EQ(0x1234abcdU, thread_id); 1520 1521 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1522 ASSERT_TRUE(raw_exception != NULL); 1523 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1524 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1525 EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, 1526 raw_exception->exception_record.exception_address); 1527 1528 MinidumpContext* md_context = md_exception->GetContext(); 1529 ASSERT_TRUE(md_context != NULL); 1530 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); 1531 const MDRawContextARM* md_raw_context = md_context->GetContextARM(); 1532 ASSERT_TRUE(md_raw_context != NULL); 1533 ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, 1534 (md_raw_context->context_flags 1535 & MD_CONTEXT_ARM_INTEGER)); 1536 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); 1537 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); 1538 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); 1539 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); 1540 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); 1541 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); 1542 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); 1543 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); 1544 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); 1545 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); 1546 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); 1547 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); 1548 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); 1549 EXPECT_EQ(0x12345678U, raw_context.iregs[13]); 1550 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); 1551 EXPECT_EQ(0x10203040U, raw_context.iregs[15]); 1552 EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); 1553 } 1554 1555 TEST(Dump, OneExceptionMIPS) { 1556 Dump dump(0, kLittleEndian); 1557 1558 MDRawContextMIPS raw_context; 1559 raw_context.context_flags = MD_CONTEXT_MIPS_INTEGER; 1560 raw_context.iregs[0] = 0x3ecba80d; 1561 raw_context.iregs[1] = 0x382583b9; 1562 raw_context.iregs[2] = 0x7fccc03f; 1563 raw_context.iregs[3] = 0xf62f8ec2; 1564 raw_context.iregs[4] = 0x46a6a6a8; 1565 raw_context.iregs[5] = 0x6a5025e2; 1566 raw_context.iregs[6] = 0xd9fabb4a; 1567 raw_context.iregs[7] = 0x6913f540; 1568 raw_context.iregs[8] = 0xbffe6eda; 1569 raw_context.iregs[9] = 0xb2ce1e2d; 1570 raw_context.iregs[10] = 0x659caaa4; 1571 raw_context.iregs[11] = 0xf0e0d0c0; 1572 raw_context.iregs[12] = 0xa9b8c7d6; 1573 raw_context.iregs[13] = 0x12345678; 1574 raw_context.iregs[14] = 0xabcd1234; 1575 raw_context.iregs[15] = 0x10203040; 1576 raw_context.iregs[16] = 0xa80d3ecb; 1577 raw_context.iregs[17] = 0x83b93825; 1578 raw_context.iregs[18] = 0xc03f7fcc; 1579 raw_context.iregs[19] = 0x8ec2f62f; 1580 raw_context.iregs[20] = 0xa6a846a6; 1581 raw_context.iregs[21] = 0x25e26a50; 1582 raw_context.iregs[22] = 0xbb4ad9fa; 1583 raw_context.iregs[23] = 0xf5406913; 1584 raw_context.iregs[24] = 0x6edabffe; 1585 raw_context.iregs[25] = 0x1e2db2ce; 1586 raw_context.iregs[26] = 0xaaa4659c; 1587 raw_context.iregs[27] = 0xd0c0f0e0; 1588 raw_context.iregs[28] = 0xc7d6a9b8; 1589 raw_context.iregs[29] = 0x56781234; 1590 raw_context.iregs[30] = 0x1234abcd; 1591 raw_context.iregs[31] = 0x30401020; 1592 1593 Context context(dump, raw_context); 1594 1595 Exception exception(dump, context, 1596 0x1234abcd, // Thread id. 1597 0xdcba4321, // Exception code. 1598 0xf0e0d0c0, // Exception flags. 1599 0x0919a9b9); // Exception address. 1600 1601 dump.Add(&context); 1602 dump.Add(&exception); 1603 dump.Finish(); 1604 1605 string contents; 1606 ASSERT_TRUE(dump.GetContents(&contents)); 1607 1608 istringstream minidump_stream(contents); 1609 Minidump minidump(minidump_stream); 1610 ASSERT_TRUE(minidump.Read()); 1611 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 1612 1613 MinidumpException* md_exception = minidump.GetException(); 1614 ASSERT_TRUE(md_exception != NULL); 1615 1616 uint32_t thread_id; 1617 ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); 1618 ASSERT_EQ(0x1234abcdU, thread_id); 1619 1620 const MDRawExceptionStream* raw_exception = md_exception->exception(); 1621 ASSERT_TRUE(raw_exception != NULL); 1622 EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); 1623 EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); 1624 EXPECT_EQ(0x0919a9b9U, 1625 raw_exception->exception_record.exception_address); 1626 1627 MinidumpContext* md_context = md_exception->GetContext(); 1628 ASSERT_TRUE(md_context != NULL); 1629 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU()); 1630 const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS(); 1631 ASSERT_TRUE(md_raw_context != NULL); 1632 ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER, 1633 (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER)); 1634 EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); 1635 EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); 1636 EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); 1637 EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); 1638 EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); 1639 EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); 1640 EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); 1641 EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); 1642 EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); 1643 EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); 1644 EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); 1645 EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); 1646 EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); 1647 EXPECT_EQ(0x12345678U, raw_context.iregs[13]); 1648 EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); 1649 EXPECT_EQ(0x10203040U, raw_context.iregs[15]); 1650 EXPECT_EQ(0xa80d3ecbU, raw_context.iregs[16]); 1651 EXPECT_EQ(0x83b93825U, raw_context.iregs[17]); 1652 EXPECT_EQ(0xc03f7fccU, raw_context.iregs[18]); 1653 EXPECT_EQ(0x8ec2f62fU, raw_context.iregs[19]); 1654 EXPECT_EQ(0xa6a846a6U, raw_context.iregs[20]); 1655 EXPECT_EQ(0x25e26a50U, raw_context.iregs[21]); 1656 EXPECT_EQ(0xbb4ad9faU, raw_context.iregs[22]); 1657 EXPECT_EQ(0xf5406913U, raw_context.iregs[23]); 1658 EXPECT_EQ(0x6edabffeU, raw_context.iregs[24]); 1659 EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]); 1660 EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]); 1661 EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]); 1662 EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]); 1663 EXPECT_EQ(0x56781234U, raw_context.iregs[29]); 1664 EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]); 1665 EXPECT_EQ(0x30401020U, raw_context.iregs[31]); 1666 } 1667 1668 } // namespace