brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.4 KiB · 44f653c Raw
930 lines · cpp
1//===-- MinidumpTypesTest.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Plugins/Process/minidump/MinidumpParser.h"10#include "Plugins/Process/minidump/MinidumpTypes.h"11#include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h"12#include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"13#include "TestingSupport/SubsystemRAII.h"14#include "TestingSupport/TestUtilities.h"15#include "lldb/Host/FileSystem.h"16#include "lldb/Target/MemoryRegionInfo.h"17#include "lldb/Utility/ArchSpec.h"18#include "lldb/Utility/DataBufferHeap.h"19#include "lldb/Utility/DataExtractor.h"20#include "lldb/Utility/FileSpec.h"21#include "llvm/ADT/ArrayRef.h"22#include "llvm/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 includes31 32// C++ includes33#include <memory>34#include <optional>35 36using namespace lldb_private;37using namespace minidump;38 39class MinidumpParserTest : public testing::Test {40public:41  SubsystemRAII<FileSystem> subsystems;42 43  void SetUpData(const char *minidump_filename) {44    std::string filename = GetInputFilePath(minidump_filename);45    auto BufferPtr = FileSystem::Instance().CreateDataBuffer(filename, -1, 0);46    ASSERT_NE(BufferPtr, nullptr);47    llvm::Expected<MinidumpParser> expected_parser =48        MinidumpParser::Create(BufferPtr);49    ASSERT_THAT_EXPECTED(expected_parser, llvm::Succeeded());50    parser = std::move(*expected_parser);51    ASSERT_GT(parser->GetData().size(), 0UL);52  }53 54  llvm::Error SetUpFromYaml(llvm::StringRef yaml) {55    std::string data;56    llvm::raw_string_ostream os(data);57    llvm::yaml::Input YIn(yaml);58    if (!llvm::yaml::convertYAML(YIn, os, [](const llvm::Twine &Msg) {}))59      return llvm::createStringError(llvm::inconvertibleErrorCode(),60                                     "convertYAML() failed");61 62    auto data_buffer_sp =63        std::make_shared<DataBufferHeap>(data.data(), data.size());64    auto expected_parser = MinidumpParser::Create(std::move(data_buffer_sp));65    if (!expected_parser)66      return expected_parser.takeError();67    parser = std::move(*expected_parser);68    return llvm::Error::success();69  }70 71  std::optional<MinidumpParser> parser;72};73 74TEST_F(MinidumpParserTest, InvalidMinidump) {75  std::string duplicate_streams;76  llvm::raw_string_ostream os(duplicate_streams);77  llvm::yaml::Input YIn(R"(78--- !minidump79Streams:80  - Type:            LinuxAuxv81    Content:         DEADBEEFBAADF00D82  - Type:            LinuxAuxv83    Content:         DEADBEEFBAADF00D84  )");85 86  ASSERT_TRUE(llvm::yaml::convertYAML(YIn, os, [](const llvm::Twine &Msg){}));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 92TEST_F(MinidumpParserTest, GetThreadsAndGetThreadContext) {93  ASSERT_THAT_ERROR(SetUpFromYaml(R"(94--- !minidump95Streams:96  - Type:            ThreadList97    Threads:98      - Thread Id:       0x00003E8199        Stack:100          Start of Memory Range: 0x00007FFCEB34A000101          Content:         C84D04BCE97F00102        Context:         00000000000000103...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 119TEST_F(MinidumpParserTest, GetArchitecture) {120  ASSERT_THAT_ERROR(SetUpFromYaml(R"(121--- !minidump122Streams:123  - Type:            SystemInfo124    Processor Arch:  AMD64125    Processor Level: 6126    Processor Revision: 16130127    Number of Processors: 1128    Platform ID:     Linux129    CPU:130      Vendor ID:       GenuineIntel131      Version Info:    0x00000000132      Feature Info:    0x00000000133...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 142TEST_F(MinidumpParserTest, GetMiscInfo_no_stream) {143  // Test that GetMiscInfo returns nullptr when the minidump does not contain144  // this stream.145  ASSERT_THAT_ERROR(SetUpFromYaml(R"(146--- !minidump147Streams:148...149)"),150                    llvm::Succeeded());151  EXPECT_EQ(nullptr, parser->GetMiscInfo());152}153 154TEST_F(MinidumpParserTest, GetLinuxProcStatus) {155  ASSERT_THAT_ERROR(SetUpFromYaml(R"(156--- !minidump157Streams:158  - Type:            SystemInfo159    Processor Arch:  AMD64160    Processor Level: 6161    Processor Revision: 16130162    Number of Processors: 1163    Platform ID:     Linux164    CSD Version:     'Linux 3.13.0-91-generic'165    CPU:166      Vendor ID:       GenuineIntel167      Version Info:    0x00000000168      Feature Info:    0x00000000169  - Type:            LinuxProcStatus170    Text:             |171      Name:	a.out172      State:	t (tracing stop)173      Tgid:	16001174      Ngid:	0175      Pid:	16001176      PPid:	13243177      TracerPid:	16002178      Uid:	404696	404696	404696	404696179      Gid:	5762	5762	5762	5762180...181)"),182                    llvm::Succeeded());183  std::optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();184  ASSERT_TRUE(proc_status.has_value());185  lldb::pid_t pid = proc_status->GetPid();186  ASSERT_EQ(16001UL, pid);187}188 189TEST_F(MinidumpParserTest, GetPid) {190  ASSERT_THAT_ERROR(SetUpFromYaml(R"(191--- !minidump192Streams:193  - Type:            SystemInfo194    Processor Arch:  AMD64195    Processor Level: 6196    Processor Revision: 16130197    Number of Processors: 1198    Platform ID:     Linux199    CSD Version:     'Linux 3.13.0-91-generic'200    CPU:201      Vendor ID:       GenuineIntel202      Version Info:    0x00000000203      Feature Info:    0x00000000204  - Type:            LinuxProcStatus205    Text:             |206      Name:	a.out207      State:	t (tracing stop)208      Tgid:	16001209      Ngid:	0210      Pid:	16001211      PPid:	13243212      TracerPid:	16002213      Uid:	404696	404696	404696	404696214      Gid:	5762	5762	5762	5762215...216)"),217                    llvm::Succeeded());218  std::optional<lldb::pid_t> pid = parser->GetPid();219  ASSERT_TRUE(pid.has_value());220  ASSERT_EQ(16001UL, *pid);221}222 223TEST_F(MinidumpParserTest, GetFilteredModuleList) {224  ASSERT_THAT_ERROR(SetUpFromYaml(R"(225--- !minidump226Streams:227  - Type:            ModuleList228    Modules:229      - Base of Image:   0x0000000000400000230        Size of Image:   0x00001000231        Module Name:     '/tmp/test/linux-x86_64_not_crashed'232        CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611233      - Base of Image:   0x0000000000600000234        Size of Image:   0x00002000235        Module Name:     '/tmp/test/linux-x86_64_not_crashed'236        CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611237...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 250TEST_F(MinidumpParserTest, GetExceptionStream) {251  SetUpData("linux-x86_64.dmp");252  auto exception_streams = parser->GetExceptionStreams();253  size_t count = 0;254  for (auto exception_stream : exception_streams) {255    ASSERT_THAT_EXPECTED(exception_stream, llvm::Succeeded());256    ASSERT_EQ(16001UL, exception_stream->ThreadId);257    count++;258  }259 260  ASSERT_THAT(1UL, count);261}262 263void check_mem_range_exists(MinidumpParser &parser, const uint64_t range_start,264                            const uint64_t range_size) {265  std::optional<minidump::Range> range = parser.FindMemoryRange(range_start);266  ASSERT_TRUE(range.has_value()) << "There is no range containing this address";267  EXPECT_EQ(range_start, range->start);268  EXPECT_EQ(range_start + range_size, range->start + range->range_ref.size());269}270 271TEST_F(MinidumpParserTest, FindMemoryRange) {272  ASSERT_THAT_ERROR(SetUpFromYaml(R"(273--- !minidump274Streams:275  - Type:            MemoryList276    Memory Ranges:277      - Start of Memory Range: 0x00007FFCEB34A000278        Content:         C84D04BCE9279      - Start of Memory Range: 0x0000000000401D46280        Content:         5421281...282)"),283                    llvm::Succeeded());284  EXPECT_EQ(std::nullopt, parser->FindMemoryRange(0x00));285  EXPECT_EQ(std::nullopt, parser->FindMemoryRange(0x2a));286  EXPECT_EQ((minidump::Range{0x401d46, llvm::ArrayRef<uint8_t>{0x54, 0x21}}),287            parser->FindMemoryRange(0x401d46));288  EXPECT_EQ(std::nullopt, parser->FindMemoryRange(0x401d46 + 2));289 290  EXPECT_EQ(291      (minidump::Range{0x7ffceb34a000,292                       llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}}),293      parser->FindMemoryRange(0x7ffceb34a000 + 2));294  EXPECT_EQ(std::nullopt, parser->FindMemoryRange(0x7ffceb34a000 + 5));295}296 297TEST_F(MinidumpParserTest, GetMemory) {298  ASSERT_THAT_ERROR(SetUpFromYaml(R"(299--- !minidump300Streams:301  - Type:            MemoryList302    Memory Ranges:303      - Start of Memory Range: 0x00007FFCEB34A000304        Content:         C84D04BCE9305      - Start of Memory Range: 0x0000000000401D46306        Content:         5421307...308)"),309                    llvm::Succeeded());310 311  EXPECT_THAT_EXPECTED(parser->GetMemory(0x401d46, 1),312                       llvm::HasValue(llvm::ArrayRef<uint8_t>{0x54}));313  EXPECT_THAT_EXPECTED(parser->GetMemory(0x401d46, 4),314                       llvm::HasValue(llvm::ArrayRef<uint8_t>{0x54, 0x21}));315  EXPECT_THAT_EXPECTED(316      parser->GetMemory(0x7ffceb34a000, 5),317      llvm::HasValue(llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}));318  EXPECT_THAT_EXPECTED(319      parser->GetMemory(0x7ffceb34a000, 3),320      llvm::HasValue(llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04}));321  EXPECT_THAT_EXPECTED(322      parser->GetMemory(0x500000, 512),323      llvm::FailedWithMessage("No memory range found for address (0x500000)"));324}325 326TEST_F(MinidumpParserTest, FindMemoryRangeWithFullMemoryMinidump) {327  SetUpData("fizzbuzz_wow64.dmp");328 329  // There are a lot of ranges in the file, just testing with some of them330  EXPECT_FALSE(parser->FindMemoryRange(0x00).has_value());331  EXPECT_FALSE(parser->FindMemoryRange(0x2a).has_value());332  check_mem_range_exists(*parser, 0x10000, 65536); // first range333  check_mem_range_exists(*parser, 0x40000, 4096);334  EXPECT_FALSE(parser->FindMemoryRange(0x40000 + 4096).has_value());335  check_mem_range_exists(*parser, 0x77c12000, 8192);336  check_mem_range_exists(*parser, 0x7ffe0000, 4096); // last range337  EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).has_value());338}339 340constexpr auto yes = MemoryRegionInfo::eYes;341constexpr auto no = MemoryRegionInfo::eNo;342constexpr auto unknown = MemoryRegionInfo::eDontKnow;343 344TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {345  ASSERT_THAT_ERROR(SetUpFromYaml(R"(346--- !minidump347Streams:348  - Type:            MemoryInfoList349    Memory Ranges:350      - Base Address:    0x0000000000000000351        Allocation Protect: [  ]352        Region Size:     0x0000000000010000353        State:           [ MEM_FREE ]354        Protect:         [ PAGE_NO_ACCESS ]355        Type:            [  ]356      - Base Address:    0x0000000000010000357        Allocation Protect: [ PAGE_READ_WRITE ]358        Region Size:     0x0000000000021000359        State:           [ MEM_COMMIT ]360        Type:            [ MEM_MAPPED ]361      - Base Address:    0x0000000000040000362        Allocation Protect: [ PAGE_EXECUTE_WRITE_COPY ]363        Region Size:     0x0000000000001000364        State:           [ MEM_COMMIT ]365        Protect:         [ PAGE_READ_ONLY ]366        Type:            [ MEM_IMAGE ]367      - Base Address:    0x000000007FFE0000368        Allocation Protect: [ PAGE_READ_ONLY ]369        Region Size:     0x0000000000001000370        State:           [ MEM_COMMIT ]371        Type:            [ MEM_PRIVATE ]372      - Base Address:    0x000000007FFE1000373        Allocation Base: 0x000000007FFE0000374        Allocation Protect: [ PAGE_READ_ONLY ]375        Region Size:     0x000000000000F000376        State:           [ MEM_RESERVE ]377        Protect:         [ PAGE_NO_ACCESS ]378        Type:            [ MEM_PRIVATE ]379...380)"),381                    llvm::Succeeded());382 383  EXPECT_THAT(384      parser->BuildMemoryRegions(),385      testing::Pair(testing::ElementsAre(386                        MemoryRegionInfo({0x0, 0x10000}, no, no, no, unknown,387                                         no, ConstString(), unknown, 0, unknown,388                                         unknown, unknown),389                        MemoryRegionInfo({0x10000, 0x21000}, yes, yes, no,390                                         unknown, yes, ConstString(), unknown,391                                         0, unknown, unknown, unknown),392                        MemoryRegionInfo({0x40000, 0x1000}, yes, no, no,393                                         unknown, yes, ConstString(), unknown,394                                         0, unknown, unknown, unknown),395                        MemoryRegionInfo({0x7ffe0000, 0x1000}, yes, no, no,396                                         unknown, yes, ConstString(), unknown,397                                         0, unknown, unknown, unknown),398                        MemoryRegionInfo({0x7ffe1000, 0xf000}, no, no, no,399                                         unknown, yes, ConstString(), unknown,400                                         0, unknown, unknown, unknown)),401                    true));402}403 404TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {405  ASSERT_THAT_ERROR(SetUpFromYaml(R"(406--- !minidump407Streams:408  - Type:            MemoryList409    Memory Ranges:410      - Start of Memory Range: 0x0000000000001000411        Content:         '31313131313131313131313131313131'412      - Start of Memory Range: 0x0000000000002000413        Content:         '3333333333333333333333333333333333333333333333333333333333333333'414...415)"),416                    llvm::Succeeded());417 418  // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when419  // we don't have a MemoryInfoListStream.420 421  EXPECT_THAT(422      parser->BuildMemoryRegions(),423      testing::Pair(testing::ElementsAre(424                        MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,425                                         unknown, yes, ConstString(), unknown,426                                         0, unknown, unknown, unknown),427                        MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,428                                         unknown, yes, ConstString(), unknown,429                                         0, unknown, unknown, unknown)),430                    false));431}432 433TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {434  SetUpData("regions-memlist64.dmp");435 436  // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when437  // we don't have a MemoryInfoListStream.438  EXPECT_THAT(439      parser->BuildMemoryRegions(),440      testing::Pair(testing::ElementsAre(441                        MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,442                                         unknown, yes, ConstString(), unknown,443                                         0, unknown, unknown, unknown),444                        MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,445                                         unknown, yes, ConstString(), unknown,446                                         0, unknown, unknown, unknown)),447                    false));448}449 450TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {451  ASSERT_THAT_ERROR(SetUpFromYaml(R"(452--- !minidump453Streams:454  - Type:            LinuxMaps455    Text:             |456      400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process457      400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process458      400dc000-400dd000 rw-p 00000000 00:00 0459      400ec000-400ed000 r--p 00000000 00:00 0460      400ee000-400ef000 rw-p 00010000 b3:04 300        /system/bin/linker461      400fc000-400fd000 rwxp 00001000 b3:04 1096       /system/lib/liblog.so462 463...464)"),465                    llvm::Succeeded());466  // Test we can get memory regions from the linux /proc/<pid>/maps stream when467  // we don't have a MemoryInfoListStream.468  ConstString app_process("/system/bin/app_process");469  ConstString linker("/system/bin/linker");470  ConstString liblog("/system/lib/liblog.so");471  EXPECT_THAT(472      parser->BuildMemoryRegions(),473      testing::Pair(474          testing::ElementsAre(475              MemoryRegionInfo({0x400d9000, 0x2000}, yes, no, yes, no, yes,476                               app_process, unknown, 0, unknown, unknown,477                               unknown),478              MemoryRegionInfo({0x400db000, 0x1000}, yes, no, no, no, yes,479                               app_process, unknown, 0, unknown, unknown,480                               unknown),481              MemoryRegionInfo({0x400dc000, 0x1000}, yes, yes, no, no, yes,482                               ConstString(), unknown, 0, unknown, unknown,483                               unknown),484              MemoryRegionInfo({0x400ec000, 0x1000}, yes, no, no, no, yes,485                               ConstString(), unknown, 0, unknown, unknown,486                               unknown),487              MemoryRegionInfo({0x400ee000, 0x1000}, yes, yes, no, no, yes,488                               linker, unknown, 0, unknown, unknown, unknown),489              MemoryRegionInfo({0x400fc000, 0x1000}, yes, yes, yes, no, yes,490                               liblog, unknown, 0, unknown, unknown, unknown)),491          true));492}493 494TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMapsError) {495  ASSERT_THAT_ERROR(SetUpFromYaml(R"(496--- !minidump497Streams:498  - Type:            LinuxMaps499    Text:             |500      400d9000-400db000 r?xp 00000000 b3:04 227501      400fc000-400fd000 rwxp 00001000 b3:04 1096502...503)"),504                    llvm::Succeeded());505  // Test that when a /proc/maps region fails to parse506  // we handle the error and continue with the rest.507  EXPECT_THAT(parser->BuildMemoryRegions(),508              testing::Pair(testing::ElementsAre(MemoryRegionInfo(509                                {0x400fc000, 0x1000}, yes, yes, yes, no, yes,510                                ConstString(nullptr), unknown, 0, unknown,511                                unknown, unknown)),512                            true));513}514 515// Windows Minidump tests516TEST_F(MinidumpParserTest, GetArchitectureWindows) {517  ASSERT_THAT_ERROR(SetUpFromYaml(R"(518--- !minidump519Streams:520  - Type:            SystemInfo521    Processor Arch:  X86522    Processor Level: 6523    Processor Revision: 15876524    Number of Processors: 32525    Product type:    1526    Major Version:   6527    Minor Version:   1528    Build Number:    7601529    Platform ID:     Win32NT530    CSD Version:     Service Pack 1531    Suite Mask:      0x0100532    CPU:533      Vendor ID:       GenuineIntel534      Version Info:    0x000306E4535      Feature Info:    0xBFEBFBFF536      AMD Extended Features: 0x771EEC80537...538)"),539                    llvm::Succeeded());540  ASSERT_EQ(llvm::Triple::ArchType::x86,541            parser->GetArchitecture().GetMachine());542  ASSERT_EQ(llvm::Triple::OSType::Win32,543            parser->GetArchitecture().GetTriple().getOS());544}545 546TEST_F(MinidumpParserTest, GetLinuxProcStatus_no_stream) {547  // Test that GetLinuxProcStatus returns nullptr when the minidump does not548  // contain this stream.549  ASSERT_THAT_ERROR(SetUpFromYaml(R"(550--- !minidump551Streams:552...553)"),554                    llvm::Succeeded());555  EXPECT_EQ(std::nullopt, parser->GetLinuxProcStatus());556}557 558TEST_F(MinidumpParserTest, GetMiscInfoWindows) {559  SetUpData("fizzbuzz_no_heap.dmp");560  const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();561  ASSERT_NE(nullptr, misc_info);562  std::optional<lldb::pid_t> pid = misc_info->GetPid();563  ASSERT_TRUE(pid.has_value());564  ASSERT_EQ(4440UL, *pid);565}566 567TEST_F(MinidumpParserTest, GetPidWindows) {568  SetUpData("fizzbuzz_no_heap.dmp");569  std::optional<lldb::pid_t> pid = parser->GetPid();570  ASSERT_TRUE(pid.has_value());571  ASSERT_EQ(4440UL, *pid);572}573 574// wow64575TEST_F(MinidumpParserTest, GetPidWow64) {576  SetUpData("fizzbuzz_wow64.dmp");577  std::optional<lldb::pid_t> pid = parser->GetPid();578  ASSERT_TRUE(pid.has_value());579  ASSERT_EQ(7836UL, *pid);580}581 582// Register tests583#define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x))584#define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x))585 586TEST_F(MinidumpParserTest, GetThreadContext_x86_32) {587  ASSERT_THAT_ERROR(SetUpFromYaml(R"(588--- !minidump589Streams:590  - Type:            ThreadList591    Threads:592      - Thread Id:       0x00026804593        Stack:594          Start of Memory Range: 0x00000000FF9DD000595          Content:         68D39DFF596        Context:         0F0001000000000000000000000000000000000000000000000000007F03FFFF0000FFFFFFFFFFFF09DC62F72300000088E36CF72B00FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063000000000000002B0000002B000000A88204085CD59DFF008077F7A3D49DFF01000000000000003CD59DFFA082040823000000820201002CD59DFF2B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000597)"),598                    llvm::Succeeded());599 600  llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();601  const minidump::Thread &thread = thread_list[0];602  llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));603  const MinidumpContext_x86_32 *context;604  EXPECT_TRUE(consumeObject(registers, context).Success());605 606  EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),607            MinidumpContext_x86_32_Flags::x86_32_Flag |608                MinidumpContext_x86_32_Flags::Full |609                MinidumpContext_x86_32_Flags::FloatingPoint);610 611  EXPECT_EQ(0x00000000u, context->eax);612  EXPECT_EQ(0xf7778000u, context->ebx);613  EXPECT_EQ(0x00000001u, context->ecx);614  EXPECT_EQ(0xff9dd4a3u, context->edx);615  EXPECT_EQ(0x080482a8u, context->edi);616  EXPECT_EQ(0xff9dd55cu, context->esi);617  EXPECT_EQ(0xff9dd53cu, context->ebp);618  EXPECT_EQ(0xff9dd52cu, context->esp);619  EXPECT_EQ(0x080482a0u, context->eip);620  EXPECT_EQ(0x00010282u, context->eflags);621  EXPECT_EQ(0x0023u, context->cs);622  EXPECT_EQ(0x0000u, context->fs);623  EXPECT_EQ(0x0063u, context->gs);624  EXPECT_EQ(0x002bu, context->ss);625  EXPECT_EQ(0x002bu, context->ds);626  EXPECT_EQ(0x002bu, context->es);627}628 629TEST_F(MinidumpParserTest, GetThreadContext_x86_64) {630  ASSERT_THAT_ERROR(SetUpFromYaml(R"(631--- !minidump632Streams:633  - Type:            ThreadList634    Threads:635      - Thread Id:       0x00003E81636        Stack:637          Start of Memory Range: 0x00007FFCEB34A000638          Content:         C84D04BCE97F00639        Context:         0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640...641)"),642                    llvm::Succeeded());643  llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();644  const minidump::Thread &thread = thread_list[0];645  llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));646  const MinidumpContext_x86_64 *context;647  EXPECT_TRUE(consumeObject(registers, context).Success());648 649  EXPECT_EQ(MinidumpContext_x86_64_Flags(uint32_t(context->context_flags)),650            MinidumpContext_x86_64_Flags::x86_64_Flag |651                MinidumpContext_x86_64_Flags::Control |652                MinidumpContext_x86_64_Flags::FloatingPoint |653                MinidumpContext_x86_64_Flags::Integer);654  EXPECT_EQ(0x0000000000000000u, context->rax);655  EXPECT_EQ(0x0000000000000000u, context->rbx);656  EXPECT_EQ(0x0000000000000010u, context->rcx);657  EXPECT_EQ(0x0000000000000000u, context->rdx);658  EXPECT_EQ(0x00007ffceb349cf0u, context->rdi);659  EXPECT_EQ(0x0000000000000000u, context->rsi);660  EXPECT_EQ(0x00007ffceb34a210u, context->rbp);661  EXPECT_EQ(0x00007ffceb34a210u, context->rsp);662  EXPECT_EQ(0x00007fe9bc1aa9c0u, context->r8);663  EXPECT_EQ(0x0000000000000000u, context->r9);664  EXPECT_EQ(0x00007fe9bc3f16a0u, context->r10);665  EXPECT_EQ(0x0000000000000246u, context->r11);666  EXPECT_EQ(0x0000000000401c92u, context->r12);667  EXPECT_EQ(0x00007ffceb34a430u, context->r13);668  EXPECT_EQ(0x0000000000000000u, context->r14);669  EXPECT_EQ(0x0000000000000000u, context->r15);670  EXPECT_EQ(0x0000000000401dc6u, context->rip);671  EXPECT_EQ(0x00010206u, context->eflags);672  EXPECT_EQ(0x0033u, context->cs);673  EXPECT_EQ(0x0000u, context->ss);674}675 676TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) {677  SetUpData("fizzbuzz_wow64.dmp");678  llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();679  const minidump::Thread &thread = thread_list[0];680  llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread));681  const MinidumpContext_x86_32 *context;682  EXPECT_TRUE(consumeObject(registers, context).Success());683 684  EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),685            MinidumpContext_x86_32_Flags::x86_32_Flag |686                MinidumpContext_x86_32_Flags::Full |687                MinidumpContext_x86_32_Flags::FloatingPoint |688                MinidumpContext_x86_32_Flags::ExtendedRegisters);689 690  EXPECT_EQ(0x00000000u, context->eax);691  EXPECT_EQ(0x0037f608u, context->ebx);692  EXPECT_EQ(0x00e61578u, context->ecx);693  EXPECT_EQ(0x00000008u, context->edx);694  EXPECT_EQ(0x00000000u, context->edi);695  EXPECT_EQ(0x00000002u, context->esi);696  EXPECT_EQ(0x0037f654u, context->ebp);697  EXPECT_EQ(0x0037f5b8u, context->esp);698  EXPECT_EQ(0x77ce01fdu, context->eip);699  EXPECT_EQ(0x00000246u, context->eflags);700  EXPECT_EQ(0x0023u, context->cs);701  EXPECT_EQ(0x0053u, context->fs);702  EXPECT_EQ(0x002bu, context->gs);703  EXPECT_EQ(0x002bu, context->ss);704  EXPECT_EQ(0x002bu, context->ds);705  EXPECT_EQ(0x002bu, context->es);706}707 708TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) {709  ASSERT_THAT_ERROR(SetUpFromYaml(R"(710--- !minidump711Streams:712  - Type:            ModuleList713    Modules:714      - Base of Image:   0x0000000000002000715        Size of Image:   0x00001000716        Module Name:     '/tmp/a'717        CodeView Record: ''718      - Base of Image:   0x0000000000001000719        Size of Image:   0x00001000720        Module Name:     '/tmp/a'721        CodeView Record: ''722...723)"),724                    llvm::Succeeded());725  // If we have a module mentioned twice in the module list, the filtered726  // module list should contain the instance with the lowest BaseOfImage.727  std::vector<const minidump::Module *> filtered_modules =728      parser->GetFilteredModuleList();729  ASSERT_EQ(1u, filtered_modules.size());730  EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->BaseOfImage);731}732 733TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMappedFirst) {734  ASSERT_THAT_ERROR(SetUpFromYaml(R"(735--- !minidump736Streams:737  - Type:            ModuleList738    Modules:739      - Base of Image:   0x400d0000740        Size of Image:   0x00002000741        Module Name:     '/usr/lib/libc.so'742        CodeView Record: ''743      - Base of Image:   0x400d3000744        Size of Image:   0x00001000745        Module Name:     '/usr/lib/libc.so'746        CodeView Record: ''747  - Type:            LinuxMaps748    Text:             |749      400d0000-400d2000 r--p 00000000 b3:04 227        /usr/lib/libc.so750      400d2000-400d3000 rw-p 00000000 00:00 0751      400d3000-400d4000 r-xp 00010000 b3:04 227        /usr/lib/libc.so752      400d4000-400d5000 rwxp 00001000 b3:04 227        /usr/lib/libc.so753...754)"),755                    llvm::Succeeded());756  // If we have a module mentioned twice in the module list, and we have full757  // linux maps for all of the memory regions, make sure we pick the one that758  // has a consecutive region with a matching path that has executable759  // permissions. If clients open an object file with mmap, breakpad can create760  // multiple mappings for a library errnoneously and the lowest address isn't761  // always the right address. In this case we check the consective memory762  // regions whose path matches starting at the base of image address and make763  // sure one of the regions is executable and prefer that one.764  //765  // This test will make sure that if the executable is second in the module766  // list, that it will become the selected module in the filtered list.767  std::vector<const minidump::Module *> filtered_modules =768      parser->GetFilteredModuleList();769  ASSERT_EQ(1u, filtered_modules.size());770  EXPECT_EQ(0x400d3000u, filtered_modules[0]->BaseOfImage);771}772 773TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMappedSecond) {774  ASSERT_THAT_ERROR(SetUpFromYaml(R"(775--- !minidump776Streams:777  - Type:            ModuleList778    Modules:779      - Base of Image:   0x400d0000780        Size of Image:   0x00002000781        Module Name:     '/usr/lib/libc.so'782        CodeView Record: ''783      - Base of Image:   0x400d3000784        Size of Image:   0x00001000785        Module Name:     '/usr/lib/libc.so'786        CodeView Record: ''787  - Type:            LinuxMaps788    Text:             |789      400d0000-400d1000 r-xp 00010000 b3:04 227        /usr/lib/libc.so790      400d1000-400d2000 rwxp 00001000 b3:04 227        /usr/lib/libc.so791      400d2000-400d3000 rw-p 00000000 00:00 0792      400d3000-400d5000 r--p 00000000 b3:04 227        /usr/lib/libc.so793...794)"),795                    llvm::Succeeded());796  // If we have a module mentioned twice in the module list, and we have full797  // linux maps for all of the memory regions, make sure we pick the one that798  // has a consecutive region with a matching path that has executable799  // permissions. If clients open an object file with mmap, breakpad can create800  // multiple mappings for a library errnoneously and the lowest address isn't801  // always the right address. In this case we check the consective memory802  // regions whose path matches starting at the base of image address and make803  // sure one of the regions is executable and prefer that one.804  //805  // This test will make sure that if the executable is first in the module806  // list, that it will remain the correctly selected module in the filtered807  // list.808  std::vector<const minidump::Module *> filtered_modules =809      parser->GetFilteredModuleList();810  ASSERT_EQ(1u, filtered_modules.size());811  EXPECT_EQ(0x400d0000u, filtered_modules[0]->BaseOfImage);812}813 814TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMappedSecondHigh) {815  ASSERT_THAT_ERROR(SetUpFromYaml(R"(816--- !minidump817Streams:818  - Type:            ModuleList819    Modules:820      - Base of Image:   0x400d3000821        Size of Image:   0x00002000822        Module Name:     '/usr/lib/libc.so'823        CodeView Record: ''824      - Base of Image:   0x400d0000825        Size of Image:   0x00001000826        Module Name:     '/usr/lib/libc.so'827        CodeView Record: ''828  - Type:            LinuxMaps829    Text:             |830      400d0000-400d2000 r--p 00000000 b3:04 227        /usr/lib/libc.so831      400d2000-400d3000 rw-p 00000000 00:00 0832      400d3000-400d4000 r-xp 00010000 b3:04 227        /usr/lib/libc.so833      400d4000-400d5000 rwxp 00001000 b3:04 227        /usr/lib/libc.so834...835)"),836                    llvm::Succeeded());837  // If we have a module mentioned twice in the module list, and we have full838  // linux maps for all of the memory regions, make sure we pick the one that839  // has a consecutive region with a matching path that has executable840  // permissions. If clients open an object file with mmap, breakpad can create841  // multiple mappings for a library errnoneously and the lowest address isn't842  // always the right address. In this case we check the consective memory843  // regions whose path matches starting at the base of image address and make844  // sure one of the regions is executable and prefer that one.845  //846  // This test will make sure that if the executable is first in the module847  // list, that it will remain the correctly selected module in the filtered848  // list, even if the non-executable module was loaded at a lower base address.849  std::vector<const minidump::Module *> filtered_modules =850      parser->GetFilteredModuleList();851  ASSERT_EQ(1u, filtered_modules.size());852  EXPECT_EQ(0x400d3000u, filtered_modules[0]->BaseOfImage);853}854 855TEST_F(MinidumpParserTest, MinidumpDuplicateModuleSeparateCode) {856  ASSERT_THAT_ERROR(SetUpFromYaml(R"(857--- !minidump858Streams:859  - Type:            ModuleList860    Modules:861      - Base of Image:   0x400d0000862        Size of Image:   0x00002000863        Module Name:     '/usr/lib/libc.so'864        CodeView Record: ''865      - Base of Image:   0x400d5000866        Size of Image:   0x00001000867        Module Name:     '/usr/lib/libc.so'868        CodeView Record: ''869  - Type:            LinuxMaps870    Text:             |871      400d0000-400d3000 r--p 00000000 b3:04 227        /usr/lib/libc.so872      400d3000-400d5000 rw-p 00000000 00:00 0873      400d5000-400d6000 r--p 00000000 b3:04 227        /usr/lib/libc.so874      400d6000-400d7000 r-xp 00010000 b3:04 227        /usr/lib/libc.so875      400d7000-400d8000 rwxp 00001000 b3:04 227        /usr/lib/libc.so876...877)"),878                    llvm::Succeeded());879  // If we have a module mentioned twice in the module list, and we have full880  // linux maps for all of the memory regions, make sure we pick the one that881  // has a consecutive region with a matching path that has executable882  // permissions. If clients open an object file with mmap, breakpad can create883  // multiple mappings for a library errnoneously and the lowest address isn't884  // always the right address. In this case we check the consective memory885  // regions whose path matches starting at the base of image address and make886  // sure one of the regions is executable and prefer that one.887  //888  // This test will make sure if binaries are compiled with "-z separate-code",889  // where the first region for a binary won't be marked as executable, that890  // it gets selected by detecting the second consecutive mapping at 0x400d7000891  // when asked about the a module mamed "/usr/lib/libc.so" at 0x400d5000.892  std::vector<const minidump::Module *> filtered_modules =893      parser->GetFilteredModuleList();894  ASSERT_EQ(1u, filtered_modules.size());895  EXPECT_EQ(0x400d5000u, filtered_modules[0]->BaseOfImage);896}897 898TEST_F(MinidumpParserTest, MinidumpModuleOrder) {899  ASSERT_THAT_ERROR(SetUpFromYaml(R"(900--- !minidump901Streams:902  - Type:            ModuleList903    Modules:904      - Base of Image:   0x0000000000002000905        Size of Image:   0x00001000906        Module Name:     '/tmp/a'907        CodeView Record: ''908      - Base of Image:   0x0000000000001000909        Size of Image:   0x00001000910        Module Name:     '/tmp/b'911        CodeView Record: ''912...913)"),914                    llvm::Succeeded());915  // Test module filtering does not affect the overall module order.  Previous916  // versions of the MinidumpParser::GetFilteredModuleList() function would sort917  // all images by address and modify the order of the modules.918  std::vector<const minidump::Module *> filtered_modules =919      parser->GetFilteredModuleList();920  ASSERT_EQ(2u, filtered_modules.size());921  EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->BaseOfImage);922  EXPECT_THAT_EXPECTED(923      parser->GetMinidumpFile().getString(filtered_modules[0]->ModuleNameRVA),924      llvm::HasValue("/tmp/a"));925  EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->BaseOfImage);926  EXPECT_THAT_EXPECTED(927      parser->GetMinidumpFile().getString(filtered_modules[1]->ModuleNameRVA),928      llvm::HasValue("/tmp/b"));929}930