1581d79a4SPavel Labath //===- MinidumpTest.cpp - Tests for Minidump.cpp --------------------------===// 2581d79a4SPavel Labath // 3581d79a4SPavel Labath // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4581d79a4SPavel Labath // See https://llvm.org/LICENSE.txt for license information. 5581d79a4SPavel Labath // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6581d79a4SPavel Labath // 7581d79a4SPavel Labath //===----------------------------------------------------------------------===// 8581d79a4SPavel Labath 9581d79a4SPavel Labath #include "llvm/Object/Minidump.h" 10581d79a4SPavel Labath #include "llvm/Support/MemoryBuffer.h" 11581d79a4SPavel Labath #include "llvm/Testing/Support/Error.h" 12581d79a4SPavel Labath #include "gtest/gtest.h" 13581d79a4SPavel Labath 14581d79a4SPavel Labath using namespace llvm; 15581d79a4SPavel Labath using namespace llvm::object; 16581d79a4SPavel Labath using namespace minidump; 17581d79a4SPavel Labath 18581d79a4SPavel Labath static Expected<std::unique_ptr<MinidumpFile>> create(ArrayRef<uint8_t> Data) { 19581d79a4SPavel Labath return MinidumpFile::create( 20581d79a4SPavel Labath MemoryBufferRef(toStringRef(Data), "Test buffer")); 21581d79a4SPavel Labath } 22581d79a4SPavel Labath 23581d79a4SPavel Labath TEST(MinidumpFile, BasicInterface) { 24045b8544SPavel Labath std::vector<uint8_t> Data{ // Header 25045b8544SPavel Labath 'M', 'D', 'M', 'P', // Signature 26045b8544SPavel Labath 0x93, 0xa7, 0, 0, // Version 27581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 28581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 29581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 30581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 31581d79a4SPavel Labath // Stream Directory 32581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 33581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 34581d79a4SPavel Labath // Stream 35045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 36045b8544SPavel Labath // A very simple minidump file which contains just a single stream. 37045b8544SPavel Labath auto ExpectedFile = create(Data); 38581d79a4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 39581d79a4SPavel Labath const MinidumpFile &File = **ExpectedFile; 40581d79a4SPavel Labath const Header &H = File.header(); 41581d79a4SPavel Labath EXPECT_EQ(Header::MagicSignature, H.Signature); 42581d79a4SPavel Labath EXPECT_EQ(Header::MagicVersion, H.Version); 43581d79a4SPavel Labath EXPECT_EQ(1u, H.NumberOfStreams); 44581d79a4SPavel Labath EXPECT_EQ(0x20u, H.StreamDirectoryRVA); 45581d79a4SPavel Labath EXPECT_EQ(0x03020100u, H.Checksum); 46581d79a4SPavel Labath EXPECT_EQ(0x07060504u, H.TimeDateStamp); 47581d79a4SPavel Labath EXPECT_EQ(uint64_t(0x0504030201000908), H.Flags); 48581d79a4SPavel Labath 49581d79a4SPavel Labath ASSERT_EQ(1u, File.streams().size()); 50581d79a4SPavel Labath const Directory &Stream0 = File.streams()[0]; 51581d79a4SPavel Labath EXPECT_EQ(StreamType::LinuxCPUInfo, Stream0.Type); 52581d79a4SPavel Labath EXPECT_EQ(7u, Stream0.Location.DataSize); 53581d79a4SPavel Labath EXPECT_EQ(0x2cu, Stream0.Location.RVA); 54581d79a4SPavel Labath 55581d79a4SPavel Labath EXPECT_EQ("CPUINFO", toStringRef(File.getRawStream(Stream0))); 56581d79a4SPavel Labath EXPECT_EQ("CPUINFO", 57581d79a4SPavel Labath toStringRef(*File.getRawStream(StreamType::LinuxCPUInfo))); 58581d79a4SPavel Labath 59581d79a4SPavel Labath EXPECT_THAT_EXPECTED(File.getSystemInfo(), Failed<BinaryError>()); 60581d79a4SPavel Labath } 61581d79a4SPavel Labath 62581d79a4SPavel Labath // Use the input from the previous test, but corrupt it in various ways 63581d79a4SPavel Labath TEST(MinidumpFile, create_ErrorCases) { 64045b8544SPavel Labath std::vector<uint8_t> FileTooShort{'M', 'D', 'M', 'P'}; 65045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(FileTooShort), Failed<BinaryError>()); 66581d79a4SPavel Labath 67045b8544SPavel Labath std::vector<uint8_t> WrongSignature{ 68045b8544SPavel Labath // Header 69581d79a4SPavel Labath '!', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 70581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 71581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 72581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 73581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 74581d79a4SPavel Labath // Stream Directory 75581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 76581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 77581d79a4SPavel Labath // Stream 78045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 79045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(WrongSignature), Failed<BinaryError>()); 80581d79a4SPavel Labath 81045b8544SPavel Labath std::vector<uint8_t> WrongVersion{ 82045b8544SPavel Labath // Header 83581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x39, 0xa7, 0, 0, // Signature, Version 84581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 85581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 86581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 87581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 88581d79a4SPavel Labath // Stream Directory 89581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 90581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 91581d79a4SPavel Labath // Stream 92045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 93045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(WrongVersion), Failed<BinaryError>()); 94581d79a4SPavel Labath 95045b8544SPavel Labath std::vector<uint8_t> DirectoryAfterEOF{ 96045b8544SPavel Labath // Header 97581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 98581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 99581d79a4SPavel Labath 0x20, 1, 0, 0, // StreamDirectoryRVA 100581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 101581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 102581d79a4SPavel Labath // Stream Directory 103581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 104581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 105581d79a4SPavel Labath // Stream 106045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 107045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(DirectoryAfterEOF), Failed<BinaryError>()); 108581d79a4SPavel Labath 109045b8544SPavel Labath std::vector<uint8_t> TruncatedDirectory{ 110045b8544SPavel Labath // Header 111581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 112581d79a4SPavel Labath 1, 1, 0, 0, // NumberOfStreams, 113581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 114581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 115581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 116581d79a4SPavel Labath // Stream Directory 117581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 118581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 119581d79a4SPavel Labath // Stream 120045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 121045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(TruncatedDirectory), Failed<BinaryError>()); 122581d79a4SPavel Labath 123045b8544SPavel Labath std::vector<uint8_t> Stream0AfterEOF{ 124045b8544SPavel Labath // Header 125581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 126581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 127581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 128581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 129581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 130581d79a4SPavel Labath // Stream Directory 131581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 132581d79a4SPavel Labath 0x2c, 1, 0, 0, // RVA 133581d79a4SPavel Labath // Stream 134045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 135045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(Stream0AfterEOF), Failed<BinaryError>()); 136581d79a4SPavel Labath 137045b8544SPavel Labath std::vector<uint8_t> Stream0Truncated{ 138045b8544SPavel Labath // Header 139581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 140581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 141581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 142581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 143581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 144581d79a4SPavel Labath // Stream Directory 145581d79a4SPavel Labath 3, 0, 0x67, 0x47, 8, 0, 0, 0, // Type, DataSize, 146581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 147581d79a4SPavel Labath // Stream 148045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 149045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(Stream0Truncated), Failed<BinaryError>()); 150581d79a4SPavel Labath 151045b8544SPavel Labath std::vector<uint8_t> DuplicateStream{ 152045b8544SPavel Labath // Header 153581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 154581d79a4SPavel Labath 2, 0, 0, 0, // NumberOfStreams, 155581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 156581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 157581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 158581d79a4SPavel Labath // Stream Directory 159581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 160581d79a4SPavel Labath 0x40, 0, 0, 0, // RVA 161581d79a4SPavel Labath // Stream 162581d79a4SPavel Labath 3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize, 163581d79a4SPavel Labath 0x40, 0, 0, 0, // RVA 164581d79a4SPavel Labath // Stream 165045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 166045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(DuplicateStream), Failed<BinaryError>()); 167581d79a4SPavel Labath 168045b8544SPavel Labath std::vector<uint8_t> DenseMapInfoConflict{ 169045b8544SPavel Labath // Header 170581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 171581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 172581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 173581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 174581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 175581d79a4SPavel Labath // Stream Directory 176581d79a4SPavel Labath 0xff, 0xff, 0xff, 0xff, 7, 0, 0, 0, // Type, DataSize, 177581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 178581d79a4SPavel Labath // Stream 179045b8544SPavel Labath 'C', 'P', 'U', 'I', 'N', 'F', 'O'}; 180045b8544SPavel Labath EXPECT_THAT_EXPECTED(create(DenseMapInfoConflict), Failed<BinaryError>()); 181581d79a4SPavel Labath } 182581d79a4SPavel Labath 183581d79a4SPavel Labath TEST(MinidumpFile, IngoresDummyStreams) { 184045b8544SPavel Labath std::vector<uint8_t> TwoDummyStreams{ 185581d79a4SPavel Labath // Header 186581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 187581d79a4SPavel Labath 2, 0, 0, 0, // NumberOfStreams, 188581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 189581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 190581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 191581d79a4SPavel Labath // Stream Directory 192581d79a4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, DataSize, 193581d79a4SPavel Labath 0x20, 0, 0, 0, // RVA 194581d79a4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, DataSize, 195581d79a4SPavel Labath 0x20, 0, 0, 0, // RVA 196045b8544SPavel Labath }; 197045b8544SPavel Labath auto ExpectedFile = create(TwoDummyStreams); 198581d79a4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 199581d79a4SPavel Labath const MinidumpFile &File = **ExpectedFile; 200581d79a4SPavel Labath ASSERT_EQ(2u, File.streams().size()); 201581d79a4SPavel Labath EXPECT_EQ(StreamType::Unused, File.streams()[0].Type); 202581d79a4SPavel Labath EXPECT_EQ(StreamType::Unused, File.streams()[1].Type); 203b6a01caaSKazu Hirata EXPECT_EQ(std::nullopt, File.getRawStream(StreamType::Unused)); 204581d79a4SPavel Labath } 205581d79a4SPavel Labath 206581d79a4SPavel Labath TEST(MinidumpFile, getSystemInfo) { 207045b8544SPavel Labath std::vector<uint8_t> Data{ 208581d79a4SPavel Labath // Header 209581d79a4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 210581d79a4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 211581d79a4SPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 212581d79a4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 213581d79a4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 214581d79a4SPavel Labath // Stream Directory 215581d79a4SPavel Labath 7, 0, 0, 0, 56, 0, 0, 0, // Type, DataSize, 216581d79a4SPavel Labath 0x2c, 0, 0, 0, // RVA 217581d79a4SPavel Labath // SystemInfo 218581d79a4SPavel Labath 0, 0, 1, 2, // ProcessorArch, ProcessorLevel 219581d79a4SPavel Labath 3, 4, 5, 6, // ProcessorRevision, NumberOfProcessors, ProductType 220581d79a4SPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // MajorVersion, MinorVersion 221581d79a4SPavel Labath 5, 6, 7, 8, 2, 0, 0, 0, // BuildNumber, PlatformId 222581d79a4SPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // CSDVersionRVA, SuiteMask, Reserved 223581d79a4SPavel Labath 'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', // VendorID 224581d79a4SPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // VersionInfo, FeatureInfo 225581d79a4SPavel Labath 9, 0, 1, 2, // AMDExtendedFeatures 226045b8544SPavel Labath }; 227045b8544SPavel Labath auto ExpectedFile = create(Data); 228581d79a4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 229581d79a4SPavel Labath const MinidumpFile &File = **ExpectedFile; 230581d79a4SPavel Labath 231581d79a4SPavel Labath auto ExpectedInfo = File.getSystemInfo(); 232581d79a4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded()); 233581d79a4SPavel Labath const SystemInfo &Info = *ExpectedInfo; 234581d79a4SPavel Labath EXPECT_EQ(ProcessorArchitecture::X86, Info.ProcessorArch); 235581d79a4SPavel Labath EXPECT_EQ(0x0201, Info.ProcessorLevel); 236581d79a4SPavel Labath EXPECT_EQ(0x0403, Info.ProcessorRevision); 237581d79a4SPavel Labath EXPECT_EQ(5, Info.NumberOfProcessors); 238581d79a4SPavel Labath EXPECT_EQ(6, Info.ProductType); 239581d79a4SPavel Labath EXPECT_EQ(0x00090807u, Info.MajorVersion); 240581d79a4SPavel Labath EXPECT_EQ(0x04030201u, Info.MinorVersion); 241581d79a4SPavel Labath EXPECT_EQ(0x08070605u, Info.BuildNumber); 242581d79a4SPavel Labath EXPECT_EQ(OSPlatform::Win32NT, Info.PlatformId); 243581d79a4SPavel Labath EXPECT_EQ(0x04030201u, Info.CSDVersionRVA); 244581d79a4SPavel Labath EXPECT_EQ(0x0605u, Info.SuiteMask); 245581d79a4SPavel Labath EXPECT_EQ(0x0807u, Info.Reserved); 246581d79a4SPavel Labath EXPECT_EQ("LLVMLLVMLLVM", llvm::StringRef(Info.CPU.X86.VendorID, 247581d79a4SPavel Labath sizeof(Info.CPU.X86.VendorID))); 248581d79a4SPavel Labath EXPECT_EQ(0x04030201u, Info.CPU.X86.VersionInfo); 249581d79a4SPavel Labath EXPECT_EQ(0x08070605u, Info.CPU.X86.FeatureInfo); 250581d79a4SPavel Labath EXPECT_EQ(0x02010009u, Info.CPU.X86.AMDExtendedFeatures); 251581d79a4SPavel Labath } 25251d9fa0aSPavel Labath 25351d9fa0aSPavel Labath TEST(MinidumpFile, getString) { 25451d9fa0aSPavel Labath std::vector<uint8_t> ManyStrings{ 25551d9fa0aSPavel Labath // Header 25651d9fa0aSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 25751d9fa0aSPavel Labath 2, 0, 0, 0, // NumberOfStreams, 25851d9fa0aSPavel Labath 0x20, 0, 0, 0, // StreamDirectoryRVA 25951d9fa0aSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 26051d9fa0aSPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // Flags 26151d9fa0aSPavel Labath // Stream Directory 26251d9fa0aSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, DataSize, 26351d9fa0aSPavel Labath 0x20, 0, 0, 0, // RVA 26451d9fa0aSPavel Labath 1, 0, 0, 0, 0, 0, // String1 - odd length 26551d9fa0aSPavel Labath 0, 0, 1, 0, 0, 0, // String2 - too long 26651d9fa0aSPavel Labath 2, 0, 0, 0, 0, 0xd8, // String3 - invalid utf16 26751d9fa0aSPavel Labath 0, 0, 0, 0, 0, 0, // String4 - "" 26851d9fa0aSPavel Labath 2, 0, 0, 0, 'a', 0, // String5 - "a" 26951d9fa0aSPavel Labath 0, // Mis-align next string 27051d9fa0aSPavel Labath 2, 0, 0, 0, 'a', 0, // String6 - "a" 27151d9fa0aSPavel Labath 27251d9fa0aSPavel Labath }; 27351d9fa0aSPavel Labath auto ExpectedFile = create(ManyStrings); 27451d9fa0aSPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 27551d9fa0aSPavel Labath const MinidumpFile &File = **ExpectedFile; 27651d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(44), Failed<BinaryError>()); 27751d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(50), Failed<BinaryError>()); 27851d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(56), Failed<BinaryError>()); 27951d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(62), HasValue("")); 28051d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(68), HasValue("a")); 28151d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(75), HasValue("a")); 28251d9fa0aSPavel Labath 28351d9fa0aSPavel Labath // Check the case when the size field does not fit into the remaining data. 28451d9fa0aSPavel Labath EXPECT_THAT_EXPECTED(File.getString(ManyStrings.size() - 2), 28551d9fa0aSPavel Labath Failed<BinaryError>()); 28651d9fa0aSPavel Labath } 287aaff480cSPavel Labath 288aaff480cSPavel Labath TEST(MinidumpFile, getModuleList) { 289aaff480cSPavel Labath std::vector<uint8_t> OneModule{ 290aaff480cSPavel Labath // Header 291aaff480cSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 292aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 293aaff480cSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 294aaff480cSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 295aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 296aaff480cSPavel Labath // Stream Directory 297aaff480cSPavel Labath 4, 0, 0, 0, 112, 0, 0, 0, // Type, DataSize, 298aaff480cSPavel Labath 44, 0, 0, 0, // RVA 299aaff480cSPavel Labath // ModuleList 300aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfModules 301aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage 302aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum 303aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA 304aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion 305aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileVersion 306aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion 307aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags 308aaff480cSPavel Labath 0, 0, 0, 0, // FileOS 309aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType 310aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileDate 311aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // CvRecord 312aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord 313aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // Reserved0 314aaff480cSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // Reserved1 315aaff480cSPavel Labath }; 316aaff480cSPavel Labath // Same as before, but with a padded module list. 317aaff480cSPavel Labath std::vector<uint8_t> PaddedModule{ 318aaff480cSPavel Labath // Header 319aaff480cSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 320aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 321aaff480cSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 322aaff480cSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 323aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 324aaff480cSPavel Labath // Stream Directory 325aaff480cSPavel Labath 4, 0, 0, 0, 116, 0, 0, 0, // Type, DataSize, 326aaff480cSPavel Labath 44, 0, 0, 0, // RVA 327aaff480cSPavel Labath // ModuleList 328aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfModules 329aaff480cSPavel Labath 0, 0, 0, 0, // Padding 330aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage 331aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum 332aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA 333aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion 334aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileVersion 335aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion 336aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags 337aaff480cSPavel Labath 0, 0, 0, 0, // FileOS 338aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType 339aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileDate 340aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // CvRecord 341aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord 342aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // Reserved0 343aaff480cSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // Reserved1 344aaff480cSPavel Labath }; 345aaff480cSPavel Labath 346cfc4519eSPavel Labath for (ArrayRef<uint8_t> Data : {OneModule, PaddedModule}) { 347aaff480cSPavel Labath auto ExpectedFile = create(Data); 348aaff480cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 349aaff480cSPavel Labath const MinidumpFile &File = **ExpectedFile; 350aaff480cSPavel Labath Expected<ArrayRef<Module>> ExpectedModule = File.getModuleList(); 351aaff480cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedModule, Succeeded()); 352aaff480cSPavel Labath ASSERT_EQ(1u, ExpectedModule->size()); 353aaff480cSPavel Labath const Module &M = ExpectedModule.get()[0]; 354aaff480cSPavel Labath EXPECT_EQ(0x0807060504030201u, M.BaseOfImage); 355aaff480cSPavel Labath EXPECT_EQ(0x02010009u, M.SizeOfImage); 356aaff480cSPavel Labath EXPECT_EQ(0x06050403u, M.Checksum); 357aaff480cSPavel Labath EXPECT_EQ(0x00090807u, M.TimeDateStamp); 358aaff480cSPavel Labath EXPECT_EQ(0x04030201u, M.ModuleNameRVA); 359aaff480cSPavel Labath EXPECT_EQ(0x04030201u, M.CvRecord.DataSize); 360aaff480cSPavel Labath EXPECT_EQ(0x08070605u, M.CvRecord.RVA); 361aaff480cSPavel Labath EXPECT_EQ(0x02010009u, M.MiscRecord.DataSize); 362aaff480cSPavel Labath EXPECT_EQ(0x06050403u, M.MiscRecord.RVA); 363aaff480cSPavel Labath EXPECT_EQ(0x0403020100090807u, M.Reserved0); 364aaff480cSPavel Labath EXPECT_EQ(0x0201000908070605u, M.Reserved1); 365aaff480cSPavel Labath } 366aaff480cSPavel Labath 367aaff480cSPavel Labath std::vector<uint8_t> StreamTooShort{ 368aaff480cSPavel Labath // Header 369aaff480cSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 370aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 371aaff480cSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 372aaff480cSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 373aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 374aaff480cSPavel Labath // Stream Directory 375aaff480cSPavel Labath 4, 0, 0, 0, 111, 0, 0, 0, // Type, DataSize, 376aaff480cSPavel Labath 44, 0, 0, 0, // RVA 377aaff480cSPavel Labath // ModuleList 378aaff480cSPavel Labath 1, 0, 0, 0, // NumberOfModules 379aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage 380aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum 381aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA 382aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion 383aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileVersion 384aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion 385aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags 386aaff480cSPavel Labath 0, 0, 0, 0, // FileOS 387aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType 388aaff480cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // FileDate 389aaff480cSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // CvRecord 390aaff480cSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord 391aaff480cSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // Reserved0 392aaff480cSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // Reserved1 393aaff480cSPavel Labath }; 394aaff480cSPavel Labath auto ExpectedFile = create(StreamTooShort); 395aaff480cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 396aaff480cSPavel Labath const MinidumpFile &File = **ExpectedFile; 397aaff480cSPavel Labath EXPECT_THAT_EXPECTED(File.getModuleList(), Failed<BinaryError>()); 398aaff480cSPavel Labath } 399cfc4519eSPavel Labath 400cfc4519eSPavel Labath TEST(MinidumpFile, getThreadList) { 401cfc4519eSPavel Labath std::vector<uint8_t> OneThread{ 402cfc4519eSPavel Labath // Header 403cfc4519eSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 404cfc4519eSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 405cfc4519eSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 406cfc4519eSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 407cfc4519eSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 408cfc4519eSPavel Labath // Stream Directory 409cfc4519eSPavel Labath 3, 0, 0, 0, 52, 0, 0, 0, // Type, DataSize, 410cfc4519eSPavel Labath 44, 0, 0, 0, // RVA 411cfc4519eSPavel Labath // ThreadList 412cfc4519eSPavel Labath 1, 0, 0, 0, // NumberOfThreads 413cfc4519eSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount 414cfc4519eSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority 415cfc4519eSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock 416cfc4519eSPavel Labath // Stack 417cfc4519eSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange 418cfc4519eSPavel Labath 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA 419cfc4519eSPavel Labath // Context 420cfc4519eSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA 421cfc4519eSPavel Labath }; 422cfc4519eSPavel Labath // Same as before, but with a padded thread list. 423cfc4519eSPavel Labath std::vector<uint8_t> PaddedThread{ 424cfc4519eSPavel Labath // Header 425cfc4519eSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 426cfc4519eSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 427cfc4519eSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 428cfc4519eSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 429cfc4519eSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 430cfc4519eSPavel Labath // Stream Directory 431cfc4519eSPavel Labath 3, 0, 0, 0, 56, 0, 0, 0, // Type, DataSize, 432cfc4519eSPavel Labath 44, 0, 0, 0, // RVA 433cfc4519eSPavel Labath // ThreadList 434cfc4519eSPavel Labath 1, 0, 0, 0, // NumberOfThreads 435cfc4519eSPavel Labath 0, 0, 0, 0, // Padding 436cfc4519eSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount 437cfc4519eSPavel Labath 9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority 438cfc4519eSPavel Labath 7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock 439cfc4519eSPavel Labath // Stack 440cfc4519eSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange 441cfc4519eSPavel Labath 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA 442cfc4519eSPavel Labath // Context 443cfc4519eSPavel Labath 1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA 444cfc4519eSPavel Labath }; 445cfc4519eSPavel Labath 446cfc4519eSPavel Labath for (ArrayRef<uint8_t> Data : {OneThread, PaddedThread}) { 447cfc4519eSPavel Labath auto ExpectedFile = create(Data); 448cfc4519eSPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 449cfc4519eSPavel Labath const MinidumpFile &File = **ExpectedFile; 450cfc4519eSPavel Labath Expected<ArrayRef<Thread>> ExpectedThread = File.getThreadList(); 451cfc4519eSPavel Labath ASSERT_THAT_EXPECTED(ExpectedThread, Succeeded()); 452cfc4519eSPavel Labath ASSERT_EQ(1u, ExpectedThread->size()); 453cfc4519eSPavel Labath const Thread &T = ExpectedThread.get()[0]; 454cfc4519eSPavel Labath EXPECT_EQ(0x04030201u, T.ThreadId); 455cfc4519eSPavel Labath EXPECT_EQ(0x08070605u, T.SuspendCount); 456cfc4519eSPavel Labath EXPECT_EQ(0x02010009u, T.PriorityClass); 457cfc4519eSPavel Labath EXPECT_EQ(0x06050403u, T.Priority); 458cfc4519eSPavel Labath EXPECT_EQ(0x0403020100090807u, T.EnvironmentBlock); 459cfc4519eSPavel Labath EXPECT_EQ(0x0201000908070605u, T.Stack.StartOfMemoryRange); 460cfc4519eSPavel Labath EXPECT_EQ(0x06050403u, T.Stack.Memory.DataSize); 461cfc4519eSPavel Labath EXPECT_EQ(0x00090807u, T.Stack.Memory.RVA); 462cfc4519eSPavel Labath EXPECT_EQ(0x04030201u, T.Context.DataSize); 463cfc4519eSPavel Labath EXPECT_EQ(0x08070605u, T.Context.RVA); 464cfc4519eSPavel Labath } 465cfc4519eSPavel Labath } 4662d29e16cSPavel Labath 4672d29e16cSPavel Labath TEST(MinidumpFile, getMemoryList) { 4682d29e16cSPavel Labath std::vector<uint8_t> OneRange{ 4692d29e16cSPavel Labath // Header 4702d29e16cSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 4712d29e16cSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 4722d29e16cSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 4732d29e16cSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 4742d29e16cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 4752d29e16cSPavel Labath // Stream Directory 4762d29e16cSPavel Labath 5, 0, 0, 0, 20, 0, 0, 0, // Type, DataSize, 4772d29e16cSPavel Labath 44, 0, 0, 0, // RVA 4782d29e16cSPavel Labath // MemoryDescriptor 4792d29e16cSPavel Labath 1, 0, 0, 0, // NumberOfMemoryRanges 4802d29e16cSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange 4812d29e16cSPavel Labath 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA 4822d29e16cSPavel Labath }; 4832d29e16cSPavel Labath // Same as before, but with a padded memory list. 4842d29e16cSPavel Labath std::vector<uint8_t> PaddedRange{ 4852d29e16cSPavel Labath // Header 4862d29e16cSPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 4872d29e16cSPavel Labath 1, 0, 0, 0, // NumberOfStreams, 4882d29e16cSPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 4892d29e16cSPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 4902d29e16cSPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 4912d29e16cSPavel Labath // Stream Directory 4922d29e16cSPavel Labath 5, 0, 0, 0, 24, 0, 0, 0, // Type, DataSize, 4932d29e16cSPavel Labath 44, 0, 0, 0, // RVA 4942d29e16cSPavel Labath // MemoryDescriptor 4952d29e16cSPavel Labath 1, 0, 0, 0, // NumberOfMemoryRanges 4962d29e16cSPavel Labath 0, 0, 0, 0, // Padding 4972d29e16cSPavel Labath 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange 4982d29e16cSPavel Labath 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA 4992d29e16cSPavel Labath }; 5002d29e16cSPavel Labath 5012d29e16cSPavel Labath for (ArrayRef<uint8_t> Data : {OneRange, PaddedRange}) { 5022d29e16cSPavel Labath auto ExpectedFile = create(Data); 5032d29e16cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 5042d29e16cSPavel Labath const MinidumpFile &File = **ExpectedFile; 5052d29e16cSPavel Labath Expected<ArrayRef<MemoryDescriptor>> ExpectedRanges = File.getMemoryList(); 5062d29e16cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedRanges, Succeeded()); 5072d29e16cSPavel Labath ASSERT_EQ(1u, ExpectedRanges->size()); 5082d29e16cSPavel Labath const MemoryDescriptor &MD = ExpectedRanges.get()[0]; 5092d29e16cSPavel Labath EXPECT_EQ(0x0201000908070605u, MD.StartOfMemoryRange); 5102d29e16cSPavel Labath EXPECT_EQ(0x06050403u, MD.Memory.DataSize); 5112d29e16cSPavel Labath EXPECT_EQ(0x00090807u, MD.Memory.RVA); 5122d29e16cSPavel Labath } 5132d29e16cSPavel Labath } 5146e0b1ce4SPavel Labath 5156e0b1ce4SPavel Labath TEST(MinidumpFile, getMemoryInfoList) { 5166e0b1ce4SPavel Labath std::vector<uint8_t> OneEntry{ 5176e0b1ce4SPavel Labath // Header 5186e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 5196e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 5206e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 5216e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 5226e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 5236e0b1ce4SPavel Labath // Stream Directory 5246e0b1ce4SPavel Labath 16, 0, 0, 0, 64, 0, 0, 0, // Type, DataSize, 5256e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 5266e0b1ce4SPavel Labath // MemoryInfoListHeader 5276e0b1ce4SPavel Labath 16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry 5286e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, 0, // NumberOfEntries 5296e0b1ce4SPavel Labath // MemoryInfo 5306e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // BaseAddress 5316e0b1ce4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // AllocationBase 5326e0b1ce4SPavel Labath 16, 0, 0, 0, 6, 7, 8, 9, // AllocationProtect, Reserved0 5336e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // RegionSize 5346e0b1ce4SPavel Labath 0, 16, 0, 0, 32, 0, 0, 0, // State, Protect 5356e0b1ce4SPavel Labath 0, 0, 2, 0, 8, 9, 0, 1, // Type, Reserved1 5366e0b1ce4SPavel Labath }; 5376e0b1ce4SPavel Labath 5386e0b1ce4SPavel Labath // Same as before, but the list header is larger. 5396e0b1ce4SPavel Labath std::vector<uint8_t> BiggerHeader{ 5406e0b1ce4SPavel Labath // Header 5416e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 5426e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 5436e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 5446e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 5456e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 5466e0b1ce4SPavel Labath // Stream Directory 5476e0b1ce4SPavel Labath 16, 0, 0, 0, 68, 0, 0, 0, // Type, DataSize, 5486e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 5496e0b1ce4SPavel Labath // MemoryInfoListHeader 5506e0b1ce4SPavel Labath 20, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry 5516e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, 0, // NumberOfEntries 5526e0b1ce4SPavel Labath 0, 0, 0, 0, // ??? 5536e0b1ce4SPavel Labath // MemoryInfo 5546e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // BaseAddress 5556e0b1ce4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // AllocationBase 5566e0b1ce4SPavel Labath 16, 0, 0, 0, 6, 7, 8, 9, // AllocationProtect, Reserved0 5576e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // RegionSize 5586e0b1ce4SPavel Labath 0, 16, 0, 0, 32, 0, 0, 0, // State, Protect 5596e0b1ce4SPavel Labath 0, 0, 2, 0, 8, 9, 0, 1, // Type, Reserved1 5606e0b1ce4SPavel Labath }; 5616e0b1ce4SPavel Labath 5626e0b1ce4SPavel Labath // Same as before, but the entry is larger. 5636e0b1ce4SPavel Labath std::vector<uint8_t> BiggerEntry{ 5646e0b1ce4SPavel Labath // Header 5656e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 5666e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 5676e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 5686e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 5696e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 5706e0b1ce4SPavel Labath // Stream Directory 5716e0b1ce4SPavel Labath 16, 0, 0, 0, 68, 0, 0, 0, // Type, DataSize, 5726e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 5736e0b1ce4SPavel Labath // MemoryInfoListHeader 5746e0b1ce4SPavel Labath 16, 0, 0, 0, 52, 0, 0, 0, // SizeOfHeader, SizeOfEntry 5756e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, 0, // NumberOfEntries 5766e0b1ce4SPavel Labath // MemoryInfo 5776e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // BaseAddress 5786e0b1ce4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // AllocationBase 5796e0b1ce4SPavel Labath 16, 0, 0, 0, 6, 7, 8, 9, // AllocationProtect, Reserved0 5806e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // RegionSize 5816e0b1ce4SPavel Labath 0, 16, 0, 0, 32, 0, 0, 0, // State, Protect 5826e0b1ce4SPavel Labath 0, 0, 2, 0, 8, 9, 0, 1, // Type, Reserved1 5836e0b1ce4SPavel Labath 0, 0, 0, 0, // ??? 5846e0b1ce4SPavel Labath }; 5856e0b1ce4SPavel Labath 5866e0b1ce4SPavel Labath for (ArrayRef<uint8_t> Data : {OneEntry, BiggerHeader, BiggerEntry}) { 5876e0b1ce4SPavel Labath auto ExpectedFile = create(Data); 5886e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 5896e0b1ce4SPavel Labath const MinidumpFile &File = **ExpectedFile; 5906e0b1ce4SPavel Labath auto ExpectedInfo = File.getMemoryInfoList(); 5916e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded()); 592bff33bd5SMiloš Stojanović ASSERT_EQ(1, std::distance(ExpectedInfo->begin(), ExpectedInfo->end())); 5936e0b1ce4SPavel Labath const MemoryInfo &Info = *ExpectedInfo.get().begin(); 5946e0b1ce4SPavel Labath EXPECT_EQ(0x0706050403020100u, Info.BaseAddress); 5956e0b1ce4SPavel Labath EXPECT_EQ(0x0504030201000908u, Info.AllocationBase); 5966e0b1ce4SPavel Labath EXPECT_EQ(MemoryProtection::Execute, Info.AllocationProtect); 5976e0b1ce4SPavel Labath EXPECT_EQ(0x09080706u, Info.Reserved0); 5986e0b1ce4SPavel Labath EXPECT_EQ(0x0706050403020100u, Info.RegionSize); 5996e0b1ce4SPavel Labath EXPECT_EQ(MemoryState::Commit, Info.State); 6006e0b1ce4SPavel Labath EXPECT_EQ(MemoryProtection::ExecuteRead, Info.Protect); 6016e0b1ce4SPavel Labath EXPECT_EQ(MemoryType::Private, Info.Type); 6026e0b1ce4SPavel Labath EXPECT_EQ(0x01000908u, Info.Reserved1); 6036e0b1ce4SPavel Labath } 6046e0b1ce4SPavel Labath 6056e0b1ce4SPavel Labath // Header does not fit into the stream. 6066e0b1ce4SPavel Labath std::vector<uint8_t> HeaderTooBig{ 6076e0b1ce4SPavel Labath // Header 6086e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 6096e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 6106e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 6116e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 6126e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 6136e0b1ce4SPavel Labath // Stream Directory 6146e0b1ce4SPavel Labath 16, 0, 0, 0, 15, 0, 0, 0, // Type, DataSize, 6156e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 6166e0b1ce4SPavel Labath // MemoryInfoListHeader 6176e0b1ce4SPavel Labath 16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry 6186e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, // ??? 6196e0b1ce4SPavel Labath }; 6206e0b1ce4SPavel Labath Expected<std::unique_ptr<MinidumpFile>> File = create(HeaderTooBig); 6216e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(File, Succeeded()); 6226e0b1ce4SPavel Labath EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>()); 6236e0b1ce4SPavel Labath 6246e0b1ce4SPavel Labath // Header fits into the stream, but it is too small to contain the required 6256e0b1ce4SPavel Labath // entries. 6266e0b1ce4SPavel Labath std::vector<uint8_t> HeaderTooSmall{ 6276e0b1ce4SPavel Labath // Header 6286e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 6296e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 6306e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 6316e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 6326e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 6336e0b1ce4SPavel Labath // Stream Directory 6346e0b1ce4SPavel Labath 16, 0, 0, 0, 15, 0, 0, 0, // Type, DataSize, 6356e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 6366e0b1ce4SPavel Labath // MemoryInfoListHeader 6376e0b1ce4SPavel Labath 15, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry 6386e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, // ??? 6396e0b1ce4SPavel Labath }; 6406e0b1ce4SPavel Labath File = create(HeaderTooSmall); 6416e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(File, Succeeded()); 6426e0b1ce4SPavel Labath EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>()); 6436e0b1ce4SPavel Labath 6446e0b1ce4SPavel Labath std::vector<uint8_t> EntryTooBig{ 6456e0b1ce4SPavel Labath // Header 6466e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 6476e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 6486e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 6496e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 6506e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 6516e0b1ce4SPavel Labath // Stream Directory 6526e0b1ce4SPavel Labath 16, 0, 0, 0, 64, 0, 0, 0, // Type, DataSize, 6536e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 6546e0b1ce4SPavel Labath // MemoryInfoListHeader 6556e0b1ce4SPavel Labath 16, 0, 0, 0, 49, 0, 0, 0, // SizeOfHeader, SizeOfEntry 6566e0b1ce4SPavel Labath 1, 0, 0, 0, 0, 0, 0, 0, // NumberOfEntries 6576e0b1ce4SPavel Labath // MemoryInfo 6586e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // BaseAddress 6596e0b1ce4SPavel Labath 8, 9, 0, 1, 2, 3, 4, 5, // AllocationBase 6606e0b1ce4SPavel Labath 16, 0, 0, 0, 6, 7, 8, 9, // AllocationProtect, Reserved0 6616e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // RegionSize 6626e0b1ce4SPavel Labath 0, 16, 0, 0, 32, 0, 0, 0, // State, Protect 6636e0b1ce4SPavel Labath 0, 0, 2, 0, 8, 9, 0, 1, // Type, Reserved1 6646e0b1ce4SPavel Labath }; 6656e0b1ce4SPavel Labath File = create(EntryTooBig); 6666e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(File, Succeeded()); 6676e0b1ce4SPavel Labath EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>()); 6686e0b1ce4SPavel Labath 6696e0b1ce4SPavel Labath std::vector<uint8_t> ThreeEntries{ 6706e0b1ce4SPavel Labath // Header 6716e0b1ce4SPavel Labath 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 6726e0b1ce4SPavel Labath 1, 0, 0, 0, // NumberOfStreams, 6736e0b1ce4SPavel Labath 32, 0, 0, 0, // StreamDirectoryRVA 6746e0b1ce4SPavel Labath 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 6756e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Flags 6766e0b1ce4SPavel Labath // Stream Directory 6776e0b1ce4SPavel Labath 16, 0, 0, 0, 160, 0, 0, 0, // Type, DataSize, 6786e0b1ce4SPavel Labath 44, 0, 0, 0, // RVA 6796e0b1ce4SPavel Labath // MemoryInfoListHeader 6806e0b1ce4SPavel Labath 16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry 6816e0b1ce4SPavel Labath 3, 0, 0, 0, 0, 0, 0, 0, // NumberOfEntries 6826e0b1ce4SPavel Labath // MemoryInfo 6836e0b1ce4SPavel Labath 0, 1, 2, 3, 0, 0, 0, 0, // BaseAddress 6846e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase 6856e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0 6866e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // RegionSize 6876e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // State, Protect 6886e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1 6896e0b1ce4SPavel Labath 0, 0, 4, 5, 6, 7, 0, 0, // BaseAddress 6906e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase 6916e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0 6926e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // RegionSize 6936e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // State, Protect 6946e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1 6956e0b1ce4SPavel Labath 0, 0, 0, 8, 9, 0, 1, 0, // BaseAddress 6966e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase 6976e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0 6986e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // RegionSize 6996e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // State, Protect 7006e0b1ce4SPavel Labath 0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1 7016e0b1ce4SPavel Labath }; 7026e0b1ce4SPavel Labath File = create(ThreeEntries); 7036e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(File, Succeeded()); 7046e0b1ce4SPavel Labath auto ExpectedInfo = File.get()->getMemoryInfoList(); 7056e0b1ce4SPavel Labath ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded()); 7066e0b1ce4SPavel Labath EXPECT_THAT(to_vector<3>(map_range(*ExpectedInfo, 7076e0b1ce4SPavel Labath [](const MemoryInfo &Info) -> uint64_t { 7086e0b1ce4SPavel Labath return Info.BaseAddress; 7096e0b1ce4SPavel Labath })), 7106e0b1ce4SPavel Labath testing::ElementsAre(0x0000000003020100u, 0x0000070605040000u, 7116e0b1ce4SPavel Labath 0x0001000908000000u)); 7126e0b1ce4SPavel Labath } 713e4452473SJoseph Tremoulet 714*deba1340SJacob Lalonde TEST(MinidumpFile, getExceptionStreams) { 715e4452473SJoseph Tremoulet std::vector<uint8_t> Data{ 716e4452473SJoseph Tremoulet // Header 717e4452473SJoseph Tremoulet 'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version 718e4452473SJoseph Tremoulet 1, 0, 0, 0, // NumberOfStreams, 719e4452473SJoseph Tremoulet 0x20, 0, 0, 0, // StreamDirectoryRVA 720e4452473SJoseph Tremoulet 0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp 721e4452473SJoseph Tremoulet 8, 9, 0, 1, 2, 3, 4, 5, // Flags 722e4452473SJoseph Tremoulet // Stream Directory 723e4452473SJoseph Tremoulet 6, 0, 0, 0, 168, 0, 0, 0, // Type, DataSize, 724e4452473SJoseph Tremoulet 0x2c, 0, 0, 0, // RVA 725e4452473SJoseph Tremoulet // Exception Stream 726e4452473SJoseph Tremoulet 1, 2, 3, 4, // Thread ID 727e4452473SJoseph Tremoulet 0, 0, 0, 0, // Padding 728e4452473SJoseph Tremoulet // Exception Record 729e4452473SJoseph Tremoulet 2, 3, 4, 2, 7, 8, 8, 9, // Code, Flags 730e4452473SJoseph Tremoulet 3, 4, 5, 6, 7, 8, 9, 10, // Inner exception record address 731e4452473SJoseph Tremoulet 8, 7, 6, 5, 4, 3, 2, 1, // Exception address 732e4452473SJoseph Tremoulet 4, 0, 0, 0, 0, 0, 0, 0, // Parameter count, padding 733e4452473SJoseph Tremoulet 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // Parameter 0 734e4452473SJoseph Tremoulet 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // Parameter 1 735e4452473SJoseph Tremoulet 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Parameter 2 736e4452473SJoseph Tremoulet 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, // Parameter 3 737e4452473SJoseph Tremoulet 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // Parameter 4 738e4452473SJoseph Tremoulet 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // Parameter 5 739e4452473SJoseph Tremoulet 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // Parameter 6 740e4452473SJoseph Tremoulet 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // Parameter 7 741e4452473SJoseph Tremoulet 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // Parameter 8 742e4452473SJoseph Tremoulet 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, // Parameter 9 743e4452473SJoseph Tremoulet 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, // Parameter 10 744e4452473SJoseph Tremoulet 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, // Parameter 11 745e4452473SJoseph Tremoulet 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, // Parameter 12 746e4452473SJoseph Tremoulet 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, // Parameter 13 747e4452473SJoseph Tremoulet 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, // Parameter 14 748e4452473SJoseph Tremoulet // Thread Context 749e4452473SJoseph Tremoulet 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // DataSize, RVA 750e4452473SJoseph Tremoulet }; 751e4452473SJoseph Tremoulet auto ExpectedFile = create(Data); 752e4452473SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 753e4452473SJoseph Tremoulet const MinidumpFile &File = **ExpectedFile; 754*deba1340SJacob Lalonde 755*deba1340SJacob Lalonde auto ExceptionStreams = File.getExceptionStreams(); 756*deba1340SJacob Lalonde ASSERT_NE(ExceptionStreams.begin(), ExceptionStreams.end()); 757*deba1340SJacob Lalonde auto ExceptionIterator = ExceptionStreams.begin(); 758*deba1340SJacob Lalonde Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator; 759e4452473SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded()); 760e4452473SJoseph Tremoulet EXPECT_EQ(0x04030201u, ExpectedStream->ThreadId); 761e4452473SJoseph Tremoulet const minidump::Exception &Exception = ExpectedStream->ExceptionRecord; 762e4452473SJoseph Tremoulet EXPECT_EQ(0x02040302u, Exception.ExceptionCode); 763e4452473SJoseph Tremoulet EXPECT_EQ(0x09080807u, Exception.ExceptionFlags); 764e4452473SJoseph Tremoulet EXPECT_EQ(0x0a09080706050403u, Exception.ExceptionRecord); 765e4452473SJoseph Tremoulet EXPECT_EQ(0x0102030405060708u, Exception.ExceptionAddress); 766e4452473SJoseph Tremoulet EXPECT_EQ(4u, Exception.NumberParameters); 767e4452473SJoseph Tremoulet for (uint64_t index = 0; index < Exception.MaxParameters; ++index) { 768e4452473SJoseph Tremoulet EXPECT_EQ(0x1716151413121110u + index * 0x1010101010101010u, 769e4452473SJoseph Tremoulet Exception.ExceptionInformation[index]); 770e4452473SJoseph Tremoulet } 771e4452473SJoseph Tremoulet EXPECT_EQ(0x84838281, ExpectedStream->ThreadContext.DataSize); 772e4452473SJoseph Tremoulet EXPECT_EQ(0x88878685, ExpectedStream->ThreadContext.RVA); 773*deba1340SJacob Lalonde ++ExceptionIterator; 774*deba1340SJacob Lalonde ASSERT_EQ(ExceptionIterator, ExceptionStreams.end()); 775e4452473SJoseph Tremoulet } 776