[llvm] r356652 - [Object] Add basic minidump support

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 21 02:18:59 PDT 2019


Author: labath
Date: Thu Mar 21 02:18:59 2019
New Revision: 356652

URL: http://llvm.org/viewvc/llvm-project?rev=356652&view=rev
Log:
[Object] Add basic minidump support

Summary:
This patch adds basic support for reading minidump files. It contains
the definitions of various important minidump data structures (header,
stream directory), and of one minidump stream (SystemInfo). The ability
to read other streams will be added in follow-up patches. However, all
streams can be read even now as raw data, which means lldb's minidump
support (where this code is taken from) can be immediately rebased on
top of this patch as soon as it lands.

As we don't have any support for generating minidump files (yet), this
tests the code via unit tests with some small handcrafted binaries in
the form of c char arrays.

Reviewers: Bigcheese, jhenderson, zturner

Subscribers: srhines, dschuff, mgorny, fedor.sergeev, lemo, clayborg, JDevlieghere, aprantl, lldb-commits, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59291

Added:
    llvm/trunk/include/llvm/BinaryFormat/Minidump.h
    llvm/trunk/include/llvm/BinaryFormat/MinidumpConstants.def
    llvm/trunk/include/llvm/Object/Minidump.h
    llvm/trunk/lib/BinaryFormat/Minidump.cpp
    llvm/trunk/lib/Object/Minidump.cpp
    llvm/trunk/unittests/Object/MinidumpTest.cpp
Modified:
    llvm/trunk/include/llvm/BinaryFormat/Magic.h
    llvm/trunk/include/llvm/Object/Binary.h
    llvm/trunk/lib/BinaryFormat/CMakeLists.txt
    llvm/trunk/lib/BinaryFormat/Magic.cpp
    llvm/trunk/lib/Object/Binary.cpp
    llvm/trunk/lib/Object/CMakeLists.txt
    llvm/trunk/lib/Object/ObjectFile.cpp
    llvm/trunk/lib/Object/SymbolicFile.cpp
    llvm/trunk/unittests/Object/CMakeLists.txt

Modified: llvm/trunk/include/llvm/BinaryFormat/Magic.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Magic.h?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Magic.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Magic.h Thu Mar 21 02:18:59 2019
@@ -39,6 +39,7 @@ struct file_magic {
     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

Added: llvm/trunk/include/llvm/BinaryFormat/Minidump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Minidump.h?rev=356652&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Minidump.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/Minidump.h Thu Mar 21 02:18:59 2019
@@ -0,0 +1,147 @@
+//===- Minidump.h - Minidump 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/ADT/DenseMapInfo.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace minidump {
+
+/// The minidump header is the first part of a minidump file. It identifies the
+/// file as a minidump file, and gives the location of the stream directory.
+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, "");
+
+/// The type of a minidump stream identifies its contents. Streams numbers after
+/// LastReserved are for application-defined data streams.
+enum class StreamType : uint32_t {
+#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  Unused = 0,
+  LastReserved = 0x0000ffff,
+};
+
+/// Specifies the location (and size) of various objects in the minidump file.
+/// The location is relative to the start of the file.
+struct LocationDescriptor {
+  support::ulittle32_t DataSize;
+  support::ulittle32_t RVA;
+};
+static_assert(sizeof(LocationDescriptor) == 8, "");
+
+/// Specifies the location and type of a single stream in the minidump file. The
+/// minidump stream directory is an array of entries of this type, with its size
+/// given by Header.NumberOfStreams.
+struct Directory {
+  support::little_t<StreamType> Type;
+  LocationDescriptor Location;
+};
+static_assert(sizeof(Directory) == 12, "");
+
+/// The processor architecture of the system that generated this minidump. Used
+/// in the ProcessorArch field of the SystemInfo stream.
+enum class ProcessorArchitecture : uint16_t {
+#define HANDLE_MDMP_ARCH(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+/// The OS Platform of the system that generated this minidump. Used in the
+/// PlatformId field of the SystemInfo stream.
+enum class OSPlatform : uint32_t {
+#define HANDLE_MDMP_PLATFORM(CODE, NAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+/// Detailed information about the processor of the system that generated this
+/// minidump. Its interpretation depends on the ProcessorArchitecture enum.
+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, "");
+
+/// The SystemInfo stream, containing various information about the system where
+/// this minidump was generated.
+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
+
+template <> struct DenseMapInfo<minidump::StreamType> {
+  static minidump::StreamType getEmptyKey() { return minidump::StreamType(-1); }
+
+  static minidump::StreamType getTombstoneKey() {
+    return minidump::StreamType(-2);
+  }
+
+  static unsigned getHashValue(minidump::StreamType Val) {
+    return DenseMapInfo<uint32_t>::getHashValue(static_cast<uint32_t>(Val));
+  }
+
+  static bool isEqual(minidump::StreamType LHS, minidump::StreamType RHS) {
+    return LHS == RHS;
+  }
+};
+
+} // namespace llvm
+
+#endif // LLVM_BINARYFORMAT_MINIDUMP_H

Added: llvm/trunk/include/llvm/BinaryFormat/MinidumpConstants.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MinidumpConstants.def?rev=356652&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MinidumpConstants.def (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MinidumpConstants.def Thu Mar 21 02:18:59 2019
@@ -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) // Win32 on 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

Modified: llvm/trunk/include/llvm/Object/Binary.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Binary.h (original)
+++ llvm/trunk/include/llvm/Object/Binary.h Thu Mar 21 02:18:59 2019
@@ -41,7 +41,9 @@ protected:
     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 @@ public:
     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);

Added: llvm/trunk/include/llvm/Object/Minidump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Minidump.h?rev=356652&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Object/Minidump.h (added)
+++ llvm/trunk/include/llvm/Object/Minidump.h Thu Mar 21 02:18:59 2019
@@ -0,0 +1,121 @@
+//===- 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/DenseMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Minidump.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace object {
+
+/// A class providing access to the contents of a minidump file.
+class MinidumpFile : public Binary {
+public:
+  /// Construct a new MinidumpFile object from the given memory buffer. Returns
+  /// an error if this file cannot be identified as a minidump file, or if its
+  /// contents are badly corrupted (i.e. we cannot read the stream directory).
+  static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source);
+
+  static bool classof(const Binary *B) { return B->isMinidump(); }
+
+  /// Returns the contents of the minidump header.
+  const minidump::Header &header() const { return Header; }
+
+  /// Returns the list of streams (stream directory entries) in this file.
+  ArrayRef<minidump::Directory> streams() const { return Streams; }
+
+  /// Returns the raw contents of the stream given by the directory entry.
+  ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const {
+    return getData().slice(Stream.Location.RVA, Stream.Location.DataSize);
+  }
+
+  /// Returns the raw contents of the stream of the given type, or None if the
+  /// file does not contain a stream of this type.
+  Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const;
+
+  /// Returns the contents of the SystemInfo stream, cast to the appropriate
+  /// type. An error is returned if the file does not contain this stream, or
+  /// the stream is smaller than the size of the SystemInfo structure. The
+  /// internal consistency of the stream is not checked in any way.
+  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);
+  }
+
+  /// Return a slice of the given data array, with bounds checking.
+  static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data,
+                                                  size_t Offset, size_t Size);
+
+  /// Return the slice of the given data array as an array of objects of the
+  /// given type. The function checks that the input array is large enough to
+  /// contain the correct number of objects of the given type.
+  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,
+               DenseMap<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());
+  }
+
+  /// Return the stream of the given type, cast to the appropriate type. Checks
+  /// that the stream is large enough to hold an object of this type.
+  template <typename T>
+  Expected<const T &> getStream(minidump::StreamType Stream) const;
+
+  const minidump::Header &Header;
+  ArrayRef<minidump::Directory> Streams;
+  DenseMap<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

Modified: llvm/trunk/lib/BinaryFormat/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/CMakeLists.txt?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/CMakeLists.txt (original)
+++ llvm/trunk/lib/BinaryFormat/CMakeLists.txt Thu Mar 21 02:18:59 2019
@@ -2,6 +2,7 @@ add_llvm_library(LLVMBinaryFormat
   AMDGPUMetadataVerifier.cpp
   Dwarf.cpp
   Magic.cpp
+  Minidump.cpp
   MsgPackDocument.cpp
   MsgPackDocumentYAML.cpp
   MsgPackReader.cpp

Modified: llvm/trunk/lib/BinaryFormat/Magic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Magic.cpp?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Magic.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Magic.cpp Thu Mar 21 02:18:59 2019
@@ -181,7 +181,8 @@ file_magic llvm::identify_magic(StringRe
       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 @@ file_magic llvm::identify_magic(StringRe
     }
     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.

Added: llvm/trunk/lib/BinaryFormat/Minidump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Minidump.cpp?rev=356652&view=auto
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Minidump.cpp (added)
+++ llvm/trunk/lib/BinaryFormat/Minidump.cpp Thu Mar 21 02:18:59 2019
@@ -0,0 +1,14 @@
+//===-- Minidump.cpp - Minidump 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/Minidump.h"
+
+using namespace llvm::minidump;
+
+constexpr uint32_t Header::MagicSignature;
+constexpr uint16_t Header::MagicVersion;

Modified: llvm/trunk/lib/Object/Binary.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Binary.cpp?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Binary.cpp (original)
+++ llvm/trunk/lib/Object/Binary.cpp Thu Mar 21 02:18:59 2019
@@ -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 @@ Expected<std::unique_ptr<Binary>> object
   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");
 }

Modified: llvm/trunk/lib/Object/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/CMakeLists.txt?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/Object/CMakeLists.txt (original)
+++ llvm/trunk/lib/Object/CMakeLists.txt Thu Mar 21 02:18:59 2019
@@ -13,6 +13,7 @@ add_llvm_library(LLVMObject
   IRSymtab.cpp
   MachOObjectFile.cpp
   MachOUniversal.cpp
+  Minidump.cpp
   ModuleSymbolTable.cpp
   Object.cpp
   ObjectFile.cpp

Added: llvm/trunk/lib/Object/Minidump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Minidump.cpp?rev=356652&view=auto
==============================================================================
--- llvm/trunk/lib/Object/Minidump.cpp (added)
+++ llvm/trunk/lib/Object/Minidump.cpp Thu Mar 21 02:18:59 2019
@@ -0,0 +1,77 @@
+//===- 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.Version & 0xffff) != Header::MagicVersion)
+    return createError("Invalid version");
+
+  auto ExpectedStreams = getDataSliceAs<Directory>(Data, Hdr.StreamDirectoryRVA,
+                                                   Hdr.NumberOfStreams);
+  if (!ExpectedStreams)
+    return ExpectedStreams.takeError();
+
+  DenseMap<StreamType, std::size_t> StreamMap;
+  for (const auto &Stream : llvm::enumerate(*ExpectedStreams)) {
+    StreamType Type = Stream.value().Type;
+    const LocationDescriptor &Loc = Stream.value().Location;
+
+    auto ExpectedStream = getDataSlice(Data, Loc.RVA, Loc.DataSize);
+    if (!ExpectedStream)
+      return ExpectedStream.takeError();
+
+    if (Type == StreamType::Unused && Loc.DataSize == 0) {
+      // Ignore dummy streams. This is technically ill-formed, but a number of
+      // existing minidumps seem to contain such streams.
+      continue;
+    }
+
+    if (Type == DenseMapInfo<StreamType>::getEmptyKey() ||
+        Type == DenseMapInfo<StreamType>::getTombstoneKey())
+      return createError("Cannot handle one of the minidump streams");
+
+    // Update the directory map, checking for duplicate stream types.
+    if (!StreamMap.try_emplace(Type, Stream.index()).second)
+      return createError("Duplicate stream type");
+  }
+
+  return std::unique_ptr<MinidumpFile>(
+      new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap)));
+}

Modified: llvm/trunk/lib/Object/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ObjectFile.cpp?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/ObjectFile.cpp Thu Mar 21 02:18:59 2019
@@ -127,6 +127,7 @@ ObjectFile::createObjectFile(MemoryBuffe
   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:

Modified: llvm/trunk/lib/Object/SymbolicFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/SymbolicFile.cpp?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/lib/Object/SymbolicFile.cpp (original)
+++ llvm/trunk/lib/Object/SymbolicFile.cpp Thu Mar 21 02:18:59 2019
@@ -52,6 +52,7 @@ SymbolicFile::createSymbolicFile(MemoryB
   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:

Modified: llvm/trunk/unittests/Object/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Object/CMakeLists.txt?rev=356652&r1=356651&r2=356652&view=diff
==============================================================================
--- llvm/trunk/unittests/Object/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Object/CMakeLists.txt Thu Mar 21 02:18:59 2019
@@ -3,7 +3,9 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_llvm_unittest(ObjectTests
+  MinidumpTest.cpp
   SymbolSizeTest.cpp
   SymbolicFileTest.cpp
   )
 
+target_link_libraries(ObjectTests PRIVATE LLVMTestingSupport)

Added: llvm/trunk/unittests/Object/MinidumpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Object/MinidumpTest.cpp?rev=356652&view=auto
==============================================================================
--- llvm/trunk/unittests/Object/MinidumpTest.cpp (added)
+++ llvm/trunk/unittests/Object/MinidumpTest.cpp Thu Mar 21 02:18:59 2019
@@ -0,0 +1,256 @@
+//===- MinidumpTest.cpp - Tests for Minidump.cpp --------------------------===//
+//
+// 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/Support/MemoryBuffer.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace minidump;
+
+static Expected<std::unique_ptr<MinidumpFile>> create(ArrayRef<uint8_t> Data) {
+  return MinidumpFile::create(
+      MemoryBufferRef(toStringRef(Data), "Test buffer"));
+}
+
+TEST(MinidumpFile, BasicInterface) {
+  // A very simple minidump file which contains just a single stream.
+  auto ExpectedFile =
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'});
+  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+  const MinidumpFile &File = **ExpectedFile;
+  const Header &H = File.header();
+  EXPECT_EQ(Header::MagicSignature, H.Signature);
+  EXPECT_EQ(Header::MagicVersion, H.Version);
+  EXPECT_EQ(1u, H.NumberOfStreams);
+  EXPECT_EQ(0x20u, H.StreamDirectoryRVA);
+  EXPECT_EQ(0x03020100u, H.Checksum);
+  EXPECT_EQ(0x07060504u, H.TimeDateStamp);
+  EXPECT_EQ(uint64_t(0x0504030201000908), H.Flags);
+
+  ASSERT_EQ(1u, File.streams().size());
+  const Directory &Stream0 = File.streams()[0];
+  EXPECT_EQ(StreamType::LinuxCPUInfo, Stream0.Type);
+  EXPECT_EQ(7u, Stream0.Location.DataSize);
+  EXPECT_EQ(0x2cu, Stream0.Location.RVA);
+
+  EXPECT_EQ("CPUINFO", toStringRef(File.getRawStream(Stream0)));
+  EXPECT_EQ("CPUINFO",
+            toStringRef(*File.getRawStream(StreamType::LinuxCPUInfo)));
+
+  EXPECT_THAT_EXPECTED(File.getSystemInfo(), Failed<BinaryError>());
+}
+
+// Use the input from the previous test, but corrupt it in various ways
+TEST(MinidumpFile, create_ErrorCases) {
+  // File too short
+  EXPECT_THAT_EXPECTED(create({'M', 'D', 'M', 'P'}), Failed<BinaryError>());
+
+  // Wrong Signature
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              '!', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Wrong Version
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x39, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Stream directory after EOF
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 1, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Truncated stream directory
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 1, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Stream0 after EOF
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x2c, 1, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Truncated Stream0
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 8, 0, 0, 0,         // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Duplicate Stream
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              2, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x40, 0, 0, 0,                        // RVA
+                                                    // Stream
+              3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
+              0x40, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+
+  // Stream matching one of the DenseMapInfo magic values
+  EXPECT_THAT_EXPECTED(
+      create({                                      // Header
+              'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+              1, 0, 0, 0,                           // NumberOfStreams,
+              0x20, 0, 0, 0,                        // StreamDirectoryRVA
+              0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+              8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                                    // Stream Directory
+              0xff, 0xff, 0xff, 0xff, 7, 0, 0, 0,   // Type, DataSize,
+              0x2c, 0, 0, 0,                        // RVA
+                                                    // Stream
+              'C', 'P', 'U', 'I', 'N', 'F', 'O'}),
+      Failed<BinaryError>());
+}
+
+TEST(MinidumpFile, IngoresDummyStreams) {
+  auto ExpectedFile = create({
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      2, 0, 0, 0,                           // NumberOfStreams,
+      0x20, 0, 0, 0,                        // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                            // Stream Directory
+      0, 0, 0, 0, 0, 0, 0, 0,               // Type, DataSize,
+      0x20, 0, 0, 0,                        // RVA
+      0, 0, 0, 0, 0, 0, 0, 0,               // Type, DataSize,
+      0x20, 0, 0, 0,                        // RVA
+  });
+  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+  const MinidumpFile &File = **ExpectedFile;
+  ASSERT_EQ(2u, File.streams().size());
+  EXPECT_EQ(StreamType::Unused, File.streams()[0].Type);
+  EXPECT_EQ(StreamType::Unused, File.streams()[1].Type);
+  EXPECT_EQ(None, File.getRawStream(StreamType::Unused));
+}
+
+TEST(MinidumpFile, getSystemInfo) {
+  auto ExpectedFile = create({
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      0x20, 0, 0, 0,                        // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      8, 9, 0, 1, 2, 3, 4, 5,               // Flags
+                                            // Stream Directory
+      7, 0, 0, 0, 56, 0, 0, 0,              // Type, DataSize,
+      0x2c, 0, 0, 0,                        // RVA
+                                            // SystemInfo
+      0, 0, 1, 2,                           // ProcessorArch, ProcessorLevel
+      3, 4, 5, 6, // ProcessorRevision, NumberOfProcessors, ProductType
+      7, 8, 9, 0, 1, 2, 3, 4, // MajorVersion, MinorVersion
+      5, 6, 7, 8, 2, 0, 0, 0, // BuildNumber, PlatformId
+      1, 2, 3, 4, 5, 6, 7, 8, // CSDVersionRVA, SuiteMask, Reserved
+      'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', // VendorID
+      1, 2, 3, 4, 5, 6, 7, 8, // VersionInfo, FeatureInfo
+      9, 0, 1, 2,             // AMDExtendedFeatures
+  });
+  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+  const MinidumpFile &File = **ExpectedFile;
+
+  auto ExpectedInfo = File.getSystemInfo();
+  ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
+  const SystemInfo &Info = *ExpectedInfo;
+  EXPECT_EQ(ProcessorArchitecture::X86, Info.ProcessorArch);
+  EXPECT_EQ(0x0201, Info.ProcessorLevel);
+  EXPECT_EQ(0x0403, Info.ProcessorRevision);
+  EXPECT_EQ(5, Info.NumberOfProcessors);
+  EXPECT_EQ(6, Info.ProductType);
+  EXPECT_EQ(0x00090807u, Info.MajorVersion);
+  EXPECT_EQ(0x04030201u, Info.MinorVersion);
+  EXPECT_EQ(0x08070605u, Info.BuildNumber);
+  EXPECT_EQ(OSPlatform::Win32NT, Info.PlatformId);
+  EXPECT_EQ(0x04030201u, Info.CSDVersionRVA);
+  EXPECT_EQ(0x0605u, Info.SuiteMask);
+  EXPECT_EQ(0x0807u, Info.Reserved);
+  EXPECT_EQ("LLVMLLVMLLVM", llvm::StringRef(Info.CPU.X86.VendorID,
+                                            sizeof(Info.CPU.X86.VendorID)));
+  EXPECT_EQ(0x04030201u, Info.CPU.X86.VersionInfo);
+  EXPECT_EQ(0x08070605u, Info.CPU.X86.FeatureInfo);
+  EXPECT_EQ(0x02010009u, Info.CPU.X86.AMDExtendedFeatures);
+}




More information about the llvm-commits mailing list