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