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 MinidumpExceptionStream *exception_stream = 256 parser->GetExceptionStream(); 257 ASSERT_NE(nullptr, exception_stream); 258 ASSERT_EQ(11UL, exception_stream->exception_record.exception_code); 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 void check_region(MinidumpParser &parser, lldb::addr_t addr, lldb::addr_t start, 336 lldb::addr_t end, MemoryRegionInfo::OptionalBool read, 337 MemoryRegionInfo::OptionalBool write, 338 MemoryRegionInfo::OptionalBool exec, 339 MemoryRegionInfo::OptionalBool mapped, 340 ConstString name = ConstString()) { 341 SCOPED_TRACE(addr); 342 auto range_info = parser.GetMemoryRegionInfo(addr); 343 EXPECT_EQ(start, range_info.GetRange().GetRangeBase()); 344 EXPECT_EQ(end, range_info.GetRange().GetRangeEnd()); 345 EXPECT_EQ(read, range_info.GetReadable()); 346 EXPECT_EQ(write, range_info.GetWritable()); 347 EXPECT_EQ(exec, range_info.GetExecutable()); 348 EXPECT_EQ(mapped, range_info.GetMapped()); 349 EXPECT_EQ(name, range_info.GetName()); 350 } 351 352 // Same as above function where addr == start 353 void check_region(MinidumpParser &parser, lldb::addr_t start, lldb::addr_t end, 354 MemoryRegionInfo::OptionalBool read, 355 MemoryRegionInfo::OptionalBool write, 356 MemoryRegionInfo::OptionalBool exec, 357 MemoryRegionInfo::OptionalBool mapped, 358 ConstString name = ConstString()) { 359 check_region(parser, start, start, end, read, write, exec, mapped, name); 360 } 361 362 363 constexpr auto yes = MemoryRegionInfo::eYes; 364 constexpr auto no = MemoryRegionInfo::eNo; 365 constexpr auto unknown = MemoryRegionInfo::eDontKnow; 366 367 TEST_F(MinidumpParserTest, GetMemoryRegionInfo) { 368 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 369 --- !minidump 370 Streams: 371 - Type: MemoryInfoList 372 Memory Ranges: 373 - Base Address: 0x0000000000000000 374 Allocation Protect: [ ] 375 Region Size: 0x0000000000010000 376 State: [ MEM_FREE ] 377 Protect: [ PAGE_NO_ACCESS ] 378 Type: [ ] 379 - Base Address: 0x0000000000010000 380 Allocation Protect: [ PAGE_READ_WRITE ] 381 Region Size: 0x0000000000010000 382 State: [ MEM_COMMIT ] 383 Type: [ MEM_MAPPED ] 384 - Base Address: 0x0000000000020000 385 Allocation Protect: [ PAGE_READ_WRITE ] 386 Region Size: 0x0000000000010000 387 State: [ MEM_COMMIT ] 388 Type: [ MEM_MAPPED ] 389 - Base Address: 0x0000000000030000 390 Allocation Protect: [ PAGE_READ_WRITE ] 391 Region Size: 0x0000000000001000 392 State: [ MEM_COMMIT ] 393 Type: [ MEM_MAPPED ] 394 - Base Address: 0x0000000000040000 395 Allocation Protect: [ PAGE_EXECUTE_WRITE_COPY ] 396 Region Size: 0x0000000000001000 397 State: [ MEM_COMMIT ] 398 Protect: [ PAGE_READ_ONLY ] 399 Type: [ MEM_IMAGE ] 400 - Base Address: 0x000000007FFE0000 401 Allocation Protect: [ PAGE_READ_ONLY ] 402 Region Size: 0x0000000000001000 403 State: [ MEM_COMMIT ] 404 Type: [ MEM_PRIVATE ] 405 - Base Address: 0x000000007FFE1000 406 Allocation Base: 0x000000007FFE0000 407 Allocation Protect: [ PAGE_READ_ONLY ] 408 Region Size: 0x000000000000F000 409 State: [ MEM_RESERVE ] 410 Protect: [ PAGE_NO_ACCESS ] 411 Type: [ MEM_PRIVATE ] 412 ... 413 )"), 414 llvm::Succeeded()); 415 416 check_region(*parser, 0x00000000, 0x00010000, no, no, no, no); 417 check_region(*parser, 0x00010000, 0x00020000, yes, yes, no, yes); 418 check_region(*parser, 0x00020000, 0x00030000, yes, yes, no, yes); 419 check_region(*parser, 0x00030000, 0x00031000, yes, yes, no, yes); 420 check_region(*parser, 0x00031000, 0x00040000, no, no, no, no); 421 check_region(*parser, 0x00040000, 0x00041000, yes, no, no, yes); 422 423 // Check addresses contained inside ranges 424 check_region(*parser, 0x00000001, 0x00000000, 0x00010000, no, no, no, no); 425 check_region(*parser, 0x0000ffff, 0x00000000, 0x00010000, no, no, no, no); 426 check_region(*parser, 0x00010001, 0x00010000, 0x00020000, yes, yes, no, yes); 427 check_region(*parser, 0x0001ffff, 0x00010000, 0x00020000, yes, yes, no, yes); 428 429 // Test that an address after the last entry maps to rest of the memory space 430 check_region(*parser, 0x7fff0000, 0x7fff0000, UINT64_MAX, no, no, no, no); 431 } 432 433 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) { 434 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 435 --- !minidump 436 Streams: 437 - Type: MemoryList 438 Memory Ranges: 439 - Start of Memory Range: 0x0000000000001000 440 Content: '31313131313131313131313131313131' 441 - Start of Memory Range: 0x0000000000002000 442 Content: '3333333333333333333333333333333333333333333333333333333333333333' 443 ... 444 )"), 445 llvm::Succeeded()); 446 // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when 447 // we don't have a MemoryInfoListStream. 448 449 // Test addres before the first entry comes back with nothing mapped up 450 // to first valid region info 451 check_region(*parser, 0x00000000, 0x00001000, no, no, no, no); 452 check_region(*parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes); 453 check_region(*parser, 0x00001010, 0x00002000, no, no, no, no); 454 check_region(*parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes); 455 check_region(*parser, 0x00002020, UINT64_MAX, no, no, no, no); 456 } 457 458 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) { 459 SetUpData("regions-memlist64.dmp"); 460 // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when 461 // we don't have a MemoryInfoListStream. 462 463 // Test addres before the first entry comes back with nothing mapped up 464 // to first valid region info 465 check_region(*parser, 0x00000000, 0x00001000, no, no, no, no); 466 check_region(*parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes); 467 check_region(*parser, 0x00001010, 0x00002000, no, no, no, no); 468 check_region(*parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes); 469 check_region(*parser, 0x00002020, UINT64_MAX, no, no, no, no); 470 } 471 472 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) { 473 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 474 --- !minidump 475 Streams: 476 - Type: LinuxMaps 477 Text: | 478 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process 479 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process 480 400dc000-400dd000 rw-p 00000000 00:00 0 481 400dd000-400ec000 r-xp 00000000 b3:04 300 /system/bin/linker 482 400ec000-400ed000 r--p 00000000 00:00 0 483 400ed000-400ee000 r--p 0000f000 b3:04 300 /system/bin/linker 484 400ee000-400ef000 rw-p 00010000 b3:04 300 /system/bin/linker 485 400ef000-400fb000 rw-p 00000000 00:00 0 486 400fb000-400fc000 r-xp 00000000 b3:04 1096 /system/lib/liblog.so 487 400fc000-400fd000 rwxp 00001000 b3:04 1096 /system/lib/liblog.so 488 400fd000-400ff000 r-xp 00002000 b3:04 1096 /system/lib/liblog.so 489 400ff000-40100000 r--p 00003000 b3:04 1096 /system/lib/liblog.so 490 40100000-40101000 rw-p 00004000 b3:04 1096 /system/lib/liblog.so 491 40101000-40122000 r-xp 00000000 b3:04 955 /system/lib/libc.so 492 40122000-40123000 rwxp 00021000 b3:04 955 /system/lib/libc.so 493 40123000-40167000 r-xp 00022000 b3:04 955 /system/lib/libc.so 494 40167000-40169000 r--p 00065000 b3:04 955 /system/lib/libc.so 495 40169000-4016b000 rw-p 00067000 b3:04 955 /system/lib/libc.so 496 4016b000-40176000 rw-p 00000000 00:00 0 497 498 ... 499 )"), 500 llvm::Succeeded()); 501 // Test we can get memory regions from the linux /proc/<pid>/maps stream when 502 // we don't have a MemoryInfoListStream. 503 504 // Test addres before the first entry comes back with nothing mapped up 505 // to first valid region info 506 ConstString a("/system/bin/app_process"); 507 ConstString b("/system/bin/linker"); 508 ConstString c("/system/lib/liblog.so"); 509 ConstString d("/system/lib/libc.so"); 510 ConstString n; 511 check_region(*parser, 0x00000000, 0x400d9000, no, no, no, no, n); 512 check_region(*parser, 0x400d9000, 0x400db000, yes, no, yes, yes, a); 513 check_region(*parser, 0x400db000, 0x400dc000, yes, no, no, yes, a); 514 check_region(*parser, 0x400dc000, 0x400dd000, yes, yes, no, yes, n); 515 check_region(*parser, 0x400dd000, 0x400ec000, yes, no, yes, yes, b); 516 check_region(*parser, 0x400ec000, 0x400ed000, yes, no, no, yes, n); 517 check_region(*parser, 0x400ed000, 0x400ee000, yes, no, no, yes, b); 518 check_region(*parser, 0x400ee000, 0x400ef000, yes, yes, no, yes, b); 519 check_region(*parser, 0x400ef000, 0x400fb000, yes, yes, no, yes, n); 520 check_region(*parser, 0x400fb000, 0x400fc000, yes, no, yes, yes, c); 521 check_region(*parser, 0x400fc000, 0x400fd000, yes, yes, yes, yes, c); 522 check_region(*parser, 0x400fd000, 0x400ff000, yes, no, yes, yes, c); 523 check_region(*parser, 0x400ff000, 0x40100000, yes, no, no, yes, c); 524 check_region(*parser, 0x40100000, 0x40101000, yes, yes, no, yes, c); 525 check_region(*parser, 0x40101000, 0x40122000, yes, no, yes, yes, d); 526 check_region(*parser, 0x40122000, 0x40123000, yes, yes, yes, yes, d); 527 check_region(*parser, 0x40123000, 0x40167000, yes, no, yes, yes, d); 528 check_region(*parser, 0x40167000, 0x40169000, yes, no, no, yes, d); 529 check_region(*parser, 0x40169000, 0x4016b000, yes, yes, no, yes, d); 530 check_region(*parser, 0x4016b000, 0x40176000, yes, yes, no, yes, n); 531 check_region(*parser, 0x40176000, UINT64_MAX, no, no, no, no, n); 532 } 533 534 // Windows Minidump tests 535 TEST_F(MinidumpParserTest, GetArchitectureWindows) { 536 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 537 --- !minidump 538 Streams: 539 - Type: SystemInfo 540 Processor Arch: X86 541 Processor Level: 6 542 Processor Revision: 15876 543 Number of Processors: 32 544 Product type: 1 545 Major Version: 6 546 Minor Version: 1 547 Build Number: 7601 548 Platform ID: Win32NT 549 CSD Version: Service Pack 1 550 Suite Mask: 0x0100 551 CPU: 552 Vendor ID: GenuineIntel 553 Version Info: 0x000306E4 554 Feature Info: 0xBFEBFBFF 555 AMD Extended Features: 0x771EEC80 556 ... 557 )"), 558 llvm::Succeeded()); 559 ASSERT_EQ(llvm::Triple::ArchType::x86, 560 parser->GetArchitecture().GetMachine()); 561 ASSERT_EQ(llvm::Triple::OSType::Win32, 562 parser->GetArchitecture().GetTriple().getOS()); 563 } 564 565 TEST_F(MinidumpParserTest, GetLinuxProcStatus_no_stream) { 566 // Test that GetLinuxProcStatus returns nullptr when the minidump does not 567 // contain this stream. 568 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 569 --- !minidump 570 Streams: 571 ... 572 )"), 573 llvm::Succeeded()); 574 EXPECT_EQ(llvm::None, parser->GetLinuxProcStatus()); 575 } 576 577 TEST_F(MinidumpParserTest, GetMiscInfoWindows) { 578 SetUpData("fizzbuzz_no_heap.dmp"); 579 const MinidumpMiscInfo *misc_info = parser->GetMiscInfo(); 580 ASSERT_NE(nullptr, misc_info); 581 llvm::Optional<lldb::pid_t> pid = misc_info->GetPid(); 582 ASSERT_TRUE(pid.hasValue()); 583 ASSERT_EQ(4440UL, pid.getValue()); 584 } 585 586 TEST_F(MinidumpParserTest, GetPidWindows) { 587 SetUpData("fizzbuzz_no_heap.dmp"); 588 llvm::Optional<lldb::pid_t> pid = parser->GetPid(); 589 ASSERT_TRUE(pid.hasValue()); 590 ASSERT_EQ(4440UL, pid.getValue()); 591 } 592 593 // wow64 594 TEST_F(MinidumpParserTest, GetPidWow64) { 595 SetUpData("fizzbuzz_wow64.dmp"); 596 llvm::Optional<lldb::pid_t> pid = parser->GetPid(); 597 ASSERT_TRUE(pid.hasValue()); 598 ASSERT_EQ(7836UL, pid.getValue()); 599 } 600 601 // Register tests 602 #define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x)) 603 #define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x)) 604 605 TEST_F(MinidumpParserTest, GetThreadContext_x86_32) { 606 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 607 --- !minidump 608 Streams: 609 - Type: ThreadList 610 Threads: 611 - Thread Id: 0x00026804 612 Stack: 613 Start of Memory Range: 0x00000000FF9DD000 614 Content: 68D39DFF 615 Context: 0F0001000000000000000000000000000000000000000000000000007F03FFFF0000FFFFFFFFFFFF09DC62F72300000088E36CF72B00FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063000000000000002B0000002B000000A88204085CD59DFF008077F7A3D49DFF01000000000000003CD59DFFA082040823000000820201002CD59DFF2B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 616 )"), 617 llvm::Succeeded()); 618 619 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 620 const minidump::Thread &thread = thread_list[0]; 621 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread)); 622 const MinidumpContext_x86_32 *context; 623 EXPECT_TRUE(consumeObject(registers, context).Success()); 624 625 EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)), 626 MinidumpContext_x86_32_Flags::x86_32_Flag | 627 MinidumpContext_x86_32_Flags::Full | 628 MinidumpContext_x86_32_Flags::FloatingPoint); 629 630 EXPECT_EQ(0x00000000u, context->eax); 631 EXPECT_EQ(0xf7778000u, context->ebx); 632 EXPECT_EQ(0x00000001u, context->ecx); 633 EXPECT_EQ(0xff9dd4a3u, context->edx); 634 EXPECT_EQ(0x080482a8u, context->edi); 635 EXPECT_EQ(0xff9dd55cu, context->esi); 636 EXPECT_EQ(0xff9dd53cu, context->ebp); 637 EXPECT_EQ(0xff9dd52cu, context->esp); 638 EXPECT_EQ(0x080482a0u, context->eip); 639 EXPECT_EQ(0x00010282u, context->eflags); 640 EXPECT_EQ(0x0023u, context->cs); 641 EXPECT_EQ(0x0000u, context->fs); 642 EXPECT_EQ(0x0063u, context->gs); 643 EXPECT_EQ(0x002bu, context->ss); 644 EXPECT_EQ(0x002bu, context->ds); 645 EXPECT_EQ(0x002bu, context->es); 646 } 647 648 TEST_F(MinidumpParserTest, GetThreadContext_x86_64) { 649 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 650 --- !minidump 651 Streams: 652 - Type: ThreadList 653 Threads: 654 - Thread Id: 0x00003E81 655 Stack: 656 Start of Memory Range: 0x00007FFCEB34A000 657 Content: C84D04BCE97F00 658 Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 659 ... 660 )"), 661 llvm::Succeeded()); 662 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 663 const minidump::Thread &thread = thread_list[0]; 664 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread)); 665 const MinidumpContext_x86_64 *context; 666 EXPECT_TRUE(consumeObject(registers, context).Success()); 667 668 EXPECT_EQ(MinidumpContext_x86_64_Flags(uint32_t(context->context_flags)), 669 MinidumpContext_x86_64_Flags::x86_64_Flag | 670 MinidumpContext_x86_64_Flags::Control | 671 MinidumpContext_x86_64_Flags::FloatingPoint | 672 MinidumpContext_x86_64_Flags::Integer); 673 EXPECT_EQ(0x0000000000000000u, context->rax); 674 EXPECT_EQ(0x0000000000000000u, context->rbx); 675 EXPECT_EQ(0x0000000000000010u, context->rcx); 676 EXPECT_EQ(0x0000000000000000u, context->rdx); 677 EXPECT_EQ(0x00007ffceb349cf0u, context->rdi); 678 EXPECT_EQ(0x0000000000000000u, context->rsi); 679 EXPECT_EQ(0x00007ffceb34a210u, context->rbp); 680 EXPECT_EQ(0x00007ffceb34a210u, context->rsp); 681 EXPECT_EQ(0x00007fe9bc1aa9c0u, context->r8); 682 EXPECT_EQ(0x0000000000000000u, context->r9); 683 EXPECT_EQ(0x00007fe9bc3f16a0u, context->r10); 684 EXPECT_EQ(0x0000000000000246u, context->r11); 685 EXPECT_EQ(0x0000000000401c92u, context->r12); 686 EXPECT_EQ(0x00007ffceb34a430u, context->r13); 687 EXPECT_EQ(0x0000000000000000u, context->r14); 688 EXPECT_EQ(0x0000000000000000u, context->r15); 689 EXPECT_EQ(0x0000000000401dc6u, context->rip); 690 EXPECT_EQ(0x00010206u, context->eflags); 691 EXPECT_EQ(0x0033u, context->cs); 692 EXPECT_EQ(0x0000u, context->ss); 693 } 694 695 TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) { 696 SetUpData("fizzbuzz_wow64.dmp"); 697 llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads(); 698 const minidump::Thread &thread = thread_list[0]; 699 llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread)); 700 const MinidumpContext_x86_32 *context; 701 EXPECT_TRUE(consumeObject(registers, context).Success()); 702 703 EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)), 704 MinidumpContext_x86_32_Flags::x86_32_Flag | 705 MinidumpContext_x86_32_Flags::Full | 706 MinidumpContext_x86_32_Flags::FloatingPoint | 707 MinidumpContext_x86_32_Flags::ExtendedRegisters); 708 709 EXPECT_EQ(0x00000000u, context->eax); 710 EXPECT_EQ(0x0037f608u, context->ebx); 711 EXPECT_EQ(0x00e61578u, context->ecx); 712 EXPECT_EQ(0x00000008u, context->edx); 713 EXPECT_EQ(0x00000000u, context->edi); 714 EXPECT_EQ(0x00000002u, context->esi); 715 EXPECT_EQ(0x0037f654u, context->ebp); 716 EXPECT_EQ(0x0037f5b8u, context->esp); 717 EXPECT_EQ(0x77ce01fdu, context->eip); 718 EXPECT_EQ(0x00000246u, context->eflags); 719 EXPECT_EQ(0x0023u, context->cs); 720 EXPECT_EQ(0x0053u, context->fs); 721 EXPECT_EQ(0x002bu, context->gs); 722 EXPECT_EQ(0x002bu, context->ss); 723 EXPECT_EQ(0x002bu, context->ds); 724 EXPECT_EQ(0x002bu, context->es); 725 } 726 727 TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) { 728 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 729 --- !minidump 730 Streams: 731 - Type: ModuleList 732 Modules: 733 - Base of Image: 0x0000000000002000 734 Size of Image: 0x00001000 735 Module Name: '/tmp/a' 736 CodeView Record: '' 737 - Base of Image: 0x0000000000001000 738 Size of Image: 0x00001000 739 Module Name: '/tmp/a' 740 CodeView Record: '' 741 ... 742 )"), 743 llvm::Succeeded()); 744 // If we have a module mentioned twice in the module list, the filtered 745 // module list should contain the instance with the lowest BaseOfImage. 746 std::vector<const minidump::Module *> filtered_modules = 747 parser->GetFilteredModuleList(); 748 ASSERT_EQ(1u, filtered_modules.size()); 749 EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->BaseOfImage); 750 } 751 752 TEST_F(MinidumpParserTest, MinidumpModuleOrder) { 753 ASSERT_THAT_ERROR(SetUpFromYaml(R"( 754 --- !minidump 755 Streams: 756 - Type: ModuleList 757 Modules: 758 - Base of Image: 0x0000000000002000 759 Size of Image: 0x00001000 760 Module Name: '/tmp/a' 761 CodeView Record: '' 762 - Base of Image: 0x0000000000001000 763 Size of Image: 0x00001000 764 Module Name: '/tmp/b' 765 CodeView Record: '' 766 ... 767 )"), 768 llvm::Succeeded()); 769 // Test module filtering does not affect the overall module order. Previous 770 // versions of the MinidumpParser::GetFilteredModuleList() function would sort 771 // all images by address and modify the order of the modules. 772 std::vector<const minidump::Module *> filtered_modules = 773 parser->GetFilteredModuleList(); 774 ASSERT_EQ(2u, filtered_modules.size()); 775 EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->BaseOfImage); 776 EXPECT_THAT_EXPECTED( 777 parser->GetMinidumpFile().getString(filtered_modules[0]->ModuleNameRVA), 778 llvm::HasValue("/tmp/a")); 779 EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->BaseOfImage); 780 EXPECT_THAT_EXPECTED( 781 parser->GetMinidumpFile().getString(filtered_modules[1]->ModuleNameRVA), 782 llvm::HasValue("/tmp/b")); 783 } 784 785