1 //===-- MinidumpTypesTest.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Plugins/Process/minidump/MinidumpParser.h" 10 #include "Plugins/Process/minidump/MinidumpTypes.h" 11 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h" 12 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h" 13 #include "TestingSupport/SubsystemRAII.h" 14 #include "TestingSupport/TestUtilities.h" 15 #include "lldb/Host/FileSystem.h" 16 #include "lldb/Target/MemoryRegionInfo.h" 17 #include "lldb/Utility/ArchSpec.h" 18 #include "lldb/Utility/DataBufferHeap.h" 19 #include "lldb/Utility/DataExtractor.h" 20 #include "lldb/Utility/FileSpec.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/Optional.h" 23 #include "llvm/ObjectYAML/yaml2obj.h" 24 #include "llvm/Support/FileSystem.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/Path.h" 27 #include "llvm/Support/YAMLTraits.h" 28 #include "llvm/Testing/Support/Error.h" 29 #include "gtest/gtest.h" 30 31 // C includes 32 33 // C++ includes 34 #include <memory> 35 36 using namespace lldb_private; 37 using namespace minidump; 38 39 class MinidumpParserTest : public testing::Test { 40 public: 41 SubsystemRAII<FileSystem> subsystems; 42 43 void SetUpData(const char *minidump_filename) { 44 std::string filename = GetInputFilePath(minidump_filename); 45 auto BufferPtr = FileSystem::Instance().CreateDataBuffer(filename, -1, 0); 46 ASSERT_NE(BufferPtr, nullptr); 47 llvm::Expected<MinidumpParser> expected_parser = 48 MinidumpParser::Create(BufferPtr); 49 ASSERT_THAT_EXPECTED(expected_parser, llvm::Succeeded()); 50 parser = std::move(*expected_parser); 51 ASSERT_GT(parser->GetData().size(), 0UL); 52 } 53 54 llvm::Error SetUpFromYaml(llvm::StringRef yaml) { 55 std::string data; 56 llvm::raw_string_ostream os(data); 57 llvm::yaml::Input YIn(yaml); 58 if (!llvm::yaml::convertYAML(YIn, os, [](const llvm::Twine &Msg) {})) 59 return llvm::createStringError(llvm::inconvertibleErrorCode(), 60 "convertYAML() failed"); 61 62 os.flush(); 63 auto data_buffer_sp = 64 std::make_shared<DataBufferHeap>(data.data(), data.size()); 65 auto expected_parser = MinidumpParser::Create(std::move(data_buffer_sp)); 66 if (!expected_parser) 67 return expected_parser.takeError(); 68 parser = std::move(*expected_parser); 69 return llvm::Error::success(); 70 } 71 72 llvm::Optional<MinidumpParser> parser; 73 }; 74 75 TEST_F(MinidumpParserTest, InvalidMinidump) { 76 std::string duplicate_streams; 77 llvm::raw_string_ostream os(duplicate_streams); 78 llvm::yaml::Input YIn(R"( 79 --- !minidump 80 Streams: 81 - Type: LinuxAuxv 82 Content: DEADBEEFBAADF00D 83 - Type: LinuxAuxv 84 Content: DEADBEEFBAADF00D 85 )"); 86 87 ASSERT_TRUE(llvm::yaml::convertYAML(YIn, os, [](const llvm::Twine &Msg){})); 88 os.flush(); 89 auto data_buffer_sp = std::make_shared<DataBufferHeap>( 90 duplicate_streams.data(), duplicate_streams.size()); 91 ASSERT_THAT_EXPECTED(MinidumpParser::Create(data_buffer_sp), llvm::Failed()); 92 } 93 94 TEST_F(MinidumpParserTest, GetThreadsAndGetThreadContext) { 95 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 96 --- !minidump 97 Streams: 98 - Type: ThreadList 99 Threads: 100 - Thread Id: 0x00003E81 101 Stack: 102 Start of Memory Range: 0x00007FFCEB34A000 103 Content: C84D04BCE97F00 104 Context: 00000000000000 105 ... 106 )"), 107 llvm::Succeeded()); 108 llvm::ArrayRef<minidump::Thread> thread_list; 109 110 thread_list = parser->GetThreads(); 111 ASSERT_EQ(1UL, thread_list.size()); 112 113 const minidump::Thread &thread = thread_list[0]; 114 115 EXPECT_EQ(0x3e81u, thread.ThreadId); 116 117 llvm::ArrayRef<uint8_t> context = parser->GetThreadContext(thread); 118 EXPECT_EQ(7u, context.size()); 119 } 120 121 TEST_F(MinidumpParserTest, GetArchitecture) { 122 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 123 --- !minidump 124 Streams: 125 - Type: SystemInfo 126 Processor Arch: AMD64 127 Processor Level: 6 128 Processor Revision: 16130 129 Number of Processors: 1 130 Platform ID: Linux 131 CPU: 132 Vendor ID: GenuineIntel 133 Version Info: 0x00000000 134 Feature Info: 0x00000000 135 ... 136 )"), 137 llvm::Succeeded()); 138 ASSERT_EQ(llvm::Triple::ArchType::x86_64, 139 parser->GetArchitecture().GetMachine()); 140 ASSERT_EQ(llvm::Triple::OSType::Linux, 141 parser->GetArchitecture().GetTriple().getOS()); 142 } 143 144 TEST_F(MinidumpParserTest, GetMiscInfo_no_stream) { 145 // Test that GetMiscInfo returns nullptr when the minidump does not contain 146 // this stream. 147 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 148 --- !minidump 149 Streams: 150 ... 151 )"), 152 llvm::Succeeded()); 153 EXPECT_EQ(nullptr, parser->GetMiscInfo()); 154 } 155 156 TEST_F(MinidumpParserTest, GetLinuxProcStatus) { 157 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 158 --- !minidump 159 Streams: 160 - Type: SystemInfo 161 Processor Arch: AMD64 162 Processor Level: 6 163 Processor Revision: 16130 164 Number of Processors: 1 165 Platform ID: Linux 166 CSD Version: 'Linux 3.13.0-91-generic' 167 CPU: 168 Vendor ID: GenuineIntel 169 Version Info: 0x00000000 170 Feature Info: 0x00000000 171 - Type: LinuxProcStatus 172 Text: | 173 Name: a.out 174 State: t (tracing stop) 175 Tgid: 16001 176 Ngid: 0 177 Pid: 16001 178 PPid: 13243 179 TracerPid: 16002 180 Uid: 404696 404696 404696 404696 181 Gid: 5762 5762 5762 5762 182 ... 183 )"), 184 llvm::Succeeded()); 185 llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus(); 186 ASSERT_TRUE(proc_status.hasValue()); 187 lldb::pid_t pid = proc_status->GetPid(); 188 ASSERT_EQ(16001UL, pid); 189 } 190 191 TEST_F(MinidumpParserTest, GetPid) { 192 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 193 --- !minidump 194 Streams: 195 - Type: SystemInfo 196 Processor Arch: AMD64 197 Processor Level: 6 198 Processor Revision: 16130 199 Number of Processors: 1 200 Platform ID: Linux 201 CSD Version: 'Linux 3.13.0-91-generic' 202 CPU: 203 Vendor ID: GenuineIntel 204 Version Info: 0x00000000 205 Feature Info: 0x00000000 206 - Type: LinuxProcStatus 207 Text: | 208 Name: a.out 209 State: t (tracing stop) 210 Tgid: 16001 211 Ngid: 0 212 Pid: 16001 213 PPid: 13243 214 TracerPid: 16002 215 Uid: 404696 404696 404696 404696 216 Gid: 5762 5762 5762 5762 217 ... 218 )"), 219 llvm::Succeeded()); 220 llvm::Optional<lldb::pid_t> pid = parser->GetPid(); 221 ASSERT_TRUE(pid.hasValue()); 222 ASSERT_EQ(16001UL, pid.getValue()); 223 } 224 225 TEST_F(MinidumpParserTest, GetFilteredModuleList) { 226 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 227 --- !minidump 228 Streams: 229 - Type: ModuleList 230 Modules: 231 - Base of Image: 0x0000000000400000 232 Size of Image: 0x00001000 233 Module Name: '/tmp/test/linux-x86_64_not_crashed' 234 CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611 235 - Base of Image: 0x0000000000600000 236 Size of Image: 0x00002000 237 Module Name: '/tmp/test/linux-x86_64_not_crashed' 238 CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611 239 ... 240 )"), 241 llvm::Succeeded()); 242 llvm::ArrayRef<minidump::Module> modules = parser->GetModuleList(); 243 std::vector<const minidump::Module *> filtered_modules = 244 parser->GetFilteredModuleList(); 245 EXPECT_EQ(2u, modules.size()); 246 ASSERT_EQ(1u, filtered_modules.size()); 247 const minidump::Module &M = *filtered_modules[0]; 248 EXPECT_THAT_EXPECTED(parser->GetMinidumpFile().getString(M.ModuleNameRVA), 249 llvm::HasValue("/tmp/test/linux-x86_64_not_crashed")); 250 } 251 252 TEST_F(MinidumpParserTest, GetExceptionStream) { 253 SetUpData("linux-x86_64.dmp"); 254 const llvm::minidump::ExceptionStream *exception_stream = 255 parser->GetExceptionStream(); 256 ASSERT_NE(nullptr, exception_stream); 257 ASSERT_EQ(11UL, exception_stream->ExceptionRecord.ExceptionCode); 258 } 259 260 void check_mem_range_exists(MinidumpParser &parser, const uint64_t range_start, 261 const uint64_t range_size) { 262 llvm::Optional<minidump::Range> range = parser.FindMemoryRange(range_start); 263 ASSERT_TRUE(range.hasValue()) << "There is no range containing this address"; 264 EXPECT_EQ(range_start, range->start); 265 EXPECT_EQ(range_start + range_size, range->start + range->range_ref.size()); 266 } 267 268 TEST_F(MinidumpParserTest, FindMemoryRange) { 269 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 270 --- !minidump 271 Streams: 272 - Type: MemoryList 273 Memory Ranges: 274 - Start of Memory Range: 0x00007FFCEB34A000 275 Content: C84D04BCE9 276 - Start of Memory Range: 0x0000000000401D46 277 Content: 5421 278 ... 279 )"), 280 llvm::Succeeded()); 281 EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x00)); 282 EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x2a)); 283 EXPECT_EQ((minidump::Range{0x401d46, llvm::ArrayRef<uint8_t>{0x54, 0x21}}), 284 parser->FindMemoryRange(0x401d46)); 285 EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x401d46 + 2)); 286 287 EXPECT_EQ( 288 (minidump::Range{0x7ffceb34a000, 289 llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}}), 290 parser->FindMemoryRange(0x7ffceb34a000 + 2)); 291 EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x7ffceb34a000 + 5)); 292 } 293 294 TEST_F(MinidumpParserTest, GetMemory) { 295 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 296 --- !minidump 297 Streams: 298 - Type: MemoryList 299 Memory Ranges: 300 - Start of Memory Range: 0x00007FFCEB34A000 301 Content: C84D04BCE9 302 - Start of Memory Range: 0x0000000000401D46 303 Content: 5421 304 ... 305 )"), 306 llvm::Succeeded()); 307 308 EXPECT_EQ((llvm::ArrayRef<uint8_t>{0x54}), parser->GetMemory(0x401d46, 1)); 309 EXPECT_EQ((llvm::ArrayRef<uint8_t>{0x54, 0x21}), 310 parser->GetMemory(0x401d46, 4)); 311 312 EXPECT_EQ((llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}), 313 parser->GetMemory(0x7ffceb34a000, 5)); 314 EXPECT_EQ((llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04}), 315 parser->GetMemory(0x7ffceb34a000, 3)); 316 317 EXPECT_EQ(llvm::ArrayRef<uint8_t>(), parser->GetMemory(0x500000, 512)); 318 } 319 320 TEST_F(MinidumpParserTest, FindMemoryRangeWithFullMemoryMinidump) { 321 SetUpData("fizzbuzz_wow64.dmp"); 322 323 // There are a lot of ranges in the file, just testing with some of them 324 EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue()); 325 EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue()); 326 check_mem_range_exists(*parser, 0x10000, 65536); // first range 327 check_mem_range_exists(*parser, 0x40000, 4096); 328 EXPECT_FALSE(parser->FindMemoryRange(0x40000 + 4096).hasValue()); 329 check_mem_range_exists(*parser, 0x77c12000, 8192); 330 check_mem_range_exists(*parser, 0x7ffe0000, 4096); // last range 331 EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).hasValue()); 332 } 333 334 constexpr auto yes = MemoryRegionInfo::eYes; 335 constexpr auto no = MemoryRegionInfo::eNo; 336 constexpr auto unknown = MemoryRegionInfo::eDontKnow; 337 338 TEST_F(MinidumpParserTest, GetMemoryRegionInfo) { 339 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 340 --- !minidump 341 Streams: 342 - Type: MemoryInfoList 343 Memory Ranges: 344 - Base Address: 0x0000000000000000 345 Allocation Protect: [ ] 346 Region Size: 0x0000000000010000 347 State: [ MEM_FREE ] 348 Protect: [ PAGE_NO_ACCESS ] 349 Type: [ ] 350 - Base Address: 0x0000000000010000 351 Allocation Protect: [ PAGE_READ_WRITE ] 352 Region Size: 0x0000000000021000 353 State: [ MEM_COMMIT ] 354 Type: [ MEM_MAPPED ] 355 - Base Address: 0x0000000000040000 356 Allocation Protect: [ PAGE_EXECUTE_WRITE_COPY ] 357 Region Size: 0x0000000000001000 358 State: [ MEM_COMMIT ] 359 Protect: [ PAGE_READ_ONLY ] 360 Type: [ MEM_IMAGE ] 361 - Base Address: 0x000000007FFE0000 362 Allocation Protect: [ PAGE_READ_ONLY ] 363 Region Size: 0x0000000000001000 364 State: [ MEM_COMMIT ] 365 Type: [ MEM_PRIVATE ] 366 - Base Address: 0x000000007FFE1000 367 Allocation Base: 0x000000007FFE0000 368 Allocation Protect: [ PAGE_READ_ONLY ] 369 Region Size: 0x000000000000F000 370 State: [ MEM_RESERVE ] 371 Protect: [ PAGE_NO_ACCESS ] 372 Type: [ MEM_PRIVATE ] 373 ... 374 )"), 375 llvm::Succeeded()); 376 377 EXPECT_THAT( 378 parser->BuildMemoryRegions(), 379 testing::Pair(testing::ElementsAre( 380 MemoryRegionInfo({0x0, 0x10000}, no, no, no, no, 381 ConstString(), unknown, 0), 382 MemoryRegionInfo({0x10000, 0x21000}, yes, yes, no, yes, 383 ConstString(), unknown, 0), 384 MemoryRegionInfo({0x40000, 0x1000}, yes, no, no, yes, 385 ConstString(), unknown, 0), 386 MemoryRegionInfo({0x7ffe0000, 0x1000}, yes, no, no, yes, 387 ConstString(), unknown, 0), 388 MemoryRegionInfo({0x7ffe1000, 0xf000}, no, no, no, yes, 389 ConstString(), unknown, 0)), 390 true)); 391 } 392 393 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) { 394 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 395 --- !minidump 396 Streams: 397 - Type: MemoryList 398 Memory Ranges: 399 - Start of Memory Range: 0x0000000000001000 400 Content: '31313131313131313131313131313131' 401 - Start of Memory Range: 0x0000000000002000 402 Content: '3333333333333333333333333333333333333333333333333333333333333333' 403 ... 404 )"), 405 llvm::Succeeded()); 406 407 // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when 408 // we don't have a MemoryInfoListStream. 409 410 EXPECT_THAT( 411 parser->BuildMemoryRegions(), 412 testing::Pair(testing::ElementsAre( 413 MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown, 414 yes, ConstString(), unknown, 0), 415 MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown, 416 yes, ConstString(), unknown, 0)), 417 false)); 418 } 419 420 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) { 421 SetUpData("regions-memlist64.dmp"); 422 423 // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when 424 // we don't have a MemoryInfoListStream. 425 EXPECT_THAT( 426 parser->BuildMemoryRegions(), 427 testing::Pair(testing::ElementsAre( 428 MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown, 429 yes, ConstString(), unknown, 0), 430 MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown, 431 yes, ConstString(), unknown, 0)), 432 false)); 433 } 434 435 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) { 436 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 437 --- !minidump 438 Streams: 439 - Type: LinuxMaps 440 Text: | 441 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process 442 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process 443 400dc000-400dd000 rw-p 00000000 00:00 0 444 400ec000-400ed000 r--p 00000000 00:00 0 445 400ee000-400ef000 rw-p 00010000 b3:04 300 /system/bin/linker 446 400fc000-400fd000 rwxp 00001000 b3:04 1096 /system/lib/liblog.so 447 448 ... 449 )"), 450 llvm::Succeeded()); 451 // Test we can get memory regions from the linux /proc/<pid>/maps stream when 452 // we don't have a MemoryInfoListStream. 453 ConstString app_process("/system/bin/app_process"); 454 ConstString linker("/system/bin/linker"); 455 ConstString liblog("/system/lib/liblog.so"); 456 EXPECT_THAT( 457 parser->BuildMemoryRegions(), 458 testing::Pair(testing::ElementsAre( 459 MemoryRegionInfo({0x400d9000, 0x2000}, yes, no, yes, 460 yes, app_process, unknown, 0), 461 MemoryRegionInfo({0x400db000, 0x1000}, yes, no, no, yes, 462 app_process, unknown, 0), 463 MemoryRegionInfo({0x400dc000, 0x1000}, yes, yes, no, 464 yes, ConstString(), unknown, 0), 465 MemoryRegionInfo({0x400ec000, 0x1000}, yes, no, no, yes, 466 ConstString(), unknown, 0), 467 MemoryRegionInfo({0x400ee000, 0x1000}, yes, yes, no, 468 yes, linker, unknown, 0), 469 MemoryRegionInfo({0x400fc000, 0x1000}, yes, yes, yes, 470 yes, liblog, unknown, 0)), 471 true)); 472 } 473 474 // Windows Minidump tests 475 TEST_F(MinidumpParserTest, GetArchitectureWindows) { 476 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 477 --- !minidump 478 Streams: 479 - Type: SystemInfo 480 Processor Arch: X86 481 Processor Level: 6 482 Processor Revision: 15876 483 Number of Processors: 32 484 Product type: 1 485 Major Version: 6 486 Minor Version: 1 487 Build Number: 7601 488 Platform ID: Win32NT 489 CSD Version: Service Pack 1 490 Suite Mask: 0x0100 491 CPU: 492 Vendor ID: GenuineIntel 493 Version Info: 0x000306E4 494 Feature Info: 0xBFEBFBFF 495 AMD Extended Features: 0x771EEC80 496 ... 497 )"), 498 llvm::Succeeded()); 499 ASSERT_EQ(llvm::Triple::ArchType::x86, 500 parser->GetArchitecture().GetMachine()); 501 ASSERT_EQ(llvm::Triple::OSType::Win32, 502 parser->GetArchitecture().GetTriple().getOS()); 503 } 504 505 TEST_F(MinidumpParserTest, GetLinuxProcStatus_no_stream) { 506 // Test that GetLinuxProcStatus returns nullptr when the minidump does not 507 // contain this stream. 508 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 509 --- !minidump 510 Streams: 511 ... 512 )"), 513 llvm::Succeeded()); 514 EXPECT_EQ(llvm::None, parser->GetLinuxProcStatus()); 515 } 516 517 TEST_F(MinidumpParserTest, GetMiscInfoWindows) { 518 SetUpData("fizzbuzz_no_heap.dmp"); 519 const MinidumpMiscInfo *misc_info = parser->GetMiscInfo(); 520 ASSERT_NE(nullptr, misc_info); 521 llvm::Optional<lldb::pid_t> pid = misc_info->GetPid(); 522 ASSERT_TRUE(pid.hasValue()); 523 ASSERT_EQ(4440UL, pid.getValue()); 524 } 525 526 TEST_F(MinidumpParserTest, GetPidWindows) { 527 SetUpData("fizzbuzz_no_heap.dmp"); 528 llvm::Optional<lldb::pid_t> pid = parser->GetPid(); 529 ASSERT_TRUE(pid.hasValue()); 530 ASSERT_EQ(4440UL, pid.getValue()); 531 } 532 533 // wow64 534 TEST_F(MinidumpParserTest, GetPidWow64) { 535 SetUpData("fizzbuzz_wow64.dmp"); 536 llvm::Optional<lldb::pid_t> pid = parser->GetPid(); 537 ASSERT_TRUE(pid.hasValue()); 538 ASSERT_EQ(7836UL, pid.getValue()); 539 } 540 541 // Register tests 542 #define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x)) 543 #define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x)) 544 545 TEST_F(MinidumpParserTest, GetThreadContext_x86_32) { 546 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 547 --- !minidump 548 Streams: 549 - Type: ThreadList 550 Threads: 551 - Thread Id: 0x00026804 552 Stack: 553 Start of Memory Range: 0x00000000FF9DD000 554 Content: 68D39DFF 555 Context: 0F0001000000000000000000000000000000000000000000000000007F03FFFF0000FFFFFFFFFFFF09DC62F72300000088E36CF72B00FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063000000000000002B0000002B000000A88204085CD59DFF008077F7A3D49DFF01000000000000003CD59DFFA082040823000000820201002CD59DFF2B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 556 )"), 557 llvm::Succeeded()); 558 559 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 560 const minidump::Thread &thread = thread_list[0]; 561 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread)); 562 const MinidumpContext_x86_32 *context; 563 EXPECT_TRUE(consumeObject(registers, context).Success()); 564 565 EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)), 566 MinidumpContext_x86_32_Flags::x86_32_Flag | 567 MinidumpContext_x86_32_Flags::Full | 568 MinidumpContext_x86_32_Flags::FloatingPoint); 569 570 EXPECT_EQ(0x00000000u, context->eax); 571 EXPECT_EQ(0xf7778000u, context->ebx); 572 EXPECT_EQ(0x00000001u, context->ecx); 573 EXPECT_EQ(0xff9dd4a3u, context->edx); 574 EXPECT_EQ(0x080482a8u, context->edi); 575 EXPECT_EQ(0xff9dd55cu, context->esi); 576 EXPECT_EQ(0xff9dd53cu, context->ebp); 577 EXPECT_EQ(0xff9dd52cu, context->esp); 578 EXPECT_EQ(0x080482a0u, context->eip); 579 EXPECT_EQ(0x00010282u, context->eflags); 580 EXPECT_EQ(0x0023u, context->cs); 581 EXPECT_EQ(0x0000u, context->fs); 582 EXPECT_EQ(0x0063u, context->gs); 583 EXPECT_EQ(0x002bu, context->ss); 584 EXPECT_EQ(0x002bu, context->ds); 585 EXPECT_EQ(0x002bu, context->es); 586 } 587 588 TEST_F(MinidumpParserTest, GetThreadContext_x86_64) { 589 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 590 --- !minidump 591 Streams: 592 - Type: ThreadList 593 Threads: 594 - Thread Id: 0x00003E81 595 Stack: 596 Start of Memory Range: 0x00007FFCEB34A000 597 Content: C84D04BCE97F00 598 Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 599 ... 600 )"), 601 llvm::Succeeded()); 602 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 603 const minidump::Thread &thread = thread_list[0]; 604 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread)); 605 const MinidumpContext_x86_64 *context; 606 EXPECT_TRUE(consumeObject(registers, context).Success()); 607 608 EXPECT_EQ(MinidumpContext_x86_64_Flags(uint32_t(context->context_flags)), 609 MinidumpContext_x86_64_Flags::x86_64_Flag | 610 MinidumpContext_x86_64_Flags::Control | 611 MinidumpContext_x86_64_Flags::FloatingPoint | 612 MinidumpContext_x86_64_Flags::Integer); 613 EXPECT_EQ(0x0000000000000000u, context->rax); 614 EXPECT_EQ(0x0000000000000000u, context->rbx); 615 EXPECT_EQ(0x0000000000000010u, context->rcx); 616 EXPECT_EQ(0x0000000000000000u, context->rdx); 617 EXPECT_EQ(0x00007ffceb349cf0u, context->rdi); 618 EXPECT_EQ(0x0000000000000000u, context->rsi); 619 EXPECT_EQ(0x00007ffceb34a210u, context->rbp); 620 EXPECT_EQ(0x00007ffceb34a210u, context->rsp); 621 EXPECT_EQ(0x00007fe9bc1aa9c0u, context->r8); 622 EXPECT_EQ(0x0000000000000000u, context->r9); 623 EXPECT_EQ(0x00007fe9bc3f16a0u, context->r10); 624 EXPECT_EQ(0x0000000000000246u, context->r11); 625 EXPECT_EQ(0x0000000000401c92u, context->r12); 626 EXPECT_EQ(0x00007ffceb34a430u, context->r13); 627 EXPECT_EQ(0x0000000000000000u, context->r14); 628 EXPECT_EQ(0x0000000000000000u, context->r15); 629 EXPECT_EQ(0x0000000000401dc6u, context->rip); 630 EXPECT_EQ(0x00010206u, context->eflags); 631 EXPECT_EQ(0x0033u, context->cs); 632 EXPECT_EQ(0x0000u, context->ss); 633 } 634 635 TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) { 636 SetUpData("fizzbuzz_wow64.dmp"); 637 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 638 const minidump::Thread &thread = thread_list[0]; 639 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread)); 640 const MinidumpContext_x86_32 *context; 641 EXPECT_TRUE(consumeObject(registers, context).Success()); 642 643 EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)), 644 MinidumpContext_x86_32_Flags::x86_32_Flag | 645 MinidumpContext_x86_32_Flags::Full | 646 MinidumpContext_x86_32_Flags::FloatingPoint | 647 MinidumpContext_x86_32_Flags::ExtendedRegisters); 648 649 EXPECT_EQ(0x00000000u, context->eax); 650 EXPECT_EQ(0x0037f608u, context->ebx); 651 EXPECT_EQ(0x00e61578u, context->ecx); 652 EXPECT_EQ(0x00000008u, context->edx); 653 EXPECT_EQ(0x00000000u, context->edi); 654 EXPECT_EQ(0x00000002u, context->esi); 655 EXPECT_EQ(0x0037f654u, context->ebp); 656 EXPECT_EQ(0x0037f5b8u, context->esp); 657 EXPECT_EQ(0x77ce01fdu, context->eip); 658 EXPECT_EQ(0x00000246u, context->eflags); 659 EXPECT_EQ(0x0023u, context->cs); 660 EXPECT_EQ(0x0053u, context->fs); 661 EXPECT_EQ(0x002bu, context->gs); 662 EXPECT_EQ(0x002bu, context->ss); 663 EXPECT_EQ(0x002bu, context->ds); 664 EXPECT_EQ(0x002bu, context->es); 665 } 666 667 TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) { 668 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 669 --- !minidump 670 Streams: 671 - Type: ModuleList 672 Modules: 673 - Base of Image: 0x0000000000002000 674 Size of Image: 0x00001000 675 Module Name: '/tmp/a' 676 CodeView Record: '' 677 - Base of Image: 0x0000000000001000 678 Size of Image: 0x00001000 679 Module Name: '/tmp/a' 680 CodeView Record: '' 681 ... 682 )"), 683 llvm::Succeeded()); 684 // If we have a module mentioned twice in the module list, the filtered 685 // module list should contain the instance with the lowest BaseOfImage. 686 std::vector<const minidump::Module *> filtered_modules = 687 parser->GetFilteredModuleList(); 688 ASSERT_EQ(1u, filtered_modules.size()); 689 EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->BaseOfImage); 690 } 691 692 TEST_F(MinidumpParserTest, MinidumpModuleOrder) { 693 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 694 --- !minidump 695 Streams: 696 - Type: ModuleList 697 Modules: 698 - Base of Image: 0x0000000000002000 699 Size of Image: 0x00001000 700 Module Name: '/tmp/a' 701 CodeView Record: '' 702 - Base of Image: 0x0000000000001000 703 Size of Image: 0x00001000 704 Module Name: '/tmp/b' 705 CodeView Record: '' 706 ... 707 )"), 708 llvm::Succeeded()); 709 // Test module filtering does not affect the overall module order. Previous 710 // versions of the MinidumpParser::GetFilteredModuleList() function would sort 711 // all images by address and modify the order of the modules. 712 std::vector<const minidump::Module *> filtered_modules = 713 parser->GetFilteredModuleList(); 714 ASSERT_EQ(2u, filtered_modules.size()); 715 EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->BaseOfImage); 716 EXPECT_THAT_EXPECTED( 717 parser->GetMinidumpFile().getString(filtered_modules[0]->ModuleNameRVA), 718 llvm::HasValue("/tmp/a")); 719 EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->BaseOfImage); 720 EXPECT_THAT_EXPECTED( 721 parser->GetMinidumpFile().getString(filtered_modules[1]->ModuleNameRVA), 722 llvm::HasValue("/tmp/b")); 723 } 724 725