minidump_unittest.cc revision 9244496c6f875ef1f7166d65f218d57ae92cabaa
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#include "breakpad_googletest_includes.h" 40#include "google_breakpad/common/minidump_format.h" 41#include "google_breakpad/processor/minidump.h" 42#include "processor/logging.h" 43#include "processor/synth_minidump.h" 44 45namespace { 46 47using google_breakpad::Minidump; 48using google_breakpad::MinidumpContext; 49using google_breakpad::MinidumpMemoryList; 50using google_breakpad::MinidumpMemoryRegion; 51using google_breakpad::MinidumpModule; 52using google_breakpad::MinidumpModuleList; 53using google_breakpad::MinidumpSystemInfo; 54using google_breakpad::MinidumpThread; 55using google_breakpad::MinidumpThreadList; 56using google_breakpad::SynthMinidump::Context; 57using google_breakpad::SynthMinidump::Dump; 58using google_breakpad::SynthMinidump::Memory; 59using google_breakpad::SynthMinidump::Module; 60using google_breakpad::SynthMinidump::Stream; 61using google_breakpad::SynthMinidump::String; 62using google_breakpad::SynthMinidump::SystemInfo; 63using google_breakpad::SynthMinidump::Thread; 64using google_breakpad::TestAssembler::kBigEndian; 65using google_breakpad::TestAssembler::kLittleEndian; 66using std::ifstream; 67using std::istringstream; 68using std::string; 69using std::vector; 70using ::testing::Return; 71 72class MinidumpTest : public ::testing::Test { 73public: 74 void SetUp() { 75 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + 76 "/src/processor/testdata/minidump2.dmp"; 77 } 78 string minidump_file_; 79}; 80 81TEST_F(MinidumpTest, TestMinidumpFromFile) { 82 Minidump minidump(minidump_file_); 83 ASSERT_EQ(minidump.path(), minidump_file_); 84 ASSERT_TRUE(minidump.Read()); 85 const MDRawHeader* header = minidump.header(); 86 ASSERT_NE(header, (MDRawHeader*)NULL); 87 ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE)); 88 //TODO: add more checks here 89} 90 91TEST_F(MinidumpTest, TestMinidumpFromStream) { 92 // read minidump contents into memory, construct a stringstream around them 93 ifstream file_stream(minidump_file_.c_str(), std::ios::in); 94 ASSERT_TRUE(file_stream.good()); 95 vector<char> bytes; 96 file_stream.seekg(0, std::ios_base::end); 97 ASSERT_TRUE(file_stream.good()); 98 bytes.resize(file_stream.tellg()); 99 file_stream.seekg(0, std::ios_base::beg); 100 ASSERT_TRUE(file_stream.good()); 101 file_stream.read(&bytes[0], bytes.size()); 102 ASSERT_TRUE(file_stream.good()); 103 string str(&bytes[0], bytes.size()); 104 istringstream stream(str); 105 ASSERT_TRUE(stream.good()); 106 107 // now read minidump from stringstream 108 Minidump minidump(stream); 109 ASSERT_EQ(minidump.path(), ""); 110 ASSERT_TRUE(minidump.Read()); 111 const MDRawHeader* header = minidump.header(); 112 ASSERT_NE(header, (MDRawHeader*)NULL); 113 ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE)); 114 //TODO: add more checks here 115} 116 117TEST(Dump, ReadBackEmpty) { 118 Dump dump(0); 119 dump.Finish(); 120 string contents; 121 ASSERT_TRUE(dump.GetContents(&contents)); 122 istringstream stream(contents); 123 Minidump minidump(stream); 124 ASSERT_TRUE(minidump.Read()); 125 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); 126} 127 128TEST(Dump, ReadBackEmptyBigEndian) { 129 Dump big_minidump(0, kBigEndian); 130 big_minidump.Finish(); 131 string contents; 132 ASSERT_TRUE(big_minidump.GetContents(&contents)); 133 istringstream stream(contents); 134 Minidump minidump(stream); 135 ASSERT_TRUE(minidump.Read()); 136 ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); 137} 138 139TEST(Dump, OneStream) { 140 Dump dump(0, kBigEndian); 141 Stream stream(dump, 0xfbb7fa2bU); 142 stream.Append("stream contents"); 143 dump.Add(&stream); 144 dump.Finish(); 145 146 string contents; 147 ASSERT_TRUE(dump.GetContents(&contents)); 148 istringstream minidump_stream(contents); 149 Minidump minidump(minidump_stream); 150 ASSERT_TRUE(minidump.Read()); 151 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 152 153 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); 154 ASSERT_TRUE(dir != NULL); 155 EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); 156 157 u_int32_t stream_length; 158 ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length)); 159 ASSERT_EQ(15U, stream_length); 160 char stream_contents[15]; 161 ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents))); 162 EXPECT_EQ(string("stream contents"), 163 string(stream_contents, sizeof(stream_contents))); 164 165 EXPECT_FALSE(minidump.GetThreadList()); 166 EXPECT_FALSE(minidump.GetModuleList()); 167 EXPECT_FALSE(minidump.GetMemoryList()); 168 EXPECT_FALSE(minidump.GetException()); 169 EXPECT_FALSE(minidump.GetAssertion()); 170 EXPECT_FALSE(minidump.GetSystemInfo()); 171 EXPECT_FALSE(minidump.GetMiscInfo()); 172 EXPECT_FALSE(minidump.GetBreakpadInfo()); 173} 174 175TEST(Dump, OneMemory) { 176 Dump dump(0, kBigEndian); 177 Memory memory(dump, 0x309d68010bd21b2cULL); 178 memory.Append("memory contents"); 179 dump.Add(&memory); 180 dump.Finish(); 181 182 string contents; 183 ASSERT_TRUE(dump.GetContents(&contents)); 184 istringstream minidump_stream(contents); 185 Minidump minidump(minidump_stream); 186 ASSERT_TRUE(minidump.Read()); 187 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 188 189 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); 190 ASSERT_TRUE(dir != NULL); 191 EXPECT_EQ((u_int32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); 192 193 MinidumpMemoryList *memory_list = minidump.GetMemoryList(); 194 ASSERT_TRUE(memory_list != NULL); 195 ASSERT_EQ(1U, memory_list->region_count()); 196 197 MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0); 198 ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase()); 199 ASSERT_EQ(15U, region1->GetSize()); 200 const u_int8_t *region1_bytes = region1->GetMemory(); 201 ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0); 202} 203 204// One thread --- and its requisite entourage. 205TEST(Dump, OneThread) { 206 Dump dump(0, kLittleEndian); 207 Memory stack(dump, 0x2326a0fa); 208 stack.Append("stack for thread"); 209 210 MDRawContextX86 raw_context; 211 raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; 212 raw_context.edi = 0x3ecba80d; 213 raw_context.esi = 0x382583b9; 214 raw_context.ebx = 0x7fccc03f; 215 raw_context.edx = 0xf62f8ec2; 216 raw_context.ecx = 0x46a6a6a8; 217 raw_context.eax = 0x6a5025e2; 218 raw_context.ebp = 0xd9fabb4a; 219 raw_context.eip = 0x6913f540; 220 raw_context.cs = 0xbffe6eda; 221 raw_context.eflags = 0xb2ce1e2d; 222 raw_context.esp = 0x659caaa4; 223 raw_context.ss = 0x2e951ef7; 224 Context context(dump, raw_context); 225 226 Thread thread(dump, 0xa898f11b, stack, context, 227 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); 228 229 dump.Add(&stack); 230 dump.Add(&context); 231 dump.Add(&thread); 232 dump.Finish(); 233 234 string contents; 235 ASSERT_TRUE(dump.GetContents(&contents)); 236 237 istringstream minidump_stream(contents); 238 Minidump minidump(minidump_stream); 239 ASSERT_TRUE(minidump.Read()); 240 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); 241 242 MinidumpMemoryList *md_memory_list = minidump.GetMemoryList(); 243 ASSERT_TRUE(md_memory_list != NULL); 244 ASSERT_EQ(1U, md_memory_list->region_count()); 245 246 MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0); 247 ASSERT_EQ(0x2326a0faU, md_region->GetBase()); 248 ASSERT_EQ(16U, md_region->GetSize()); 249 const u_int8_t *region_bytes = md_region->GetMemory(); 250 ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); 251 252 MinidumpThreadList *thread_list = minidump.GetThreadList(); 253 ASSERT_TRUE(thread_list != NULL); 254 ASSERT_EQ(1U, thread_list->thread_count()); 255 256 MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0); 257 ASSERT_TRUE(md_thread != NULL); 258 u_int32_t thread_id; 259 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); 260 ASSERT_EQ(0xa898f11bU, thread_id); 261 MinidumpMemoryRegion *md_stack = md_thread->GetMemory(); 262 ASSERT_TRUE(md_stack != NULL); 263 ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); 264 ASSERT_EQ(16U, md_stack->GetSize()); 265 const u_int8_t *md_stack_bytes = md_stack->GetMemory(); 266 ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); 267 268 MinidumpContext *md_context = md_thread->GetContext(); 269 ASSERT_TRUE(md_context != NULL); 270 ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); 271 const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); 272 ASSERT_TRUE(md_raw_context != NULL); 273 ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), 274 (md_raw_context->context_flags 275 & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); 276 EXPECT_EQ(0x3ecba80dU, raw_context.edi); 277 EXPECT_EQ(0x382583b9U, raw_context.esi); 278 EXPECT_EQ(0x7fccc03fU, raw_context.ebx); 279 EXPECT_EQ(0xf62f8ec2U, raw_context.edx); 280 EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); 281 EXPECT_EQ(0x6a5025e2U, raw_context.eax); 282 EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); 283 EXPECT_EQ(0x6913f540U, raw_context.eip); 284 EXPECT_EQ(0xbffe6edaU, raw_context.cs); 285 EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); 286 EXPECT_EQ(0x659caaa4U, raw_context.esp); 287 EXPECT_EQ(0x2e951ef7U, raw_context.ss); 288} 289 290TEST(Dump, OneModule) { 291 static const MDVSFixedFileInfo fixed_file_info = { 292 0xb2fba33a, // signature 293 0x33d7a728, // struct_version 294 0x31afcb20, // file_version_hi 295 0xe51cdab1, // file_version_lo 296 0xd1ea6907, // product_version_hi 297 0x03032857, // product_version_lo 298 0x11bf71d7, // file_flags_mask 299 0x5fb8cdbf, // file_flags 300 0xe45d0d5d, // file_os 301 0x107d9562, // file_type 302 0x5a8844d4, // file_subtype 303 0xa8d30b20, // file_date_hi 304 0x651c3e4e // file_date_lo 305 }; 306 307 Dump dump(0, kBigEndian); 308 String module_name(dump, "single module"); 309 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, 310 module_name, 311 0xb1054d2a, 312 0x34571371, 313 fixed_file_info, // from synth_minidump_unittest_data.h 314 NULL, NULL); 315 316 dump.Add(&module); 317 dump.Add(&module_name); 318 dump.Finish(); 319 320 string contents; 321 ASSERT_TRUE(dump.GetContents(&contents)); 322 istringstream minidump_stream(contents); 323 Minidump minidump(minidump_stream); 324 ASSERT_TRUE(minidump.Read()); 325 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 326 327 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); 328 ASSERT_TRUE(dir != NULL); 329 EXPECT_EQ((u_int32_t) MD_MODULE_LIST_STREAM, dir->stream_type); 330 331 MinidumpModuleList *md_module_list = minidump.GetModuleList(); 332 ASSERT_TRUE(md_module_list != NULL); 333 ASSERT_EQ(1U, md_module_list->module_count()); 334 335 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); 336 ASSERT_TRUE(md_module != NULL); 337 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); 338 ASSERT_EQ(0xada542bd, md_module->size()); 339 ASSERT_EQ("single module", md_module->code_file()); 340 341 const MDRawModule *md_raw_module = md_module->module(); 342 ASSERT_TRUE(md_raw_module != NULL); 343 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); 344 ASSERT_EQ(0x34571371U, md_raw_module->checksum); 345 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, 346 sizeof(fixed_file_info)) == 0); 347} 348 349TEST(Dump, OneSystemInfo) { 350 Dump dump(0, kLittleEndian); 351 String csd_version(dump, "Petulant Pierogi"); 352 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 353 354 dump.Add(&system_info); 355 dump.Add(&csd_version); 356 dump.Finish(); 357 358 string contents; 359 ASSERT_TRUE(dump.GetContents(&contents)); 360 istringstream minidump_stream(contents); 361 Minidump minidump(minidump_stream); 362 ASSERT_TRUE(minidump.Read()); 363 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); 364 365 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); 366 ASSERT_TRUE(dir != NULL); 367 EXPECT_EQ((u_int32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); 368 369 MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo(); 370 ASSERT_TRUE(md_system_info != NULL); 371 ASSERT_EQ("windows", md_system_info->GetOS()); 372 ASSERT_EQ("x86", md_system_info->GetCPU()); 373 ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); 374 ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor()); 375} 376 377TEST(Dump, BigDump) { 378 Dump dump(0, kLittleEndian); 379 380 // A SystemInfo stream. 381 String csd_version(dump, "Munificent Macaque"); 382 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); 383 dump.Add(&csd_version); 384 dump.Add(&system_info); 385 386 // Five threads! 387 Memory stack0(dump, 0x70b9ebfc); 388 stack0.Append("stack for thread zero"); 389 MDRawContextX86 raw_context0; 390 raw_context0.context_flags = MD_CONTEXT_X86_INTEGER; 391 raw_context0.eip = 0xaf0709e4; 392 Context context0(dump, raw_context0); 393 Thread thread0(dump, 0xbbef4432, stack0, context0, 394 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL); 395 dump.Add(&stack0); 396 dump.Add(&context0); 397 dump.Add(&thread0); 398 399 Memory stack1(dump, 0xf988cc45); 400 stack1.Append("stack for thread one"); 401 MDRawContextX86 raw_context1; 402 raw_context1.context_flags = MD_CONTEXT_X86_INTEGER; 403 raw_context1.eip = 0xe4f56f81; 404 Context context1(dump, raw_context1); 405 Thread thread1(dump, 0x657c3f58, stack1, context1, 406 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL); 407 dump.Add(&stack1); 408 dump.Add(&context1); 409 dump.Add(&thread1); 410 411 Memory stack2(dump, 0xc8a92e7c); 412 stack2.Append("stack for thread two"); 413 MDRawContextX86 raw_context2; 414 raw_context2.context_flags = MD_CONTEXT_X86_INTEGER; 415 raw_context2.eip = 0xb336a438; 416 Context context2(dump, raw_context2); 417 Thread thread2(dump, 0xdf4b8a71, stack2, context2, 418 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL); 419 dump.Add(&stack2); 420 dump.Add(&context2); 421 dump.Add(&thread2); 422 423 Memory stack3(dump, 0x36d08e08); 424 stack3.Append("stack for thread three"); 425 MDRawContextX86 raw_context3; 426 raw_context3.context_flags = MD_CONTEXT_X86_INTEGER; 427 raw_context3.eip = 0xdf99a60c; 428 Context context3(dump, raw_context3); 429 Thread thread3(dump, 0x86e6c341, stack3, context3, 430 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL); 431 dump.Add(&stack3); 432 dump.Add(&context3); 433 dump.Add(&thread3); 434 435 Memory stack4(dump, 0x1e0ab4fa); 436 stack4.Append("stack for thread four"); 437 MDRawContextX86 raw_context4; 438 raw_context4.context_flags = MD_CONTEXT_X86_INTEGER; 439 raw_context4.eip = 0xaa646267; 440 Context context4(dump, raw_context4); 441 Thread thread4(dump, 0x261a28d4, stack4, context4, 442 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL); 443 dump.Add(&stack4); 444 dump.Add(&context4); 445 dump.Add(&thread4); 446 447 // Three modules! 448 String module1_name(dump, "module one"); 449 Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name); 450 dump.Add(&module1_name); 451 dump.Add(&module1); 452 453 String module2_name(dump, "module two"); 454 Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name); 455 dump.Add(&module2_name); 456 dump.Add(&module2); 457 458 String module3_name(dump, "module three"); 459 Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name); 460 dump.Add(&module3_name); 461 dump.Add(&module3); 462 463 // Add one more memory region, on top of the five stacks. 464 Memory memory5(dump, 0x61979e828040e564ULL); 465 memory5.Append("contents of memory 5"); 466 dump.Add(&memory5); 467 468 dump.Finish(); 469 470 string contents; 471 ASSERT_TRUE(dump.GetContents(&contents)); 472 istringstream minidump_stream(contents); 473 Minidump minidump(minidump_stream); 474 ASSERT_TRUE(minidump.Read()); 475 ASSERT_EQ(4U, minidump.GetDirectoryEntryCount()); 476 477 // Check the threads. 478 MinidumpThreadList *thread_list = minidump.GetThreadList(); 479 ASSERT_TRUE(thread_list != NULL); 480 ASSERT_EQ(5U, thread_list->thread_count()); 481 u_int32_t thread_id; 482 ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); 483 ASSERT_EQ(0xbbef4432U, thread_id); 484 ASSERT_EQ(0x70b9ebfcU, 485 thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase()); 486 ASSERT_EQ(0xaf0709e4U, 487 thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86() 488 ->eip); 489 490 ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id)); 491 ASSERT_EQ(0x657c3f58U, thread_id); 492 ASSERT_EQ(0xf988cc45U, 493 thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase()); 494 ASSERT_EQ(0xe4f56f81U, 495 thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86() 496 ->eip); 497 498 ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id)); 499 ASSERT_EQ(0xdf4b8a71U, thread_id); 500 ASSERT_EQ(0xc8a92e7cU, 501 thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase()); 502 ASSERT_EQ(0xb336a438U, 503 thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86() 504 ->eip); 505 506 ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id)); 507 ASSERT_EQ(0x86e6c341U, thread_id); 508 ASSERT_EQ(0x36d08e08U, 509 thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase()); 510 ASSERT_EQ(0xdf99a60cU, 511 thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86() 512 ->eip); 513 514 ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id)); 515 ASSERT_EQ(0x261a28d4U, thread_id); 516 ASSERT_EQ(0x1e0ab4faU, 517 thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase()); 518 ASSERT_EQ(0xaa646267U, 519 thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86() 520 ->eip); 521 522 // Check the modules. 523 MinidumpModuleList *md_module_list = minidump.GetModuleList(); 524 ASSERT_TRUE(md_module_list != NULL); 525 ASSERT_EQ(3U, md_module_list->module_count()); 526 EXPECT_EQ(0xeb77da57b5d4cbdaULL, 527 md_module_list->GetModuleAtIndex(0)->base_address()); 528 EXPECT_EQ(0x8675884adfe5ac90ULL, 529 md_module_list->GetModuleAtIndex(1)->base_address()); 530 EXPECT_EQ(0x95fc1544da321b6cULL, 531 md_module_list->GetModuleAtIndex(2)->base_address()); 532} 533 534} // namespace 535