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

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 21 03:05:43 PDT 2019


On 21/03/2019 10:57, Alex Bradbury wrote:
> This breaks a -DBUILD_SHARED_LIBS=True build:
> 
> [649/669] Linking CXX executable unittests/Object/ObjectTests
> FAILED: unittests/Object/ObjectTests
> : && /usr/bin/clang++  -fPIC -fvisibility-inlines-hidden
> -Werror=date-time -Werror=unguarded-availability-new -std=c++11 -Wall
> -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual
> -Wmissing-field-initializers -pedantic -Wno-long-long
> -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type
> -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wstring-conversion
> -fdiagnostics-color -g  -fuse-ld=lld -Wl,--color-diagnostics
> -Wl,-allow-shlib-undefined
> unittests/Object/CMakeFiles/ObjectTests.dir/MinidumpTest.cpp.o
> unittests/Object/CMakeFiles/ObjectTests.dir/SymbolSizeTest.cpp.o
> unittests/Object/CMakeFiles/ObjectTests.dir/SymbolicFileTest.cpp.o  -o
> unittests/Object/ObjectTests  -Wl,-rpath,/home/asb/llvm/build/lib
> lib/libLLVMObject.so.9svn lib/libLLVMSupport.so.9svn -lpthread
> lib/libgtest_main.so.9svn lib/libgtest.so.9svn -lpthread
> lib/libLLVMTestingSupport.so.9svn && :
> ld.lld: error: undefined symbol: llvm::minidump::Header::MagicSignature
>>>> referenced by MinidumpTest.cpp:39 (../unittests/Object/MinidumpTest.cpp:39)
>>>>                unittests/Object/CMakeFiles/ObjectTests.dir/MinidumpTest.cpp.o:(MinidumpFile_BasicInterface_Test::TestBody())
> 
> ld.lld: error: undefined symbol: llvm::minidump::Header::MagicVersion
>>>> referenced by MinidumpTest.cpp:40 (../unittests/Object/MinidumpTest.cpp:40)
>>>>                unittests/Object/CMakeFiles/ObjectTests.dir/MinidumpTest.cpp.o:(MinidumpFile_BasicInterface_Test::TestBody())
> clang-7: error: linker command failed with exit code 1 (use -v to see
> invocation)
> 
> On Thu, 21 Mar 2019 at 10:17, Pavel Labath via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>>
>> 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);
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits

Thanks for the heads-up. Should have that fixed soon.


More information about the llvm-commits mailing list