609 lines · cpp
1//===- MinidumpYAML.cpp - Minidump YAMLIO implementation ------------------===//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 "llvm/ObjectYAML/MinidumpYAML.h"10 11using namespace llvm;12using namespace llvm::MinidumpYAML;13using namespace llvm::minidump;14 15/// Perform an optional yaml-mapping of an endian-aware type EndianType. The16/// only purpose of this function is to avoid casting the Default value to the17/// endian type;18template <typename EndianType>19static inline void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val,20 typename EndianType::value_type Default) {21 IO.mapOptional(Key, Val, EndianType(Default));22}23 24/// Yaml-map an endian-aware type EndianType as some other type MapType.25template <typename MapType, typename EndianType>26static inline void mapRequiredAs(yaml::IO &IO, const char *Key,27 EndianType &Val) {28 MapType Mapped = static_cast<typename EndianType::value_type>(Val);29 IO.mapRequired(Key, Mapped);30 Val = static_cast<typename EndianType::value_type>(Mapped);31}32 33/// Perform an optional yaml-mapping of an endian-aware type EndianType as some34/// other type MapType.35template <typename MapType, typename EndianType>36static inline void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val,37 MapType Default) {38 MapType Mapped = static_cast<typename EndianType::value_type>(Val);39 IO.mapOptional(Key, Mapped, Default);40 Val = static_cast<typename EndianType::value_type>(Mapped);41}42 43namespace {44/// Return the appropriate yaml Hex type for a given endian-aware type.45template <typename EndianType> struct HexType;46template <> struct HexType<support::ulittle16_t> { using type = yaml::Hex16; };47template <> struct HexType<support::ulittle32_t> { using type = yaml::Hex32; };48template <> struct HexType<support::ulittle64_t> { using type = yaml::Hex64; };49} // namespace50 51/// Yaml-map an endian-aware type as an appropriately-sized hex value.52template <typename EndianType>53static inline void mapRequiredHex(yaml::IO &IO, const char *Key,54 EndianType &Val) {55 mapRequiredAs<typename HexType<EndianType>::type>(IO, Key, Val);56}57 58/// Perform an optional yaml-mapping of an endian-aware type as an59/// appropriately-sized hex value.60template <typename EndianType>61static inline void mapOptionalHex(yaml::IO &IO, const char *Key,62 EndianType &Val,63 typename EndianType::value_type Default) {64 mapOptionalAs<typename HexType<EndianType>::type>(IO, Key, Val, Default);65}66 67Stream::~Stream() = default;68 69Stream::StreamKind Stream::getKind(StreamType Type) {70 switch (Type) {71 case StreamType::Exception:72 return StreamKind::Exception;73 case StreamType::MemoryInfoList:74 return StreamKind::MemoryInfoList;75 case StreamType::MemoryList:76 return StreamKind::MemoryList;77 case StreamType::Memory64List:78 return StreamKind::Memory64List;79 case StreamType::ModuleList:80 return StreamKind::ModuleList;81 case StreamType::SystemInfo:82 return StreamKind::SystemInfo;83 case StreamType::LinuxCPUInfo:84 case StreamType::LinuxProcStatus:85 case StreamType::LinuxLSBRelease:86 case StreamType::LinuxCMDLine:87 case StreamType::LinuxMaps:88 case StreamType::LinuxProcStat:89 case StreamType::LinuxProcUptime:90 return StreamKind::TextContent;91 case StreamType::ThreadList:92 return StreamKind::ThreadList;93 default:94 return StreamKind::RawContent;95 }96}97 98std::unique_ptr<Stream> Stream::create(StreamType Type) {99 StreamKind Kind = getKind(Type);100 switch (Kind) {101 case StreamKind::Exception:102 return std::make_unique<ExceptionStream>();103 case StreamKind::MemoryInfoList:104 return std::make_unique<MemoryInfoListStream>();105 case StreamKind::MemoryList:106 return std::make_unique<MemoryListStream>();107 case StreamKind::Memory64List:108 return std::make_unique<Memory64ListStream>();109 case StreamKind::ModuleList:110 return std::make_unique<ModuleListStream>();111 case StreamKind::RawContent:112 return std::make_unique<RawContentStream>(Type);113 case StreamKind::SystemInfo:114 return std::make_unique<SystemInfoStream>();115 case StreamKind::TextContent:116 return std::make_unique<TextContentStream>(Type);117 case StreamKind::ThreadList:118 return std::make_unique<ThreadListStream>();119 }120 llvm_unreachable("Unhandled stream kind!");121}122 123void yaml::ScalarBitSetTraits<MemoryProtection>::bitset(124 IO &IO, MemoryProtection &Protect) {125#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) \126 IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);127#include "llvm/BinaryFormat/MinidumpConstants.def"128}129 130void yaml::ScalarBitSetTraits<MemoryState>::bitset(IO &IO, MemoryState &State) {131#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) \132 IO.bitSetCase(State, #NATIVENAME, MemoryState::NAME);133#include "llvm/BinaryFormat/MinidumpConstants.def"134}135 136void yaml::ScalarBitSetTraits<MemoryType>::bitset(IO &IO, MemoryType &Type) {137#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) \138 IO.bitSetCase(Type, #NATIVENAME, MemoryType::NAME);139#include "llvm/BinaryFormat/MinidumpConstants.def"140}141 142void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(143 IO &IO, ProcessorArchitecture &Arch) {144#define HANDLE_MDMP_ARCH(CODE, NAME) \145 IO.enumCase(Arch, #NAME, ProcessorArchitecture::NAME);146#include "llvm/BinaryFormat/MinidumpConstants.def"147 IO.enumFallback<Hex16>(Arch);148}149 150void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO,151 OSPlatform &Plat) {152#define HANDLE_MDMP_PLATFORM(CODE, NAME) \153 IO.enumCase(Plat, #NAME, OSPlatform::NAME);154#include "llvm/BinaryFormat/MinidumpConstants.def"155 IO.enumFallback<Hex32>(Plat);156}157 158void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO,159 StreamType &Type) {160#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) \161 IO.enumCase(Type, #NAME, StreamType::NAME);162#include "llvm/BinaryFormat/MinidumpConstants.def"163 IO.enumFallback<Hex32>(Type);164}165 166void yaml::MappingTraits<CPUInfo::ArmInfo>::mapping(IO &IO,167 CPUInfo::ArmInfo &Info) {168 mapRequiredHex(IO, "CPUID", Info.CPUID);169 mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0);170}171 172namespace {173template <std::size_t N> struct FixedSizeHex {174 FixedSizeHex(uint8_t (&Storage)[N]) : Storage(Storage) {}175 176 uint8_t (&Storage)[N];177};178} // namespace179 180namespace llvm {181namespace yaml {182template <std::size_t N> struct ScalarTraits<FixedSizeHex<N>> {183 static void output(const FixedSizeHex<N> &Fixed, void *, raw_ostream &OS) {184 OS << toHex(ArrayRef(Fixed.Storage));185 }186 187 static StringRef input(StringRef Scalar, void *, FixedSizeHex<N> &Fixed) {188 if (!all_of(Scalar, isHexDigit))189 return "Invalid hex digit in input";190 if (Scalar.size() < 2 * N)191 return "String too short";192 if (Scalar.size() > 2 * N)193 return "String too long";194 copy(fromHex(Scalar), Fixed.Storage);195 return "";196 }197 198 static QuotingType mustQuote(StringRef S) { return QuotingType::None; }199};200} // namespace yaml201} // namespace llvm202void yaml::MappingTraits<CPUInfo::OtherInfo>::mapping(203 IO &IO, CPUInfo::OtherInfo &Info) {204 FixedSizeHex<sizeof(Info.ProcessorFeatures)> Features(Info.ProcessorFeatures);205 IO.mapRequired("Features", Features);206}207 208namespace {209/// A type which only accepts strings of a fixed size for yaml conversion.210template <std::size_t N> struct FixedSizeString {211 FixedSizeString(char (&Storage)[N]) : Storage(Storage) {}212 213 char (&Storage)[N];214};215} // namespace216 217namespace llvm {218namespace yaml {219template <std::size_t N> struct ScalarTraits<FixedSizeString<N>> {220 static void output(const FixedSizeString<N> &Fixed, void *, raw_ostream &OS) {221 OS << StringRef(Fixed.Storage, N);222 }223 224 static StringRef input(StringRef Scalar, void *, FixedSizeString<N> &Fixed) {225 if (Scalar.size() < N)226 return "String too short";227 if (Scalar.size() > N)228 return "String too long";229 copy(Scalar, Fixed.Storage);230 return "";231 }232 233 static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }234};235} // namespace yaml236} // namespace llvm237 238void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO,239 CPUInfo::X86Info &Info) {240 FixedSizeString<sizeof(Info.VendorID)> VendorID(Info.VendorID);241 IO.mapRequired("Vendor ID", VendorID);242 243 mapRequiredHex(IO, "Version Info", Info.VersionInfo);244 mapRequiredHex(IO, "Feature Info", Info.FeatureInfo);245 mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);246}247 248void yaml::MappingTraits<MemoryInfo>::mapping(IO &IO, MemoryInfo &Info) {249 mapRequiredHex(IO, "Base Address", Info.BaseAddress);250 mapOptionalHex(IO, "Allocation Base", Info.AllocationBase, Info.BaseAddress);251 mapRequiredAs<MemoryProtection>(IO, "Allocation Protect",252 Info.AllocationProtect);253 mapOptionalHex(IO, "Reserved0", Info.Reserved0, 0);254 mapRequiredHex(IO, "Region Size", Info.RegionSize);255 mapRequiredAs<MemoryState>(IO, "State", Info.State);256 mapOptionalAs<MemoryProtection>(IO, "Protect", Info.Protect,257 Info.AllocationProtect);258 mapRequiredAs<MemoryType>(IO, "Type", Info.Type);259 mapOptionalHex(IO, "Reserved1", Info.Reserved1, 0);260}261 262void yaml::MappingTraits<Memory64ListStream::entry_type>::mapping(263 IO &IO, Memory64ListStream::entry_type &Mem) {264 MappingContextTraits<MemoryDescriptor_64, yaml::BinaryRef>::mapping(265 IO, Mem.Entry, Mem.Content);266}267 268void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO,269 VSFixedFileInfo &Info) {270 mapOptionalHex(IO, "Signature", Info.Signature, 0);271 mapOptionalHex(IO, "Struct Version", Info.StructVersion, 0);272 mapOptionalHex(IO, "File Version High", Info.FileVersionHigh, 0);273 mapOptionalHex(IO, "File Version Low", Info.FileVersionLow, 0);274 mapOptionalHex(IO, "Product Version High", Info.ProductVersionHigh, 0);275 mapOptionalHex(IO, "Product Version Low", Info.ProductVersionLow, 0);276 mapOptionalHex(IO, "File Flags Mask", Info.FileFlagsMask, 0);277 mapOptionalHex(IO, "File Flags", Info.FileFlags, 0);278 mapOptionalHex(IO, "File OS", Info.FileOS, 0);279 mapOptionalHex(IO, "File Type", Info.FileType, 0);280 mapOptionalHex(IO, "File Subtype", Info.FileSubtype, 0);281 mapOptionalHex(IO, "File Date High", Info.FileDateHigh, 0);282 mapOptionalHex(IO, "File Date Low", Info.FileDateLow, 0);283}284 285void yaml::MappingTraits<ModuleListStream::entry_type>::mapping(286 IO &IO, ModuleListStream::entry_type &M) {287 mapRequiredHex(IO, "Base of Image", M.Entry.BaseOfImage);288 mapRequiredHex(IO, "Size of Image", M.Entry.SizeOfImage);289 mapOptionalHex(IO, "Checksum", M.Entry.Checksum, 0);290 mapOptional(IO, "Time Date Stamp", M.Entry.TimeDateStamp, 0);291 IO.mapRequired("Module Name", M.Name);292 IO.mapOptional("Version Info", M.Entry.VersionInfo, VSFixedFileInfo());293 IO.mapRequired("CodeView Record", M.CvRecord);294 IO.mapOptional("Misc Record", M.MiscRecord, yaml::BinaryRef());295 mapOptionalHex(IO, "Reserved0", M.Entry.Reserved0, 0);296 mapOptionalHex(IO, "Reserved1", M.Entry.Reserved1, 0);297}298 299static void streamMapping(yaml::IO &IO, RawContentStream &Stream) {300 IO.mapOptional("Content", Stream.Content);301 IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size());302}303 304static std::string streamValidate(RawContentStream &Stream) {305 if (Stream.Size.value < Stream.Content.binary_size())306 return "Stream size must be greater or equal to the content size";307 return "";308}309 310void yaml::MappingTraits<MemoryListStream::entry_type>::mapping(311 IO &IO, MemoryListStream::entry_type &Range) {312 MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(313 IO, Range.Entry, Range.Content);314}315 316static void streamMapping(yaml::IO &IO, MemoryInfoListStream &Stream) {317 IO.mapRequired("Memory Ranges", Stream.Infos);318}319 320static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {321 IO.mapRequired("Memory Ranges", Stream.Entries);322}323 324static void streamMapping(yaml::IO &IO, Memory64ListStream &Stream) {325 IO.mapRequired("Memory Ranges", Stream.Entries);326}327 328static std::string streamValidate(Memory64ListStream &Stream) {329 for (auto &Entry : Stream.Entries) {330 if (Entry.Entry.DataSize < Entry.Content.binary_size())331 return "Memory region size must be greater or equal to the content size";332 }333 return "";334}335 336static void streamMapping(yaml::IO &IO, ModuleListStream &Stream) {337 IO.mapRequired("Modules", Stream.Entries);338}339 340static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) {341 SystemInfo &Info = Stream.Info;342 IO.mapRequired("Processor Arch", Info.ProcessorArch);343 mapOptional(IO, "Processor Level", Info.ProcessorLevel, 0);344 mapOptional(IO, "Processor Revision", Info.ProcessorRevision, 0);345 IO.mapOptional("Number of Processors", Info.NumberOfProcessors, 0);346 IO.mapOptional("Product type", Info.ProductType, 0);347 mapOptional(IO, "Major Version", Info.MajorVersion, 0);348 mapOptional(IO, "Minor Version", Info.MinorVersion, 0);349 mapOptional(IO, "Build Number", Info.BuildNumber, 0);350 IO.mapRequired("Platform ID", Info.PlatformId);351 IO.mapOptional("CSD Version", Stream.CSDVersion, "");352 mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);353 mapOptionalHex(IO, "Reserved", Info.Reserved, 0);354 switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {355 case ProcessorArchitecture::X86:356 case ProcessorArchitecture::AMD64:357 IO.mapOptional("CPU", Info.CPU.X86);358 break;359 case ProcessorArchitecture::ARM:360 case ProcessorArchitecture::ARM64:361 case ProcessorArchitecture::BP_ARM64:362 IO.mapOptional("CPU", Info.CPU.Arm);363 break;364 default:365 IO.mapOptional("CPU", Info.CPU.Other);366 break;367 }368}369 370static void streamMapping(yaml::IO &IO, TextContentStream &Stream) {371 IO.mapOptional("Text", Stream.Text);372}373 374void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(375 IO &IO, MemoryDescriptor &Memory, BinaryRef &Content) {376 mapRequiredHex(IO, "Start of Memory Range", Memory.StartOfMemoryRange);377 IO.mapRequired("Content", Content);378}379 380void yaml::MappingContextTraits<MemoryDescriptor_64, yaml::BinaryRef>::mapping(381 IO &IO, MemoryDescriptor_64 &Memory, BinaryRef &Content) {382 mapRequiredHex(IO, "Start of Memory Range", Memory.StartOfMemoryRange);383 IO.mapRequired("Content", Content);384 mapOptional(IO, "Data Size", Memory.DataSize, Content.binary_size());385}386 387void yaml::MappingTraits<ThreadListStream::entry_type>::mapping(388 IO &IO, ThreadListStream::entry_type &T) {389 mapRequiredHex(IO, "Thread Id", T.Entry.ThreadId);390 mapOptionalHex(IO, "Suspend Count", T.Entry.SuspendCount, 0);391 mapOptionalHex(IO, "Priority Class", T.Entry.PriorityClass, 0);392 mapOptionalHex(IO, "Priority", T.Entry.Priority, 0);393 mapOptionalHex(IO, "Environment Block", T.Entry.EnvironmentBlock, 0);394 IO.mapRequired("Context", T.Context);395 IO.mapRequired("Stack", T.Entry.Stack, T.Stack);396}397 398static void streamMapping(yaml::IO &IO, ThreadListStream &Stream) {399 IO.mapRequired("Threads", Stream.Entries);400}401 402static void streamMapping(yaml::IO &IO, MinidumpYAML::ExceptionStream &Stream) {403 mapRequiredHex(IO, "Thread ID", Stream.MDExceptionStream.ThreadId);404 IO.mapRequired("Exception Record", Stream.MDExceptionStream.ExceptionRecord);405 IO.mapRequired("Thread Context", Stream.ThreadContext);406}407 408void yaml::MappingTraits<minidump::Exception>::mapping(409 yaml::IO &IO, minidump::Exception &Exception) {410 mapRequiredHex(IO, "Exception Code", Exception.ExceptionCode);411 mapOptionalHex(IO, "Exception Flags", Exception.ExceptionFlags, 0);412 mapOptionalHex(IO, "Exception Record", Exception.ExceptionRecord, 0);413 mapOptionalHex(IO, "Exception Address", Exception.ExceptionAddress, 0);414 mapOptional(IO, "Number of Parameters", Exception.NumberParameters, 0);415 416 for (size_t Index = 0; Index < Exception.MaxParameters; ++Index) {417 SmallString<16> Name("Parameter ");418 Twine(Index).toVector(Name);419 support::ulittle64_t &Field = Exception.ExceptionInformation[Index];420 421 if (Index < Exception.NumberParameters)422 mapRequiredHex(IO, Name.c_str(), Field);423 else424 mapOptionalHex(IO, Name.c_str(), Field, 0);425 }426}427 428void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(429 yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {430 StreamType Type;431 if (IO.outputting())432 Type = S->Type;433 IO.mapRequired("Type", Type);434 435 if (!IO.outputting())436 S = MinidumpYAML::Stream::create(Type);437 switch (S->Kind) {438 case MinidumpYAML::Stream::StreamKind::Exception:439 streamMapping(IO, llvm::cast<MinidumpYAML::ExceptionStream>(*S));440 break;441 case MinidumpYAML::Stream::StreamKind::MemoryInfoList:442 streamMapping(IO, llvm::cast<MemoryInfoListStream>(*S));443 break;444 case MinidumpYAML::Stream::StreamKind::MemoryList:445 streamMapping(IO, llvm::cast<MemoryListStream>(*S));446 break;447 case MinidumpYAML::Stream::StreamKind::Memory64List:448 streamMapping(IO, llvm::cast<Memory64ListStream>(*S));449 break;450 case MinidumpYAML::Stream::StreamKind::ModuleList:451 streamMapping(IO, llvm::cast<ModuleListStream>(*S));452 break;453 case MinidumpYAML::Stream::StreamKind::RawContent:454 streamMapping(IO, llvm::cast<RawContentStream>(*S));455 break;456 case MinidumpYAML::Stream::StreamKind::SystemInfo:457 streamMapping(IO, llvm::cast<SystemInfoStream>(*S));458 break;459 case MinidumpYAML::Stream::StreamKind::TextContent:460 streamMapping(IO, llvm::cast<TextContentStream>(*S));461 break;462 case MinidumpYAML::Stream::StreamKind::ThreadList:463 streamMapping(IO, llvm::cast<ThreadListStream>(*S));464 break;465 }466}467 468std::string yaml::MappingTraits<std::unique_ptr<Stream>>::validate(469 yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {470 switch (S->Kind) {471 case MinidumpYAML::Stream::StreamKind::RawContent:472 return streamValidate(cast<RawContentStream>(*S));473 case MinidumpYAML::Stream::StreamKind::Memory64List:474 return streamValidate(cast<Memory64ListStream>(*S));475 case MinidumpYAML::Stream::StreamKind::Exception:476 case MinidumpYAML::Stream::StreamKind::MemoryInfoList:477 case MinidumpYAML::Stream::StreamKind::MemoryList:478 case MinidumpYAML::Stream::StreamKind::ModuleList:479 case MinidumpYAML::Stream::StreamKind::SystemInfo:480 case MinidumpYAML::Stream::StreamKind::TextContent:481 case MinidumpYAML::Stream::StreamKind::ThreadList:482 return "";483 }484 llvm_unreachable("Fully covered switch above!");485}486 487void yaml::MappingTraits<Object>::mapping(IO &IO, Object &O) {488 IO.mapTag("!minidump", true);489 mapOptionalHex(IO, "Signature", O.Header.Signature, Header::MagicSignature);490 mapOptionalHex(IO, "Version", O.Header.Version, Header::MagicVersion);491 mapOptionalHex(IO, "Flags", O.Header.Flags, 0);492 IO.mapRequired("Streams", O.Streams);493}494 495Expected<std::unique_ptr<Stream>>496Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {497 StreamKind Kind = getKind(StreamDesc.Type);498 switch (Kind) {499 case StreamKind::Exception: {500 Expected<const minidump::ExceptionStream &> ExpectedExceptionStream =501 File.getExceptionStream(StreamDesc);502 if (!ExpectedExceptionStream)503 return ExpectedExceptionStream.takeError();504 Expected<ArrayRef<uint8_t>> ExpectedThreadContext =505 File.getRawData(ExpectedExceptionStream->ThreadContext);506 if (!ExpectedThreadContext)507 return ExpectedThreadContext.takeError();508 return std::make_unique<ExceptionStream>(*ExpectedExceptionStream,509 *ExpectedThreadContext);510 }511 case StreamKind::MemoryInfoList: {512 if (auto ExpectedList = File.getMemoryInfoList())513 return std::make_unique<MemoryInfoListStream>(*ExpectedList);514 else515 return ExpectedList.takeError();516 }517 case StreamKind::MemoryList: {518 auto ExpectedList = File.getMemoryList();519 if (!ExpectedList)520 return ExpectedList.takeError();521 std::vector<MemoryListStream::entry_type> Ranges;522 for (const MemoryDescriptor &MD : *ExpectedList) {523 auto ExpectedContent = File.getRawData(MD.Memory);524 if (!ExpectedContent)525 return ExpectedContent.takeError();526 Ranges.push_back({MD, *ExpectedContent});527 }528 return std::make_unique<MemoryListStream>(std::move(Ranges));529 }530 case StreamKind::Memory64List: {531 Error Err = Error::success();532 auto Memory64List = File.getMemory64List(Err);533 std::vector<Memory64ListStream::entry_type> Ranges;534 for (const auto &Pair : Memory64List) {535 Ranges.push_back({Pair.first, Pair.second});536 }537 538 if (Err)539 return Err;540 return std::make_unique<Memory64ListStream>(std::move(Ranges));541 }542 case StreamKind::ModuleList: {543 auto ExpectedList = File.getModuleList();544 if (!ExpectedList)545 return ExpectedList.takeError();546 std::vector<ModuleListStream::entry_type> Modules;547 for (const Module &M : *ExpectedList) {548 auto ExpectedName = File.getString(M.ModuleNameRVA);549 if (!ExpectedName)550 return ExpectedName.takeError();551 auto ExpectedCv = File.getRawData(M.CvRecord);552 if (!ExpectedCv)553 return ExpectedCv.takeError();554 auto ExpectedMisc = File.getRawData(M.MiscRecord);555 if (!ExpectedMisc)556 return ExpectedMisc.takeError();557 Modules.push_back(558 {M, std::move(*ExpectedName), *ExpectedCv, *ExpectedMisc});559 }560 return std::make_unique<ModuleListStream>(std::move(Modules));561 }562 case StreamKind::RawContent:563 return std::make_unique<RawContentStream>(StreamDesc.Type,564 File.getRawStream(StreamDesc));565 case StreamKind::SystemInfo: {566 auto ExpectedInfo = File.getSystemInfo();567 if (!ExpectedInfo)568 return ExpectedInfo.takeError();569 auto ExpectedCSDVersion = File.getString(ExpectedInfo->CSDVersionRVA);570 if (!ExpectedCSDVersion)571 return ExpectedInfo.takeError();572 return std::make_unique<SystemInfoStream>(*ExpectedInfo,573 std::move(*ExpectedCSDVersion));574 }575 case StreamKind::TextContent:576 return std::make_unique<TextContentStream>(577 StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc)));578 case StreamKind::ThreadList: {579 auto ExpectedList = File.getThreadList();580 if (!ExpectedList)581 return ExpectedList.takeError();582 std::vector<ThreadListStream::entry_type> Threads;583 for (const Thread &T : *ExpectedList) {584 auto ExpectedStack = File.getRawData(T.Stack.Memory);585 if (!ExpectedStack)586 return ExpectedStack.takeError();587 auto ExpectedContext = File.getRawData(T.Context);588 if (!ExpectedContext)589 return ExpectedContext.takeError();590 Threads.push_back({T, *ExpectedStack, *ExpectedContext});591 }592 return std::make_unique<ThreadListStream>(std::move(Threads));593 }594 }595 llvm_unreachable("Unhandled stream kind!");596}597 598Expected<Object> Object::create(const object::MinidumpFile &File) {599 std::vector<std::unique_ptr<Stream>> Streams;600 Streams.reserve(File.streams().size());601 for (const Directory &StreamDesc : File.streams()) {602 auto ExpectedStream = Stream::create(StreamDesc, File);603 if (!ExpectedStream)604 return ExpectedStream.takeError();605 Streams.push_back(std::move(*ExpectedStream));606 }607 return Object(File.header(), std::move(Streams));608}609