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