labath created this revision.
labath added reviewers: Bigcheese, jhenderson, zturner.
Herald added subscribers: fedor.sergeev, mgorny, dschuff, srhines.
Herald added a project: LLVM.

This commit adds enough code to be able to dump a simple minidump (a
windows "core" file) file into yaml. It consists of the following parts:

- the declarations of various structures and constants in the BinaryFormat 
library
- a basic minidump parser in the Object library
- code for converting a parsed minidump file into YAML

The three parts could technically be submitted separately, but I put them in a
single patch here since there is no way to test the first two parts until we are
able to produce some output.

After this patch, the development can go in three directions which can
be worked on more-or-less in parallel (and in smaller chunks):

- Add support for more stream types
- yaml2obj support for minidump files
- rebase lldb's minidump handling code onto the llvm Object parser


Repository:
  rL LLVM

https://reviews.llvm.org/D59291

Files:
  include/llvm/BinaryFormat/Magic.h
  include/llvm/BinaryFormat/Minidump.h
  include/llvm/BinaryFormat/MinidumpConstants.def
  include/llvm/Object/Binary.h
  include/llvm/Object/Minidump.h
  include/llvm/ObjectYAML/MinidumpYAML.h
  lib/BinaryFormat/Magic.cpp
  lib/Object/Binary.cpp
  lib/Object/CMakeLists.txt
  lib/Object/Minidump.cpp
  lib/Object/ObjectFile.cpp
  lib/Object/SymbolicFile.cpp
  lib/ObjectYAML/CMakeLists.txt
  lib/ObjectYAML/MinidumpYAML.cpp
  test/tools/obj2yaml/Inputs/basic-minidump.dmp
  test/tools/obj2yaml/basic-minidump.test
  tools/obj2yaml/CMakeLists.txt
  tools/obj2yaml/minidump2yaml.cpp
  tools/obj2yaml/obj2yaml.cpp
  tools/obj2yaml/obj2yaml.h

Index: tools/obj2yaml/obj2yaml.h
===================================================================
--- tools/obj2yaml/obj2yaml.h
+++ tools/obj2yaml/obj2yaml.h
@@ -23,6 +23,8 @@
                          const llvm::object::ObjectFile &Obj);
 std::error_code macho2yaml(llvm::raw_ostream &Out,
                            const llvm::object::Binary &Obj);
+llvm::Error minidump2yaml(llvm::raw_ostream &Out,
+                          const llvm::object::Binary &Obj);
 std::error_code wasm2yaml(llvm::raw_ostream &Out,
                           const llvm::object::WasmObjectFile &Obj);
 
Index: tools/obj2yaml/obj2yaml.cpp
===================================================================
--- tools/obj2yaml/obj2yaml.cpp
+++ tools/obj2yaml/obj2yaml.cpp
@@ -37,6 +37,8 @@
   // here with the other binary types.
   if (Binary.isMachO() || Binary.isMachOUniversalBinary())
     return errorCodeToError(macho2yaml(outs(), Binary));
+  if (Binary.isMinidump())
+    return minidump2yaml(outs(), Binary);
   // TODO: If this is an archive, then burst it and dump each entry
   if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
     return errorCodeToError(dumpObject(*Obj));
Index: tools/obj2yaml/minidump2yaml.cpp
===================================================================
--- /dev/null
+++ tools/obj2yaml/minidump2yaml.cpp
@@ -0,0 +1,28 @@
+//===- minidump2yaml.cpp - Minidump to yaml conversion tool -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "obj2yaml.h"
+#include "llvm/Object/Minidump.h"
+#include "llvm/ObjectYAML/MinidumpYAML.h"
+
+using namespace llvm;
+
+llvm::Error minidump2yaml(llvm::raw_ostream &Out,
+                          const llvm::object::Binary &Obj) {
+  const auto *MDObj = dyn_cast<object::MinidumpFile>(&Obj);
+  if (!MDObj)
+    return errorCodeToError(obj2yaml_error::unsupported_obj_file_format);
+
+  yaml::Output Yout(Out);
+  auto ExpectedObject = MinidumpYAML::Object::create(*MDObj);
+  if (!ExpectedObject)
+    return ExpectedObject.takeError();
+  Yout << *ExpectedObject;
+  return llvm::Error::success();
+}
Index: tools/obj2yaml/CMakeLists.txt
===================================================================
--- tools/obj2yaml/CMakeLists.txt
+++ tools/obj2yaml/CMakeLists.txt
@@ -13,6 +13,7 @@
   dwarf2yaml.cpp
   elf2yaml.cpp
   macho2yaml.cpp
+  minidump2yaml.cpp
   wasm2yaml.cpp
   Error.cpp
   )
Index: test/tools/obj2yaml/basic-minidump.test
===================================================================
--- /dev/null
+++ test/tools/obj2yaml/basic-minidump.test
@@ -0,0 +1,50 @@
+RUN: core2yaml %S/Inputs/basic-minidump.dmp | FileCheck %s
+
+CHECK:      --- !minidump
+CHECK-NEXT: Streams:         
+CHECK-NEXT:   - Type:            SystemInfo
+CHECK-NEXT:     Processor Arch:  ARM64
+CHECK-NEXT:     Platform ID:     Linux
+CHECK-NEXT:     CSD Version RVA: 0x00000288
+CHECK-NEXT:     CPU:             
+CHECK-NEXT:       CPUID:           0x00000000
+CHECK-NEXT:   - Type:            LinuxEnviron
+CHECK-NEXT:     Variables:       
+CHECK-NEXT:       - '/proc/<pid>/environ output'
+CHECK-NEXT:   - Type:            LinuxMaps
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process
+CHECK-NEXT:       400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process
+CHECK-NEXT:       400dc000-400dd000 rw-p 00000000 00:00 0 
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxProcStatus
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       /proc/<pid>/status output
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxProcStat
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       /proc/<pid>/stat output
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxCMDLine
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       /proc/<pid>/cmdline output
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxProcFD
+CHECK-NEXT:     Content:         2F70726F632F3C7069643E2F6664206F757470757400
+CHECK-NEXT:   - Type:            LinuxAuxv
+CHECK-NEXT:     Content:         2F70726F632F3C7069643E2F61757876206F757470757400
+CHECK-NEXT:   - Type:            MiscInfo
+CHECK-NEXT:     Content:         00000000010000007B000000000000000000000000000000
+CHECK-NEXT:   - Type:            LinuxCPUInfo
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       cpu info output
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxLSBRelease
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       /etc/lsb-release output
+CHECK-EMPTY:
+CHECK-NEXT:   - Type:            LinuxProcUptime
+CHECK-NEXT:     Text:             |
+CHECK-NEXT:       uptime output
+CHECK-EMPTY:
+CHECK-NEXT: ...
Index: lib/ObjectYAML/MinidumpYAML.cpp
===================================================================
--- /dev/null
+++ lib/ObjectYAML/MinidumpYAML.cpp
@@ -0,0 +1,276 @@
+//===- MinidumpYAML.cpp - Minidump YAMLIO implementation ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/MinidumpYAML.h"
+
+using namespace llvm;
+using namespace llvm::MinidumpYAML;
+using namespace llvm::minidump;
+
+/// Perform an optional yaml-mapping of an endian-aware type EndianType. The
+/// only purpose of this function is to avoid casting the Default value to the
+/// endian type;
+template <typename EndianType>
+static inline void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val,
+                               typename EndianType::value_type Default) {
+  IO.mapOptional(Key, Val, EndianType(Default));
+}
+
+/// Yaml-map an endian-aware type EndianType as some other type MapType.
+template <typename MapType, typename EndianType>
+static inline void mapAs(yaml::IO &IO, const char *Key, EndianType &Val) {
+  MapType Mapped = static_cast<typename EndianType::value_type>(Val);
+  IO.mapRequired(Key, Mapped);
+  Val = static_cast<typename EndianType::value_type>(Mapped);
+}
+
+/// Perform an optional yaml-mapping of an endian-aware type EndianType as some
+/// other type MapType.
+template <typename MapType, typename EndianType>
+static inline void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val,
+                                 MapType Default) {
+  MapType Mapped = static_cast<typename EndianType::value_type>(Val);
+  IO.mapOptional(Key, Mapped, Default);
+  Val = static_cast<typename EndianType::value_type>(Mapped);
+}
+
+namespace {
+/// Return the appropriate yaml Hex type for a given endian-aware type.
+template <typename EndianType> struct HexType;
+template <> struct HexType<support::ulittle16_t> { using type = yaml::Hex16; };
+template <> struct HexType<support::ulittle32_t> { using type = yaml::Hex32; };
+template <> struct HexType<support::ulittle64_t> { using type = yaml::Hex64; };
+} // namespace
+
+/// Yaml-map an endian-aware type as an appropriately-sized hex value.
+template <typename EndianType>
+static inline void mapHex(yaml::IO &IO, const char *Key, EndianType &Val) {
+  mapAs<typename HexType<EndianType>::type>(IO, Key, Val);
+}
+
+/// Perform an optionam yaml-mapping of an endian-aware type as an
+/// appropriately-sized hex value.
+template <typename EndianType>
+static inline void mapOptionalHex(yaml::IO &IO, const char *Key,
+                                  EndianType &Val,
+                                  typename EndianType::value_type Default) {
+  mapOptionalAs<typename HexType<EndianType>::type>(IO, Key, Val, Default);
+}
+
+Stream::~Stream() = default;
+
+Stream::StreamKind Stream::getKind(StreamType Type) {
+  switch (Type) {
+  case StreamType::LinuxEnviron:
+    return EnvironmentKind;
+  case StreamType::SystemInfo:
+    return SystemInfoKind;
+  case StreamType::LinuxCPUInfo:
+  case StreamType::LinuxProcStatus:
+  case StreamType::LinuxLSBRelease:
+  case StreamType::LinuxCMDLine:
+  case StreamType::LinuxMaps:
+  case StreamType::LinuxProcStat:
+  case StreamType::LinuxProcUptime:
+    return TextKind;
+  default:
+    return HexKind;
+  }
+}
+
+llvm::Expected<std::unique_ptr<Stream>>
+Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
+  StreamKind Kind = getKind(StreamDesc.Type);
+  switch (Kind) {
+  case HexKind:
+    return llvm::make_unique<HexStream>(StreamDesc.Type,
+                                        File.getRawStream(StreamDesc));
+  case EnvironmentKind: {
+    llvm::StringRef Data = toStringRef(File.getRawStream(StreamDesc));
+    llvm::SmallVector<llvm::StringRef, 0> Variables;
+    if (!Data.empty()) {
+      if (Data.back() != '\0')
+        return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                       "Environment is not null terminated.");
+      Data.split(Variables, '\0');
+      Variables.pop_back();
+    }
+    return llvm::make_unique<EnvironmentStream>(std::move(Variables));
+  }
+  case SystemInfoKind: {
+    Expected<SystemInfo> ExpectedInfo = File.getSystemInfo();
+    if (!ExpectedInfo)
+      return ExpectedInfo.takeError();
+    return llvm::make_unique<SystemInfoStream>(*ExpectedInfo);
+  }
+  case TextKind:
+    return llvm::make_unique<TextStream>(
+        StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc)));
+  }
+  llvm_unreachable("Unhandled stream kind!");
+}
+
+std::unique_ptr<Stream> Stream::create(StreamType Type) {
+  StreamKind Kind = getKind(Type);
+  switch (Kind) {
+  case HexKind:
+    return llvm::make_unique<HexStream>(Type);
+  case EnvironmentKind:
+    return llvm::make_unique<EnvironmentStream>();
+  case SystemInfoKind:
+    return llvm::make_unique<SystemInfoStream>();
+  case TextKind:
+    return llvm::make_unique<TextStream>(Type);
+  }
+  llvm_unreachable("Unhandled stream kind!");
+}
+
+llvm::Expected<Object> Object::create(const object::MinidumpFile &File) {
+  std::vector<std::unique_ptr<Stream>> Streams;
+  Streams.reserve(File.streams().size());
+  for (const Directory &StreamDesc : File.streams()) {
+    auto ExpectedStream = Stream::create(StreamDesc, File);
+    if (!ExpectedStream)
+      return ExpectedStream.takeError();
+    Streams.push_back(std::move(*ExpectedStream));
+  }
+  return Object(File.header(), std::move(Streams));
+}
+
+void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
+    IO &IO, ProcessorArchitecture &Arch) {
+#define HANDLE_MDMP_ARCH(CODE, NAME)                                           \
+  IO.enumCase(Arch, #NAME, ProcessorArchitecture::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  IO.enumFallback<Hex16>(Arch);
+}
+
+void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO,
+                                                            OSPlatform &Plat) {
+#define HANDLE_MDMP_PLATFORM(CODE, NAME)                                       \
+  IO.enumCase(Plat, #NAME, OSPlatform::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  IO.enumFallback<Hex32>(Plat);
+}
+
+void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO,
+                                                            StreamType &Type) {
+#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME)                                    \
+  IO.enumCase(Type, #NAME, StreamType::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  IO.enumFallback<Hex32>(Type);
+}
+
+void yaml::MappingTraits<CPUInfo::ArmInfo>::mapping(IO &IO,
+                                                    CPUInfo::ArmInfo &Info) {
+  mapHex(IO, "CPUID", Info.CPUID);
+  mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0);
+}
+
+void yaml::MappingTraits<CPUInfo::OtherInfo>::mapping(
+    IO &IO, CPUInfo::OtherInfo &Info) {
+  llvm::MutableArrayRef<uint8_t> Features(Info.ProcessorFeatures);
+  yaml::BinaryRef FeaturesRef(Features);
+
+  IO.mapRequired("Features", FeaturesRef);
+
+  llvm::SmallString<16> FeaturesStorage;
+  llvm::raw_svector_ostream FeaturesStream(FeaturesStorage);
+  FeaturesRef.writeAsBinary(FeaturesStream);
+  std::fill(Features.begin(), Features.end(), 0);
+  std::memcpy(Features.begin(), FeaturesStorage.begin(),
+              std::min(FeaturesStorage.size(), Features.size()));
+}
+
+void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO,
+                                                    CPUInfo::X86Info &Info) {
+  llvm::StringRef VendorID(Info.VendorID, sizeof(Info.VendorID));
+  IO.mapRequired("Vendor ID", VendorID);
+  std::fill_n(Info.VendorID, sizeof(Info.VendorID), 0);
+  std::copy_n(VendorID.begin(),
+              std::min(VendorID.size(), sizeof(Info.VendorID)), Info.VendorID);
+
+  mapHex(IO, "Version Info", Info.FeatureInfo);
+  mapHex(IO, "Feature Info", Info.FeatureInfo);
+  mapOptionalHex(IO, "AMD Extended CPU Features", Info.AMDExtendedFeatures, 0);
+}
+
+static void streamMapping(yaml::IO &IO, EnvironmentStream &Stream) {
+  IO.mapRequired("Variables", Stream.Variables);
+}
+
+static void streamMapping(yaml::IO &IO, HexStream &Stream) {
+  IO.mapOptional("Content", Stream.Content);
+  IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size());
+}
+
+static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) {
+  SystemInfo &Info = Stream.Info;
+  IO.mapRequired("Processor Arch", Info.ProcessorArch);
+  mapOptional(IO, "Processor Level", Info.ProcessorLevel, 0);
+  mapOptional(IO, "Processor Revision", Info.ProcessorRevision, 0);
+  IO.mapOptional("Number of Processors", Info.NumberOfProcessors, 0);
+  IO.mapOptional("Product type", Info.ProductType, 0);
+  mapOptional(IO, "Major Version", Info.MajorVersion, 0);
+  mapOptional(IO, "Minor Version", Info.MinorVersion, 0);
+  mapOptional(IO, "Build Number", Info.BuildNumber, 0);
+  IO.mapRequired("Platform ID", Info.PlatformId);
+  mapOptionalHex(IO, "CSD Version RVA", Info.CSDVersionRVA, 0);
+  mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);
+  mapOptionalHex(IO, "Reserved", Info.Reserved, 0);
+  switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {
+  case ProcessorArchitecture::X86:
+  case ProcessorArchitecture::AMD64:
+    IO.mapOptional("CPU", Info.CPU.X86);
+    break;
+  case ProcessorArchitecture::ARM:
+  case ProcessorArchitecture::ARM64:
+    IO.mapOptional("CPU", Info.CPU.Arm);
+    break;
+  default:
+    IO.mapOptional("CPU", Info.CPU.Other);
+    break;
+  }
+}
+
+static void streamMapping(yaml::IO &IO, TextStream &Stream) {
+  IO.mapOptional("Text", Stream.Text);
+}
+
+void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
+    yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
+  StreamType Type;
+  if (IO.outputting())
+    Type = S->Type;
+  IO.mapRequired("Type", Type);
+
+  if (!IO.outputting())
+    S = MinidumpYAML::Stream::create(Type);
+  switch (S->Kind) {
+  case MinidumpYAML::Stream::EnvironmentKind:
+    streamMapping(IO, llvm::cast<EnvironmentStream>(*S));
+    break;
+  case MinidumpYAML::Stream::HexKind:
+    streamMapping(IO, llvm::cast<HexStream>(*S));
+    break;
+  case MinidumpYAML::Stream::SystemInfoKind:
+    streamMapping(IO, llvm::cast<SystemInfoStream>(*S));
+    break;
+  case MinidumpYAML::Stream::TextKind:
+    streamMapping(IO, llvm::cast<TextStream>(*S));
+    break;
+  }
+}
+
+void yaml::MappingTraits<Object>::mapping(IO &IO, Object &O) {
+  IO.mapTag("!minidump", true);
+  mapOptionalHex(IO, "Signature", O.Header.Signature, Header::MagicSignature);
+  mapOptionalHex(IO, "Version", O.Header.Version, Header::MagicVersion);
+  mapOptionalHex(IO, "Flags", O.Header.Flags, 0);
+  IO.mapRequired("Streams", O.Streams);
+}
Index: lib/ObjectYAML/CMakeLists.txt
===================================================================
--- lib/ObjectYAML/CMakeLists.txt
+++ lib/ObjectYAML/CMakeLists.txt
@@ -10,6 +10,7 @@
   ELFYAML.cpp
   MachOYAML.cpp
   ObjectYAML.cpp
+  MinidumpYAML.cpp
   WasmYAML.cpp
   YAML.cpp
   )
Index: lib/Object/SymbolicFile.cpp
===================================================================
--- lib/Object/SymbolicFile.cpp
+++ lib/Object/SymbolicFile.cpp
@@ -52,6 +52,7 @@
   case file_magic::macho_universal_binary:
   case file_magic::windows_resource:
   case file_magic::pdb:
+  case file_magic::minidump:
     return errorCodeToError(object_error::invalid_file_type);
   case file_magic::elf:
   case file_magic::elf_executable:
Index: lib/Object/ObjectFile.cpp
===================================================================
--- lib/Object/ObjectFile.cpp
+++ lib/Object/ObjectFile.cpp
@@ -127,6 +127,7 @@
   case file_magic::macho_universal_binary:
   case file_magic::windows_resource:
   case file_magic::pdb:
+  case file_magic::minidump:
     return errorCodeToError(object_error::invalid_file_type);
   case file_magic::elf:
   case file_magic::elf_relocatable:
Index: lib/Object/Minidump.cpp
===================================================================
--- /dev/null
+++ lib/Object/Minidump.cpp
@@ -0,0 +1,72 @@
+//===- Minidump.cpp - Minidump object file implementation -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/Minidump.h"
+#include "llvm/Object/Error.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::minidump;
+
+Optional<ArrayRef<uint8_t>>
+MinidumpFile::getRawStream(minidump::StreamType Type) const {
+  auto It = StreamMap.find(Type);
+  if (It != StreamMap.end())
+    return getRawStream(Streams[It->second]);
+  return None;
+}
+
+Expected<ArrayRef<uint8_t>>
+MinidumpFile::getDataSlice(ArrayRef<uint8_t> Data, size_t Offset, size_t Size) {
+  // Check for overflow.
+  if (Offset + Size < Offset || Offset + Size < Size ||
+      Offset + Size > Data.size())
+    return createEOFError();
+  return Data.slice(Offset, Size);
+}
+
+Expected<std::unique_ptr<MinidumpFile>>
+MinidumpFile::create(MemoryBufferRef Source) {
+  ArrayRef<uint8_t> Data = arrayRefFromStringRef(Source.getBuffer());
+  auto ExpectedHeader = getDataSliceAs<minidump::Header>(Data, 0, 1);
+  if (!ExpectedHeader)
+    return ExpectedHeader.takeError();
+
+  const minidump::Header &Hdr = (*ExpectedHeader)[0];
+  if (Hdr.Signature != Header::MagicSignature)
+    return createError("Invalid signature.");
+  if ((Hdr.MagicVersion & 0xffff) != Header::MagicVersion)
+    return createError("Invalid version.");
+
+  auto ExpectedStreams = getDataSliceAs<Directory>(Data, Hdr.StreamDirectoryRVA,
+                                                   Hdr.NumberOfStreams);
+  if (!ExpectedStreams)
+    return ExpectedStreams.takeError();
+
+  std::unordered_map<StreamType, std::size_t> StreamMap;
+  for (const auto &Stream : llvm::enumerate(*ExpectedStreams)) {
+    if (Stream.value().Type == StreamType::Unused &&
+        Stream.value().Location.DataSize == 0) {
+      // Ignore dummy streams. This is technically ill-formed, but a number of
+      // existing minidumps seem to contain such streams.
+      continue;
+    }
+
+    auto ExpectedStream = getDataSlice(Data, Stream.value().Location.RVA,
+                                       Stream.value().Location.DataSize);
+    if (!ExpectedStream)
+      return ExpectedStream.takeError();
+
+    // Update the directory map, checking for duplicate stream types.
+    if (!StreamMap.emplace(Stream.value().Type, Stream.index()).second)
+      return createError("Duplicate stream type.");
+  }
+
+  return std::unique_ptr<MinidumpFile>(
+      new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap)));
+}
Index: lib/Object/CMakeLists.txt
===================================================================
--- lib/Object/CMakeLists.txt
+++ lib/Object/CMakeLists.txt
@@ -13,6 +13,7 @@
   IRSymtab.cpp
   MachOObjectFile.cpp
   MachOUniversal.cpp
+  Minidump.cpp
   ModuleSymbolTable.cpp
   Object.cpp
   ObjectFile.cpp
Index: lib/Object/Binary.cpp
===================================================================
--- lib/Object/Binary.cpp
+++ lib/Object/Binary.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/Error.h"
 #include "llvm/Object/MachOUniversal.h"
+#include "llvm/Object/Minidump.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/WindowsResource.h"
 #include "llvm/Support/Error.h"
@@ -81,6 +82,8 @@
   case file_magic::coff_cl_gl_object:
     // Unrecognized object file format.
     return errorCodeToError(object_error::invalid_file_type);
+  case file_magic::minidump:
+    return MinidumpFile::create(Buffer);
   }
   llvm_unreachable("Unexpected Binary File Type");
 }
Index: lib/BinaryFormat/Magic.cpp
===================================================================
--- lib/BinaryFormat/Magic.cpp
+++ lib/BinaryFormat/Magic.cpp
@@ -181,7 +181,8 @@
       return file_magic::coff_object;
     break;
 
-  case 'M': // Possible MS-DOS stub on Windows PE file or MSF/PDB file.
+  case 'M': // Possible MS-DOS stub on Windows PE file, MSF/PDB file or a
+            // Minidump file.
     if (startswith(Magic, "MZ") && Magic.size() >= 0x3c + 4) {
       uint32_t off = read32le(Magic.data() + 0x3c);
       // PE/COFF file, either EXE or DLL.
@@ -191,6 +192,8 @@
     }
     if (Magic.startswith("Microsoft C/C++ MSF 7.00\r\n"))
       return file_magic::pdb;
+    if (startswith(Magic, "MDMP"))
+      return file_magic::minidump;
     break;
 
   case 0x64: // x86-64 or ARM64 Windows.
Index: include/llvm/ObjectYAML/MinidumpYAML.h
===================================================================
--- /dev/null
+++ include/llvm/ObjectYAML/MinidumpYAML.h
@@ -0,0 +1,163 @@
+//===- MinidumpYAML.h - Minidump YAMLIO implementation ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_MINIDUMPYAML_H
+#define LLVM_OBJECTYAML_MINIDUMPYAML_H
+
+#include "llvm/Object/Minidump.h"
+#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace MinidumpYAML {
+
+/// The base class for all minidump streams. The "Type" of the stream
+/// corresponds to the Stream Type field in the minidump file. The "Kind" field
+/// specifies how are we going to treat it. For highly specialized streams (e.g.
+/// SystemInfo), there is a 1:1 mapping between Types and Kinds, but in general
+/// one stream Kind can be used to represent multiple stream Types (e.g. any
+/// unrecognised stream Type will be handled via HexStream). The mapping from
+/// Types to Kinds is fixed and given by the static getKind function.
+struct Stream {
+  enum StreamKind {
+    EnvironmentKind,
+    HexKind,
+    SystemInfoKind,
+    TextKind,
+  };
+
+  Stream(StreamKind Kind, minidump::StreamType Type) : Kind(Kind), Type(Type) {}
+  virtual ~Stream(); // anchor
+
+  const StreamKind Kind;
+  const minidump::StreamType Type;
+
+  /// Get the stream Kind used for representing streams of a given Type.
+  static StreamKind getKind(minidump::StreamType Type);
+
+  /// Construct a stream of the given Type, using the data in the minidump file.
+  static Expected<std::unique_ptr<Stream>>
+  create(const minidump::Directory &StreamDesc,
+         const object::MinidumpFile &File);
+
+  /// Create an empty stream of the given Type.
+  static std::unique_ptr<Stream> create(minidump::StreamType Type);
+};
+
+/// A stream containing the execution environment of the process.
+struct EnvironmentStream : public Stream {
+  SmallVector<StringRef, 0> Variables;
+
+  explicit EnvironmentStream(SmallVector<StringRef, 0> Variables = {})
+      : Stream(EnvironmentKind, minidump::StreamType::LinuxEnviron),
+        Variables(std::move(Variables)) {}
+
+  static bool classof(const Stream *S) { return S->Kind == EnvironmentKind; }
+};
+
+/// A minidump stream represented as a sequence of hex bytes. This is used as a
+/// fallback when no other stream kind is suitable.
+struct HexStream : public Stream {
+  yaml::BinaryRef Content;
+  yaml::Hex32 Size;
+
+  HexStream(minidump::StreamType Type, ArrayRef<uint8_t> Content = {})
+      : Stream(HexKind, Type), Content(Content), Size(Content.size()) {}
+
+  static bool classof(const Stream *S) { return S->Kind == HexKind; }
+};
+
+/// SystemInfo minidump stream.
+struct SystemInfoStream : public Stream {
+  minidump::SystemInfo Info;
+
+  explicit SystemInfoStream(const minidump::SystemInfo &Info)
+      : Stream(SystemInfoKind, minidump::StreamType::SystemInfo), Info(Info) {}
+
+  SystemInfoStream()
+      : Stream(SystemInfoKind, minidump::StreamType::SystemInfo) {
+    memset(&Info, 0, sizeof(Info));
+  }
+
+  static bool classof(const Stream *S) { return S->Kind == SystemInfoKind; }
+};
+
+/// A StringRef, which is printed using YAML block notation.
+LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef)
+
+/// A minidump stream containing textual data (typically, the contents of a
+/// /proc/<pid> file on linux).
+struct TextStream : public Stream {
+  BlockStringRef Text;
+
+  TextStream(minidump::StreamType Type, StringRef Text = {})
+      : Stream(TextKind, Type), Text(Text) {}
+
+  static bool classof(const Stream *S) { return S->Kind == TextKind; }
+};
+
+/// The top level structure representing a minidump object, consisting of a
+/// minidump header, and zero or more streams. To construct an Object from a
+/// minidump file, use the static create function. To serialize to/from yaml,
+/// use the appropriate streaming operator on a yaml stream.
+/// TODO: Add minidump serialization support.
+struct Object {
+  Object(const minidump::Header &Header,
+         std::vector<std::unique_ptr<Stream>> Streams)
+      : Header(Header), Streams(std::move(Streams)) {}
+
+  Object(const Object &) = delete;
+  Object &operator=(const Object &) = delete;
+  Object(Object &&) = default;
+  Object &operator=(Object &&) = default;
+
+  /// The minidump header.
+  minidump::Header Header;
+
+  /// The list of streams in this minidump object.
+  std::vector<std::unique_ptr<Stream>> Streams;
+
+  /// Construct a minidump object from the given minidump file. The returned
+  /// object contains references to the data in the minidump file, so the parser
+  /// instance should outlive the minidump object.
+  static Expected<Object> create(const object::MinidumpFile &File);
+};
+
+} // namespace MinidumpYAML
+
+namespace yaml {
+template <> struct BlockScalarTraits<MinidumpYAML::BlockStringRef> {
+  static void output(const MinidumpYAML::BlockStringRef &Text, void *,
+                     raw_ostream &OS) {
+    OS << Text;
+  }
+
+  static StringRef input(StringRef Scalar, void *,
+                         MinidumpYAML::BlockStringRef &Text) {
+    Text = Scalar;
+    return "";
+  }
+};
+} // namespace yaml
+
+} // namespace llvm
+
+LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
+LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
+LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(std::unique_ptr<llvm::MinidumpYAML::Stream>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
+
+#endif // LLVM_OBJECTYAML_MINIDUMPYAML_H
Index: include/llvm/Object/Minidump.h
===================================================================
--- /dev/null
+++ include/llvm/Object/Minidump.h
@@ -0,0 +1,101 @@
+//===- Minidump.h - Minidump object file implementation ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_MINIDUMP_H
+#define LLVM_OBJECT_MINIDUMP_H
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Minidump.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Support/Error.h"
+#include <unordered_map>
+
+namespace llvm {
+namespace object {
+
+class MinidumpFile : public Binary {
+public:
+  static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source);
+
+  static bool classof(const Binary *B) { return B->isMinidump(); }
+
+  const minidump::Header &header() const { return Header; }
+  ArrayRef<minidump::Directory> streams() const { return Streams; }
+
+  ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const {
+    return getData().slice(Stream.Location.RVA, Stream.Location.DataSize);
+  }
+
+  Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const;
+
+  Expected<const minidump::SystemInfo &> getSystemInfo() const {
+    return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo);
+  }
+
+private:
+  static Error createError(StringRef Str,
+                           object_error Err = object_error::parse_failed) {
+    return make_error<GenericBinaryError>(Str, Err);
+  }
+
+  static Error createEOFError() {
+    return createError("Unexpected EOF.", object_error::unexpected_eof);
+  }
+
+  static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data,
+                                                  size_t Offset, size_t Size);
+
+  template <typename T>
+  static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data,
+                                              size_t Offset, size_t Count);
+
+  MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header,
+               ArrayRef<minidump::Directory> Streams,
+               std::unordered_map<minidump::StreamType, std::size_t> StreamMap)
+      : Binary(ID_Minidump, Source), Header(Header), Streams(Streams),
+        StreamMap(std::move(StreamMap)) {}
+
+  ArrayRef<uint8_t> getData() const {
+    return arrayRefFromStringRef(Data.getBuffer());
+  }
+
+  template <typename T>
+  Expected<const T &> getStream(minidump::StreamType Stream) const;
+
+  const minidump::Header &Header;
+  ArrayRef<minidump::Directory> Streams;
+  std::unordered_map<minidump::StreamType, std::size_t> StreamMap;
+};
+
+template <typename T>
+Expected<const T &> MinidumpFile::getStream(minidump::StreamType Stream) const {
+  if (auto OptionalStream = getRawStream(Stream)) {
+    if (OptionalStream->size() >= sizeof(T))
+      return *reinterpret_cast<const T *>(OptionalStream->data());
+    return createError("Malformed stream.", object_error::unexpected_eof);
+  }
+  return createError("No such stream.", object_error::invalid_section_index);
+}
+
+template <typename T>
+Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data,
+                                                   size_t Offset,
+                                                   size_t Count) {
+  // Check for overflow.
+  if (Count > std::numeric_limits<size_t>::max() / sizeof(T))
+    return createEOFError();
+  auto ExpectedArray = getDataSlice(Data, Offset, sizeof(T) * Count);
+  if (!ExpectedArray)
+    return ExpectedArray.takeError();
+  return ArrayRef<T>(reinterpret_cast<const T *>(ExpectedArray->data()), Count);
+}
+
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_MINIDUMP_H
Index: include/llvm/Object/Binary.h
===================================================================
--- include/llvm/Object/Binary.h
+++ include/llvm/Object/Binary.h
@@ -41,7 +41,9 @@
     ID_Archive,
     ID_MachOUniversalBinary,
     ID_COFFImportFile,
-    ID_IR,                 // LLVM IR
+    ID_IR, // LLVM IR
+
+    ID_Minidump,
 
     ID_WinRes, // Windows resource (.res) file.
 
@@ -127,6 +129,8 @@
     return TypeID == ID_IR;
   }
 
+  bool isMinidump() const { return TypeID == ID_Minidump; }
+
   bool isLittleEndian() const {
     return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
              TypeID == ID_MachO32B || TypeID == ID_MachO64B);
Index: include/llvm/BinaryFormat/MinidumpConstants.def
===================================================================
--- /dev/null
+++ include/llvm/BinaryFormat/MinidumpConstants.def
@@ -0,0 +1,107 @@
+//===- MinidumpConstants.def - Iteration over minidump constants-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_MDMP_STREAM_TYPE || defined HANDLE_MDMP_ARCH ||           \
+      defined HANDLE_MDMP_PLATFORM)
+#error "Missing HANDLE_MDMP definition"
+#endif
+
+#ifndef HANDLE_MDMP_STREAM_TYPE
+#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME)
+#endif
+
+#ifndef HANDLE_MDMP_ARCH
+#define HANDLE_MDMP_ARCH(CODE, NAME)
+#endif
+
+#ifndef HANDLE_MDMP_PLATFORM
+#define HANDLE_MDMP_PLATFORM(CODE, NAME)
+#endif
+
+HANDLE_MDMP_STREAM_TYPE(0x0003, ThreadList)
+HANDLE_MDMP_STREAM_TYPE(0x0004, ModuleList)
+HANDLE_MDMP_STREAM_TYPE(0x0005, MemoryList)
+HANDLE_MDMP_STREAM_TYPE(0x0006, Exception)
+HANDLE_MDMP_STREAM_TYPE(0x0007, SystemInfo)
+HANDLE_MDMP_STREAM_TYPE(0x0008, ThreadExList)
+HANDLE_MDMP_STREAM_TYPE(0x0009, Memory64List)
+HANDLE_MDMP_STREAM_TYPE(0x000a, CommentA)
+HANDLE_MDMP_STREAM_TYPE(0x000b, CommentW)
+HANDLE_MDMP_STREAM_TYPE(0x000c, HandleData)
+HANDLE_MDMP_STREAM_TYPE(0x000d, FunctionTable)
+HANDLE_MDMP_STREAM_TYPE(0x000e, UnloadedModuleList)
+HANDLE_MDMP_STREAM_TYPE(0x000f, MiscInfo)
+HANDLE_MDMP_STREAM_TYPE(0x0010, MemoryInfoList)
+HANDLE_MDMP_STREAM_TYPE(0x0011, ThreadInfoList)
+HANDLE_MDMP_STREAM_TYPE(0x0012, HandleOperationList)
+HANDLE_MDMP_STREAM_TYPE(0x0013, Token)
+HANDLE_MDMP_STREAM_TYPE(0x0014, JavascriptData)
+HANDLE_MDMP_STREAM_TYPE(0x0015, SystemMemoryInfo)
+HANDLE_MDMP_STREAM_TYPE(0x0016, ProcessVMCounters)
+// Breakpad extension types.  0x4767 = "Gg"
+HANDLE_MDMP_STREAM_TYPE(0x47670001, BreakpadInfo)
+HANDLE_MDMP_STREAM_TYPE(0x47670002, AssertionInfo)
+// These are additional minidump stream values which are specific to the linux
+// breakpad implementation.
+HANDLE_MDMP_STREAM_TYPE(0x47670003, LinuxCPUInfo)    // /proc/cpuinfo
+HANDLE_MDMP_STREAM_TYPE(0x47670004, LinuxProcStatus) // /proc/$x/status
+HANDLE_MDMP_STREAM_TYPE(0x47670005, LinuxLSBRelease) // /etc/lsb-release
+HANDLE_MDMP_STREAM_TYPE(0x47670006, LinuxCMDLine)    // /proc/$x/cmdline
+HANDLE_MDMP_STREAM_TYPE(0x47670007, LinuxEnviron)    // /proc/$x/environ
+HANDLE_MDMP_STREAM_TYPE(0x47670008, LinuxAuxv)       // /proc/$x/auxv
+HANDLE_MDMP_STREAM_TYPE(0x47670009, LinuxMaps)       // /proc/$x/maps
+HANDLE_MDMP_STREAM_TYPE(0x4767000A, LinuxDSODebug)
+HANDLE_MDMP_STREAM_TYPE(0x4767000B, LinuxProcStat)   // /proc/$x/stat
+HANDLE_MDMP_STREAM_TYPE(0x4767000C, LinuxProcUptime) // uptime
+HANDLE_MDMP_STREAM_TYPE(0x4767000D, LinuxProcFD)     // /proc/$x/fd
+// Facebook-defined stream types
+HANDLE_MDMP_STREAM_TYPE(0xFACE1CA7, FacebookLogcat)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFA, FacebookAppCustomData)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFB, FacebookBuildID)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFC, FacebookAppVersionName)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFD, FacebookJavaStack)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFE, FacebookDalvikInfo)
+HANDLE_MDMP_STREAM_TYPE(0xFACECAFF, FacebookUnwindSymbols)
+HANDLE_MDMP_STREAM_TYPE(0xFACECB00, FacebookDumpErrorLog)
+HANDLE_MDMP_STREAM_TYPE(0xFACECCCC, FacebookAppStateLog)
+HANDLE_MDMP_STREAM_TYPE(0xFACEDEAD, FacebookAbortReason)
+HANDLE_MDMP_STREAM_TYPE(0xFACEE000, FacebookThreadName)
+
+HANDLE_MDMP_ARCH(0x0000, X86)      // PROCESSOR_ARCHITECTURE_INTEL
+HANDLE_MDMP_ARCH(0x0001, MIPS)     // PROCESSOR_ARCHITECTURE_MIPS
+HANDLE_MDMP_ARCH(0x0002, Alpha)    // PROCESSOR_ARCHITECTURE_ALPHA
+HANDLE_MDMP_ARCH(0x0003, PPC)      // PROCESSOR_ARCHITECTURE_PPC
+HANDLE_MDMP_ARCH(0x0004, SHX)      // PROCESSOR_ARCHITECTURE_SHX (Super-H)
+HANDLE_MDMP_ARCH(0x0005, ARM)      // PROCESSOR_ARCHITECTURE_ARM
+HANDLE_MDMP_ARCH(0x0006, IA64)     // PROCESSOR_ARCHITECTURE_IA64
+HANDLE_MDMP_ARCH(0x0007, Alpha64)  // PROCESSOR_ARCHITECTURE_ALPHA64
+HANDLE_MDMP_ARCH(0x0008, MSIL)     // PROCESSOR_ARCHITECTURE_MSIL
+HANDLE_MDMP_ARCH(0x0009, AMD64)    // PROCESSOR_ARCHITECTURE_AMD64
+HANDLE_MDMP_ARCH(0x000a, X86Win64) // PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
+HANDLE_MDMP_ARCH(0x8001, SPARC)    // Breakpad-defined value for SPARC
+HANDLE_MDMP_ARCH(0x8002, PPC64)    // Breakpad-defined value for PPC64
+HANDLE_MDMP_ARCH(0x8003, ARM64)    // Breakpad-defined value for ARM64
+HANDLE_MDMP_ARCH(0x8004, MIPS64)   // Breakpad-defined value for MIPS64
+
+HANDLE_MDMP_PLATFORM(0x0000, Win32S) // Windows 3.1
+HANDLE_MDMP_PLATFORM(0x0001, Win32Windows) // Windows 95-98-Me
+HANDLE_MDMP_PLATFORM(0x0002, Win32NT) // Windows NT, 2000+
+HANDLE_MDMP_PLATFORM(0x0003, Win32CE) // Windows CE, Windows Mobile, "Handheld"
+// Breakpad-defined values.
+HANDLE_MDMP_PLATFORM(0x8000, Unix) // Generic Unix-ish
+HANDLE_MDMP_PLATFORM(0x8101, MacOSX) // Mac OS X/Darwin
+HANDLE_MDMP_PLATFORM(0x8102, IOS) // iOS
+HANDLE_MDMP_PLATFORM(0x8201, Linux) // Linux
+HANDLE_MDMP_PLATFORM(0x8202, Solaris) // Solaris
+HANDLE_MDMP_PLATFORM(0x8203, Android) // Android
+HANDLE_MDMP_PLATFORM(0x8204, PS3) // PS3
+HANDLE_MDMP_PLATFORM(0x8205, NaCl) // Native Client (NaCl)
+
+#undef HANDLE_MDMP_STREAM_TYPE
+#undef HANDLE_MDMP_ARCH
+#undef HANDLE_MDMP_PLATFORM
Index: include/llvm/BinaryFormat/Minidump.h
===================================================================
--- /dev/null
+++ include/llvm/BinaryFormat/Minidump.h
@@ -0,0 +1,112 @@
+//===- Minidump.h - Minidumg constants and structures -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header constants and data structures pertaining to the Windows Minidump
+// core file format.
+//
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx
+// https://chromium.googlesource.com/breakpad/breakpad/
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_MINIDUMP_H
+#define LLVM_BINARYFORMAT_MINIDUMP_H
+
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace minidump {
+
+struct Header {
+  static constexpr uint32_t MagicSignature = 0x504d444d; // PMDM
+  static constexpr uint16_t MagicVersion = 0xa793;
+
+  support::ulittle32_t Signature;
+  // The high 16 bits of version field are implementation specific. The low 16
+  // bits should be MagicVersion.
+  support::ulittle32_t Version;
+  support::ulittle32_t NumberOfStreams;
+  support::ulittle32_t StreamDirectoryRVA;
+  support::ulittle32_t Checksum;
+  support::ulittle32_t TimeDateStamp;
+  support::ulittle64_t Flags;
+};
+static_assert(sizeof(Header) == 32, "");
+
+enum class StreamType : uint32_t {
+#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  Unused = 0,
+  LastReserved = 0x0000ffff,
+};
+
+struct LocationDescriptor {
+  support::ulittle32_t DataSize;
+  support::ulittle32_t RVA;
+};
+static_assert(sizeof(LocationDescriptor) == 8, "");
+
+struct Directory {
+  support::little_t<StreamType> Type;
+  LocationDescriptor Location;
+};
+static_assert(sizeof(Directory) == 12, "");
+
+enum class ProcessorArchitecture : uint16_t {
+#define HANDLE_MDMP_ARCH(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+enum class OSPlatform : uint32_t {
+#define HANDLE_MDMP_PLATFORM(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+union CPUInfo {
+  struct X86Info {
+    char VendorID[12];                        // cpuid 0: ebx, edx, ecx
+    support::ulittle32_t VersionInfo;         // cpuid 1: eax
+    support::ulittle32_t FeatureInfo;         // cpuid 1: edx
+    support::ulittle32_t AMDExtendedFeatures; // cpuid 0x80000001, ebx
+  } X86;
+  struct ArmInfo {
+    support::ulittle32_t CPUID;
+    support::ulittle32_t ElfHWCaps; // linux specific, 0 otherwise
+  } Arm;
+  struct OtherInfo {
+    uint8_t ProcessorFeatures[16];
+  } Other;
+};
+static_assert(sizeof(CPUInfo) == 24, "");
+
+struct SystemInfo {
+  support::little_t<ProcessorArchitecture> ProcessorArch;
+  support::ulittle16_t ProcessorLevel;
+  support::ulittle16_t ProcessorRevision;
+
+  uint8_t NumberOfProcessors;
+  uint8_t ProductType;
+
+  support::ulittle32_t MajorVersion;
+  support::ulittle32_t MinorVersion;
+  support::ulittle32_t BuildNumber;
+  support::little_t<OSPlatform> PlatformId;
+  support::ulittle32_t CSDVersionRVA;
+
+  support::ulittle16_t SuiteMask;
+  support::ulittle16_t Reserved;
+
+  CPUInfo CPU;
+};
+static_assert(sizeof(SystemInfo) == 56, "");
+
+} // namespace minidump
+} // namespace llvm
+
+#endif // LLVM_BINARYFORMAT_MINIDUMP_H
Index: include/llvm/BinaryFormat/Magic.h
===================================================================
--- include/llvm/BinaryFormat/Magic.h
+++ include/llvm/BinaryFormat/Magic.h
@@ -39,6 +39,7 @@
     macho_dsym_companion,                     ///< Mach-O dSYM companion file
     macho_kext_bundle,                        ///< Mach-O kext bundle file
     macho_universal_binary,                   ///< Mach-O universal binary
+    minidump,                                 ///< Windows minidump file
     coff_cl_gl_object,   ///< Microsoft cl.exe's intermediate code file
     coff_object,         ///< COFF object file
     coff_import_library, ///< COFF import library
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to