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