169de7a95SPavel Labath //===- MinidumpYAMLTest.cpp - Tests for Minidump<->YAML code --------------===// 269de7a95SPavel Labath // 369de7a95SPavel Labath // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 469de7a95SPavel Labath // See https://llvm.org/LICENSE.txt for license information. 569de7a95SPavel Labath // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 669de7a95SPavel Labath // 769de7a95SPavel Labath //===----------------------------------------------------------------------===// 869de7a95SPavel Labath 969de7a95SPavel Labath #include "llvm/Object/Minidump.h" 1082275ec5SPavel Labath #include "llvm/ObjectYAML/yaml2obj.h" 1182275ec5SPavel Labath #include "llvm/Support/YAMLTraits.h" 1269de7a95SPavel Labath #include "llvm/Testing/Support/Error.h" 1369de7a95SPavel Labath #include "gtest/gtest.h" 1469de7a95SPavel Labath 1569de7a95SPavel Labath using namespace llvm; 1669de7a95SPavel Labath using namespace llvm::minidump; 1769de7a95SPavel Labath 1869de7a95SPavel Labath static Expected<std::unique_ptr<object::MinidumpFile>> 1969de7a95SPavel Labath toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) { 2069de7a95SPavel Labath Storage.clear(); 2169de7a95SPavel Labath raw_svector_ostream OS(Storage); 2282275ec5SPavel Labath yaml::Input YIn(Yaml); 2385011027SGeorge Rimar if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 2485011027SGeorge Rimar return createStringError(std::errc::invalid_argument, 2585011027SGeorge Rimar "unable to convert YAML"); 2669de7a95SPavel Labath 2769de7a95SPavel Labath return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary")); 2869de7a95SPavel Labath } 2969de7a95SPavel Labath 3069de7a95SPavel Labath TEST(MinidumpYAML, Basic) { 3169de7a95SPavel Labath SmallString<0> Storage; 3269de7a95SPavel Labath auto ExpectedFile = toBinary(Storage, R"( 3369de7a95SPavel Labath --- !minidump 3469de7a95SPavel Labath Streams: 3569de7a95SPavel Labath - Type: SystemInfo 36e9430231SPavel Labath Processor Arch: ARM64 3769de7a95SPavel Labath Platform ID: Linux 3869de7a95SPavel Labath CPU: 3969de7a95SPavel Labath CPUID: 0x05060708 4069de7a95SPavel Labath - Type: LinuxMaps 4169de7a95SPavel Labath Text: | 4269de7a95SPavel Labath 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process 4369de7a95SPavel Labath 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process 4469de7a95SPavel Labath 4569de7a95SPavel Labath - Type: LinuxAuxv 4669de7a95SPavel Labath Content: DEADBEEFBAADF00D)"); 4769de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 4869de7a95SPavel Labath object::MinidumpFile &File = **ExpectedFile; 4969de7a95SPavel Labath 5069de7a95SPavel Labath ASSERT_EQ(3u, File.streams().size()); 5169de7a95SPavel Labath 5269de7a95SPavel Labath EXPECT_EQ(StreamType::SystemInfo, File.streams()[0].Type); 5369de7a95SPavel Labath auto ExpectedSysInfo = File.getSystemInfo(); 5469de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded()); 5569de7a95SPavel Labath const SystemInfo &SysInfo = *ExpectedSysInfo; 56e9430231SPavel Labath EXPECT_EQ(ProcessorArchitecture::ARM64, SysInfo.ProcessorArch); 5769de7a95SPavel Labath EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId); 5869de7a95SPavel Labath EXPECT_EQ(0x05060708u, SysInfo.CPU.Arm.CPUID); 5969de7a95SPavel Labath 6069de7a95SPavel Labath EXPECT_EQ(StreamType::LinuxMaps, File.streams()[1].Type); 6169de7a95SPavel Labath EXPECT_EQ("400d9000-400db000 r-xp 00000000 b3:04 227 " 6269de7a95SPavel Labath "/system/bin/app_process\n" 6369de7a95SPavel Labath "400db000-400dc000 r--p 00001000 b3:04 227 " 6469de7a95SPavel Labath "/system/bin/app_process\n", 6569de7a95SPavel Labath toStringRef(*File.getRawStream(StreamType::LinuxMaps))); 6669de7a95SPavel Labath 6769de7a95SPavel Labath EXPECT_EQ(StreamType::LinuxAuxv, File.streams()[2].Type); 6869de7a95SPavel Labath EXPECT_EQ((ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D}), 6969de7a95SPavel Labath File.getRawStream(StreamType::LinuxAuxv)); 7069de7a95SPavel Labath } 7169de7a95SPavel Labath 7269de7a95SPavel Labath TEST(MinidumpYAML, RawContent) { 7369de7a95SPavel Labath SmallString<0> Storage; 7469de7a95SPavel Labath auto ExpectedFile = toBinary(Storage, R"( 7569de7a95SPavel Labath --- !minidump 7669de7a95SPavel Labath Streams: 7769de7a95SPavel Labath - Type: LinuxAuxv 7869de7a95SPavel Labath Size: 9 7969de7a95SPavel Labath Content: DEADBEEFBAADF00D)"); 8069de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 8169de7a95SPavel Labath object::MinidumpFile &File = **ExpectedFile; 8269de7a95SPavel Labath 8369de7a95SPavel Labath EXPECT_EQ( 8469de7a95SPavel Labath (ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, 0x00}), 8569de7a95SPavel Labath File.getRawStream(StreamType::LinuxAuxv)); 8669de7a95SPavel Labath } 8769de7a95SPavel Labath 8869de7a95SPavel Labath TEST(MinidumpYAML, X86SystemInfo) { 8969de7a95SPavel Labath SmallString<0> Storage; 9069de7a95SPavel Labath auto ExpectedFile = toBinary(Storage, R"( 9169de7a95SPavel Labath --- !minidump 9269de7a95SPavel Labath Streams: 9369de7a95SPavel Labath - Type: SystemInfo 9469de7a95SPavel Labath Processor Arch: X86 9569de7a95SPavel Labath Platform ID: Linux 9669de7a95SPavel Labath CPU: 9769de7a95SPavel Labath Vendor ID: LLVMLLVMLLVM 9869de7a95SPavel Labath Version Info: 0x01020304 9969de7a95SPavel Labath Feature Info: 0x05060708 10069de7a95SPavel Labath AMD Extended Features: 0x09000102)"); 10169de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 10269de7a95SPavel Labath object::MinidumpFile &File = **ExpectedFile; 10369de7a95SPavel Labath 10469de7a95SPavel Labath ASSERT_EQ(1u, File.streams().size()); 10569de7a95SPavel Labath 10669de7a95SPavel Labath auto ExpectedSysInfo = File.getSystemInfo(); 10769de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded()); 10869de7a95SPavel Labath const SystemInfo &SysInfo = *ExpectedSysInfo; 10969de7a95SPavel Labath EXPECT_EQ(ProcessorArchitecture::X86, SysInfo.ProcessorArch); 11069de7a95SPavel Labath EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId); 11169de7a95SPavel Labath EXPECT_EQ("LLVMLLVMLLVM", StringRef(SysInfo.CPU.X86.VendorID, 11269de7a95SPavel Labath sizeof(SysInfo.CPU.X86.VendorID))); 11369de7a95SPavel Labath EXPECT_EQ(0x01020304u, SysInfo.CPU.X86.VersionInfo); 11469de7a95SPavel Labath EXPECT_EQ(0x05060708u, SysInfo.CPU.X86.FeatureInfo); 11569de7a95SPavel Labath EXPECT_EQ(0x09000102u, SysInfo.CPU.X86.AMDExtendedFeatures); 11669de7a95SPavel Labath } 11769de7a95SPavel Labath 11869de7a95SPavel Labath TEST(MinidumpYAML, OtherSystemInfo) { 11969de7a95SPavel Labath SmallString<0> Storage; 12069de7a95SPavel Labath auto ExpectedFile = toBinary(Storage, R"( 12169de7a95SPavel Labath --- !minidump 12269de7a95SPavel Labath Streams: 12369de7a95SPavel Labath - Type: SystemInfo 12469de7a95SPavel Labath Processor Arch: PPC 12569de7a95SPavel Labath Platform ID: Linux 12669de7a95SPavel Labath CPU: 12769de7a95SPavel Labath Features: 000102030405060708090a0b0c0d0e0f)"); 12869de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 12969de7a95SPavel Labath object::MinidumpFile &File = **ExpectedFile; 13069de7a95SPavel Labath 13169de7a95SPavel Labath ASSERT_EQ(1u, File.streams().size()); 13269de7a95SPavel Labath 13369de7a95SPavel Labath auto ExpectedSysInfo = File.getSystemInfo(); 13469de7a95SPavel Labath ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded()); 13569de7a95SPavel Labath const SystemInfo &SysInfo = *ExpectedSysInfo; 13669de7a95SPavel Labath EXPECT_EQ(ProcessorArchitecture::PPC, SysInfo.ProcessorArch); 13769de7a95SPavel Labath EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId); 13869de7a95SPavel Labath EXPECT_EQ( 13969de7a95SPavel Labath (ArrayRef<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}), 14038818b60Sserge-sans-paille ArrayRef(SysInfo.CPU.Other.ProcessorFeatures)); 14169de7a95SPavel Labath } 142a50272f8SJoseph Tremoulet 143a50272f8SJoseph Tremoulet // Test that we can parse a normal-looking ExceptionStream. 144a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream) { 145a50272f8SJoseph Tremoulet SmallString<0> Storage; 146a50272f8SJoseph Tremoulet auto ExpectedFile = toBinary(Storage, R"( 147a50272f8SJoseph Tremoulet --- !minidump 148a50272f8SJoseph Tremoulet Streams: 149a50272f8SJoseph Tremoulet - Type: Exception 150a50272f8SJoseph Tremoulet Thread ID: 0x7 151a50272f8SJoseph Tremoulet Exception Record: 152a50272f8SJoseph Tremoulet Exception Code: 0x23 153a50272f8SJoseph Tremoulet Exception Flags: 0x5 154a50272f8SJoseph Tremoulet Exception Record: 0x0102030405060708 155a50272f8SJoseph Tremoulet Exception Address: 0x0a0b0c0d0e0f1011 156a50272f8SJoseph Tremoulet Number of Parameters: 2 157a50272f8SJoseph Tremoulet Parameter 0: 0x22 158a50272f8SJoseph Tremoulet Parameter 1: 0x24 159a50272f8SJoseph Tremoulet Thread Context: 3DeadBeefDefacedABadCafe)"); 160a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 161a50272f8SJoseph Tremoulet object::MinidumpFile &File = **ExpectedFile; 162a50272f8SJoseph Tremoulet 163a50272f8SJoseph Tremoulet ASSERT_EQ(1u, File.streams().size()); 164a50272f8SJoseph Tremoulet 165*deba1340SJacob Lalonde auto ExceptionIterator = File.getExceptionStreams().begin(); 166*deba1340SJacob Lalonde 167*deba1340SJacob Lalonde Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator; 168a50272f8SJoseph Tremoulet 169a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded()); 170a50272f8SJoseph Tremoulet 171a50272f8SJoseph Tremoulet const minidump::ExceptionStream &Stream = *ExpectedStream; 172a50272f8SJoseph Tremoulet EXPECT_EQ(0x7u, Stream.ThreadId); 173a50272f8SJoseph Tremoulet const minidump::Exception &Exception = Stream.ExceptionRecord; 174a50272f8SJoseph Tremoulet EXPECT_EQ(0x23u, Exception.ExceptionCode); 175a50272f8SJoseph Tremoulet EXPECT_EQ(0x5u, Exception.ExceptionFlags); 176a50272f8SJoseph Tremoulet EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord); 177a50272f8SJoseph Tremoulet EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress); 178a50272f8SJoseph Tremoulet EXPECT_EQ(2u, Exception.NumberParameters); 179a50272f8SJoseph Tremoulet EXPECT_EQ(0x22u, Exception.ExceptionInformation[0]); 180a50272f8SJoseph Tremoulet EXPECT_EQ(0x24u, Exception.ExceptionInformation[1]); 181a50272f8SJoseph Tremoulet 182a50272f8SJoseph Tremoulet Expected<ArrayRef<uint8_t>> ExpectedContext = 183a50272f8SJoseph Tremoulet File.getRawData(Stream.ThreadContext); 184a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded()); 185a50272f8SJoseph Tremoulet EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed, 186a50272f8SJoseph Tremoulet 0xab, 0xad, 0xca, 0xfe}), 187a50272f8SJoseph Tremoulet *ExpectedContext); 188a50272f8SJoseph Tremoulet } 189a50272f8SJoseph Tremoulet 190a50272f8SJoseph Tremoulet // Test that we can parse an exception stream with no ExceptionInformation. 191a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_NoParameters) { 192a50272f8SJoseph Tremoulet SmallString<0> Storage; 193a50272f8SJoseph Tremoulet auto ExpectedFile = toBinary(Storage, R"( 194a50272f8SJoseph Tremoulet --- !minidump 195a50272f8SJoseph Tremoulet Streams: 196a50272f8SJoseph Tremoulet - Type: Exception 197a50272f8SJoseph Tremoulet Thread ID: 0x7 198a50272f8SJoseph Tremoulet Exception Record: 199a50272f8SJoseph Tremoulet Exception Code: 0x23 200a50272f8SJoseph Tremoulet Exception Flags: 0x5 201a50272f8SJoseph Tremoulet Exception Record: 0x0102030405060708 202a50272f8SJoseph Tremoulet Exception Address: 0x0a0b0c0d0e0f1011 203a50272f8SJoseph Tremoulet Thread Context: 3DeadBeefDefacedABadCafe)"); 204a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 205a50272f8SJoseph Tremoulet object::MinidumpFile &File = **ExpectedFile; 206a50272f8SJoseph Tremoulet 207a50272f8SJoseph Tremoulet ASSERT_EQ(1u, File.streams().size()); 208a50272f8SJoseph Tremoulet 209*deba1340SJacob Lalonde auto ExceptionIterator = File.getExceptionStreams().begin(); 210a50272f8SJoseph Tremoulet 211*deba1340SJacob Lalonde Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator; 212a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded()); 213a50272f8SJoseph Tremoulet 214a50272f8SJoseph Tremoulet const minidump::ExceptionStream &Stream = *ExpectedStream; 215a50272f8SJoseph Tremoulet EXPECT_EQ(0x7u, Stream.ThreadId); 216a50272f8SJoseph Tremoulet const minidump::Exception &Exception = Stream.ExceptionRecord; 217a50272f8SJoseph Tremoulet EXPECT_EQ(0x23u, Exception.ExceptionCode); 218a50272f8SJoseph Tremoulet EXPECT_EQ(0x5u, Exception.ExceptionFlags); 219a50272f8SJoseph Tremoulet EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord); 220a50272f8SJoseph Tremoulet EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress); 221a50272f8SJoseph Tremoulet EXPECT_EQ(0u, Exception.NumberParameters); 222a50272f8SJoseph Tremoulet 223a50272f8SJoseph Tremoulet Expected<ArrayRef<uint8_t>> ExpectedContext = 224a50272f8SJoseph Tremoulet File.getRawData(Stream.ThreadContext); 225a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded()); 226a50272f8SJoseph Tremoulet EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed, 227a50272f8SJoseph Tremoulet 0xab, 0xad, 0xca, 0xfe}), 228a50272f8SJoseph Tremoulet *ExpectedContext); 229a50272f8SJoseph Tremoulet } 230a50272f8SJoseph Tremoulet 231a50272f8SJoseph Tremoulet // Test that we can parse an ExceptionStream where the stated number of 232a50272f8SJoseph Tremoulet // parameters is greater than the actual size of the ExceptionInformation 233a50272f8SJoseph Tremoulet // array. 234a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_TooManyParameters) { 235a50272f8SJoseph Tremoulet SmallString<0> Storage; 236a50272f8SJoseph Tremoulet auto ExpectedFile = toBinary(Storage, R"( 237a50272f8SJoseph Tremoulet --- !minidump 238a50272f8SJoseph Tremoulet Streams: 239a50272f8SJoseph Tremoulet - Type: Exception 240a50272f8SJoseph Tremoulet Thread ID: 0x8 241a50272f8SJoseph Tremoulet Exception Record: 242a50272f8SJoseph Tremoulet Exception Code: 0 243a50272f8SJoseph Tremoulet Number of Parameters: 16 244a50272f8SJoseph Tremoulet Parameter 0: 0x0 245a50272f8SJoseph Tremoulet Parameter 1: 0xff 246a50272f8SJoseph Tremoulet Parameter 2: 0xee 247a50272f8SJoseph Tremoulet Parameter 3: 0xdd 248a50272f8SJoseph Tremoulet Parameter 4: 0xcc 249a50272f8SJoseph Tremoulet Parameter 5: 0xbb 250a50272f8SJoseph Tremoulet Parameter 6: 0xaa 251a50272f8SJoseph Tremoulet Parameter 7: 0x99 252a50272f8SJoseph Tremoulet Parameter 8: 0x88 253a50272f8SJoseph Tremoulet Parameter 9: 0x77 254a50272f8SJoseph Tremoulet Parameter 10: 0x66 255a50272f8SJoseph Tremoulet Parameter 11: 0x55 256a50272f8SJoseph Tremoulet Parameter 12: 0x44 257a50272f8SJoseph Tremoulet Parameter 13: 0x33 258a50272f8SJoseph Tremoulet Parameter 14: 0x22 259a50272f8SJoseph Tremoulet Thread Context: 3DeadBeefDefacedABadCafe)"); 260a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 261a50272f8SJoseph Tremoulet object::MinidumpFile &File = **ExpectedFile; 262a50272f8SJoseph Tremoulet 263a50272f8SJoseph Tremoulet ASSERT_EQ(1u, File.streams().size()); 264a50272f8SJoseph Tremoulet 265*deba1340SJacob Lalonde auto ExceptionIterator = File.getExceptionStreams().begin(); 266*deba1340SJacob Lalonde 267*deba1340SJacob Lalonde Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator; 268a50272f8SJoseph Tremoulet 269a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded()); 270a50272f8SJoseph Tremoulet 271a50272f8SJoseph Tremoulet const minidump::ExceptionStream &Stream = *ExpectedStream; 272a50272f8SJoseph Tremoulet EXPECT_EQ(0x8u, Stream.ThreadId); 273a50272f8SJoseph Tremoulet const minidump::Exception &Exception = Stream.ExceptionRecord; 274a50272f8SJoseph Tremoulet EXPECT_EQ(0x0u, Exception.ExceptionCode); 275a50272f8SJoseph Tremoulet EXPECT_EQ(0x0u, Exception.ExceptionFlags); 276a50272f8SJoseph Tremoulet EXPECT_EQ(0x00u, Exception.ExceptionRecord); 277a50272f8SJoseph Tremoulet EXPECT_EQ(0x0u, Exception.ExceptionAddress); 278a50272f8SJoseph Tremoulet EXPECT_EQ(16u, Exception.NumberParameters); 279a50272f8SJoseph Tremoulet EXPECT_EQ(0x0u, Exception.ExceptionInformation[0]); 280a50272f8SJoseph Tremoulet for (int Index = 1; Index < 15; ++Index) { 281a50272f8SJoseph Tremoulet EXPECT_EQ(0x110u - Index * 0x11, Exception.ExceptionInformation[Index]); 282a50272f8SJoseph Tremoulet } 283a50272f8SJoseph Tremoulet 284a50272f8SJoseph Tremoulet Expected<ArrayRef<uint8_t>> ExpectedContext = 285a50272f8SJoseph Tremoulet File.getRawData(Stream.ThreadContext); 286a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded()); 287a50272f8SJoseph Tremoulet EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed, 288a50272f8SJoseph Tremoulet 0xab, 0xad, 0xca, 0xfe}), 289a50272f8SJoseph Tremoulet *ExpectedContext); 290a50272f8SJoseph Tremoulet } 291a50272f8SJoseph Tremoulet 292a50272f8SJoseph Tremoulet // Test that we can parse an ExceptionStream where the number of 293a50272f8SJoseph Tremoulet // ExceptionInformation parameters provided is greater than the 294a50272f8SJoseph Tremoulet // specified Number of Parameters. 295a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_ExtraParameter) { 296a50272f8SJoseph Tremoulet SmallString<0> Storage; 297a50272f8SJoseph Tremoulet auto ExpectedFile = toBinary(Storage, R"( 298a50272f8SJoseph Tremoulet --- !minidump 299a50272f8SJoseph Tremoulet Streams: 300a50272f8SJoseph Tremoulet - Type: Exception 301a50272f8SJoseph Tremoulet Thread ID: 0x7 302a50272f8SJoseph Tremoulet Exception Record: 303a50272f8SJoseph Tremoulet Exception Code: 0x23 304a50272f8SJoseph Tremoulet Exception Flags: 0x5 305a50272f8SJoseph Tremoulet Exception Record: 0x0102030405060708 306a50272f8SJoseph Tremoulet Exception Address: 0x0a0b0c0d0e0f1011 307a50272f8SJoseph Tremoulet Number of Parameters: 2 308a50272f8SJoseph Tremoulet Parameter 0: 0x99 309a50272f8SJoseph Tremoulet Parameter 1: 0x23 310a50272f8SJoseph Tremoulet Parameter 2: 0x42 311a50272f8SJoseph Tremoulet Thread Context: 3DeadBeefDefacedABadCafe)"); 312a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 313a50272f8SJoseph Tremoulet object::MinidumpFile &File = **ExpectedFile; 314a50272f8SJoseph Tremoulet 315a50272f8SJoseph Tremoulet ASSERT_EQ(1u, File.streams().size()); 316a50272f8SJoseph Tremoulet 317*deba1340SJacob Lalonde auto ExceptionIterator = File.getExceptionStreams().begin(); 318*deba1340SJacob Lalonde 319*deba1340SJacob Lalonde Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator; 320a50272f8SJoseph Tremoulet 321a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded()); 322a50272f8SJoseph Tremoulet 323a50272f8SJoseph Tremoulet const minidump::ExceptionStream &Stream = *ExpectedStream; 324a50272f8SJoseph Tremoulet EXPECT_EQ(0x7u, Stream.ThreadId); 325a50272f8SJoseph Tremoulet const minidump::Exception &Exception = Stream.ExceptionRecord; 326a50272f8SJoseph Tremoulet EXPECT_EQ(0x23u, Exception.ExceptionCode); 327a50272f8SJoseph Tremoulet EXPECT_EQ(0x5u, Exception.ExceptionFlags); 328a50272f8SJoseph Tremoulet EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord); 329a50272f8SJoseph Tremoulet EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress); 330a50272f8SJoseph Tremoulet EXPECT_EQ(2u, Exception.NumberParameters); 331a50272f8SJoseph Tremoulet EXPECT_EQ(0x99u, Exception.ExceptionInformation[0]); 332a50272f8SJoseph Tremoulet EXPECT_EQ(0x23u, Exception.ExceptionInformation[1]); 333a50272f8SJoseph Tremoulet EXPECT_EQ(0x42u, Exception.ExceptionInformation[2]); 334a50272f8SJoseph Tremoulet 335a50272f8SJoseph Tremoulet Expected<ArrayRef<uint8_t>> ExpectedContext = 336a50272f8SJoseph Tremoulet File.getRawData(Stream.ThreadContext); 337a50272f8SJoseph Tremoulet ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded()); 338a50272f8SJoseph Tremoulet EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed, 339a50272f8SJoseph Tremoulet 0xab, 0xad, 0xca, 0xfe}), 340a50272f8SJoseph Tremoulet *ExpectedContext); 341a50272f8SJoseph Tremoulet } 342b1edac04SJacob Lalonde 343b1edac04SJacob Lalonde TEST(MinidumpYAML, MemoryRegion_64bit) { 344b1edac04SJacob Lalonde SmallString<0> Storage; 345b1edac04SJacob Lalonde auto ExpectedFile = toBinary(Storage, R"( 346b1edac04SJacob Lalonde --- !minidump 347b1edac04SJacob Lalonde Streams: 348b1edac04SJacob Lalonde - Type: Memory64List 349b1edac04SJacob Lalonde Memory Ranges: 350b1edac04SJacob Lalonde - Start of Memory Range: 0x7FFFFFCF0818283 351b1edac04SJacob Lalonde Content: '68656c6c6f' 352b1edac04SJacob Lalonde - Start of Memory Range: 0x7FFFFFFF0818283 353b1edac04SJacob Lalonde Content: '776f726c64' 354b1edac04SJacob Lalonde )"); 355b1edac04SJacob Lalonde 356b1edac04SJacob Lalonde ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 357b1edac04SJacob Lalonde object::MinidumpFile &File = **ExpectedFile; 358b1edac04SJacob Lalonde 359b1edac04SJacob Lalonde ASSERT_THAT(File.streams().size(), 1u); 360b1edac04SJacob Lalonde 361b1edac04SJacob Lalonde Error Err = Error::success(); 362b1edac04SJacob Lalonde iterator_range<object::MinidumpFile::FallibleMemory64Iterator> MemoryList = 363b1edac04SJacob Lalonde File.getMemory64List(Err); 364b1edac04SJacob Lalonde 365b1edac04SJacob Lalonde ASSERT_THAT_ERROR(std::move(Err), Succeeded()); 366b1edac04SJacob Lalonde auto Iterator = MemoryList.begin(); 367b1edac04SJacob Lalonde 368b1edac04SJacob Lalonde auto DescOnePair = *Iterator; 369b1edac04SJacob Lalonde const minidump::MemoryDescriptor_64 &DescOne = DescOnePair.first; 370b1edac04SJacob Lalonde ASSERT_THAT(DescOne.StartOfMemoryRange, 0x7FFFFFCF0818283u); 371b1edac04SJacob Lalonde ASSERT_THAT(DescOne.DataSize, 5u); 372b1edac04SJacob Lalonde ++Iterator; 373b1edac04SJacob Lalonde ASSERT_THAT_ERROR(std::move(Err), Succeeded()); 374b1edac04SJacob Lalonde 375b1edac04SJacob Lalonde auto DescTwoPair = *Iterator; 376b1edac04SJacob Lalonde const minidump::MemoryDescriptor_64 &DescTwo = DescTwoPair.first; 377b1edac04SJacob Lalonde ASSERT_THAT(DescTwo.StartOfMemoryRange, 0x7FFFFFFF0818283u); 378b1edac04SJacob Lalonde ASSERT_THAT(DescTwo.DataSize, 5u); 379b1edac04SJacob Lalonde ++Iterator; 380b1edac04SJacob Lalonde ASSERT_THAT_ERROR(std::move(Err), Succeeded()); 381b1edac04SJacob Lalonde 382b1edac04SJacob Lalonde const std::optional<ArrayRef<uint8_t>> ExpectedContent = 383b1edac04SJacob Lalonde File.getRawStream(StreamType::Memory64List); 384b1edac04SJacob Lalonde ASSERT_TRUE(ExpectedContent); 385b1edac04SJacob Lalonde const size_t ExpectedStreamSize = 386b1edac04SJacob Lalonde sizeof(Memory64ListHeader) + (sizeof(MemoryDescriptor_64) * 2); 387b1edac04SJacob Lalonde ASSERT_THAT(ExpectedContent->size(), ExpectedStreamSize); 388b1edac04SJacob Lalonde 389b1edac04SJacob Lalonde Expected<minidump::Memory64ListHeader> ExpectedHeader = 390b1edac04SJacob Lalonde File.getMemoryList64Header(); 391b1edac04SJacob Lalonde ASSERT_THAT_EXPECTED(ExpectedHeader, Succeeded()); 392b1edac04SJacob Lalonde ASSERT_THAT(ExpectedHeader->BaseRVA, 92u); 393b1edac04SJacob Lalonde 394b1edac04SJacob Lalonde Expected<ArrayRef<uint8_t>> DescOneExpectedContentSlice = DescOnePair.second; 395b1edac04SJacob Lalonde ASSERT_THAT_EXPECTED(DescOneExpectedContentSlice, Succeeded()); 396b1edac04SJacob Lalonde ASSERT_THAT(DescOneExpectedContentSlice->size(), 5u); 397b1edac04SJacob Lalonde ASSERT_THAT(*DescOneExpectedContentSlice, arrayRefFromStringRef("hello")); 398b1edac04SJacob Lalonde 399b1edac04SJacob Lalonde Expected<ArrayRef<uint8_t>> DescTwoExpectedContentSlice = DescTwoPair.second; 400b1edac04SJacob Lalonde ASSERT_THAT_EXPECTED(DescTwoExpectedContentSlice, Succeeded()); 401b1edac04SJacob Lalonde ASSERT_THAT(*DescTwoExpectedContentSlice, arrayRefFromStringRef("world")); 402b1edac04SJacob Lalonde 403b1edac04SJacob Lalonde ASSERT_EQ(Iterator, MemoryList.end()); 404b1edac04SJacob Lalonde } 405*deba1340SJacob Lalonde 406*deba1340SJacob Lalonde // Test that we can parse multiple exception streams. 407*deba1340SJacob Lalonde TEST(MinidumpYAML, ExceptionStream_MultipleExceptions) { 408*deba1340SJacob Lalonde SmallString<0> Storage; 409*deba1340SJacob Lalonde auto ExpectedFile = toBinary(Storage, R"( 410*deba1340SJacob Lalonde --- !minidump 411*deba1340SJacob Lalonde Streams: 412*deba1340SJacob Lalonde - Type: Exception 413*deba1340SJacob Lalonde Thread ID: 0x7 414*deba1340SJacob Lalonde Exception Record: 415*deba1340SJacob Lalonde Exception Code: 0x23 416*deba1340SJacob Lalonde Exception Flags: 0x5 417*deba1340SJacob Lalonde Exception Record: 0x0102030405060708 418*deba1340SJacob Lalonde Exception Address: 0x0a0b0c0d0e0f1011 419*deba1340SJacob Lalonde Number of Parameters: 2 420*deba1340SJacob Lalonde Parameter 0: 0x99 421*deba1340SJacob Lalonde Parameter 1: 0x23 422*deba1340SJacob Lalonde Parameter 2: 0x42 423*deba1340SJacob Lalonde Thread Context: 3DeadBeefDefacedABadCafe 424*deba1340SJacob Lalonde - Type: Exception 425*deba1340SJacob Lalonde Thread ID: 0x5 426*deba1340SJacob Lalonde Exception Record: 427*deba1340SJacob Lalonde Exception Code: 0x23 428*deba1340SJacob Lalonde Exception Flags: 0x5 429*deba1340SJacob Lalonde Exception Record: 0x0102030405060708 430*deba1340SJacob Lalonde Exception Address: 0x0a0b0c0d0e0f1011 431*deba1340SJacob Lalonde Thread Context: 3DeadBeefDefacedABadCafe)"); 432*deba1340SJacob Lalonde 433*deba1340SJacob Lalonde ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 434*deba1340SJacob Lalonde object::MinidumpFile &File = **ExpectedFile; 435*deba1340SJacob Lalonde 436*deba1340SJacob Lalonde ASSERT_EQ(2u, File.streams().size()); 437*deba1340SJacob Lalonde 438*deba1340SJacob Lalonde size_t count = 0; 439*deba1340SJacob Lalonde for (auto exception_stream : File.getExceptionStreams()) { 440*deba1340SJacob Lalonde count++; 441*deba1340SJacob Lalonde ASSERT_THAT_EXPECTED(exception_stream, Succeeded()); 442*deba1340SJacob Lalonde ASSERT_THAT(0x23u, exception_stream->ExceptionRecord.ExceptionCode); 443*deba1340SJacob Lalonde } 444*deba1340SJacob Lalonde 445*deba1340SJacob Lalonde ASSERT_THAT(2u, count); 446*deba1340SJacob Lalonde } 447