brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.3 KiB · a9b996c Raw
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