[llvm] r356753 - [ObjectYAML] Add basic minidump generation support

Kristina Brooks via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 10 20:38:29 PDT 2019


Hi,

This doesn't build with modules enabled (using Clang r374503):

FAILED: lib/ObjectYAML/CMakeFiles/LLVMObjectYAML.dir/MinidumpYAML.cpp.o
/o/b/llvm-10/408/bin/clang++  -DGTEST_HAS_RTTI=0 -D_DEBUG
-D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS
-D__STDC_LIMIT_MACROS -Ilib/ObjectYAML
-I/home/src2/llvm-tainted/lib/ObjectYAML -Iinclude
-I/home/src2/llvm-tainted/include -O3 -march=native
-Wno-unused-command-line-argument  -gline-tables-only -stdlib=libc++
-fPIC -fvisibility-inlines-hidden -Werror=date-time
-Werror=unguarded-availability-new -std=c++14 -fmodules
-fmodules-cache-path=/o/b/llvm-10/409/module.cache -Xclang
-fmodules-local-submodule-visibility -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 -ffunction-sections -fdata-sections -flto=thin -O3
   -UNDEBUG  -fno-exceptions -fno-rtti -MD -MT
lib/ObjectYAML/CMakeFiles/LLVMObjectYAML.dir/MinidumpYAML.cpp.o -MF
lib/ObjectYAML/CMakeFiles/LLVMObjectYAML.dir/MinidumpYAML.cpp.o.d -o
lib/ObjectYAML/CMakeFiles/LLVMObjectYAML.dir/MinidumpYAML.cpp.o -c
/home/src2/llvm-tainted/lib/ObjectYAML/MinidumpYAML.cpp
In module 'LLVM_Utils' imported from
/home/src2/llvm-tainted/include/llvm/ObjectYAML/YAML.h:12:
/home/src2/llvm-tainted/include/llvm/Support/YAMLTraits.h:819:48:
error: call to function 'operator&' that is neither visible in the
template definition nor found by argument-dependent lookup
    if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
                                               ^
/home/src2/llvm-tainted/include/llvm/BinaryFormat/MinidumpConstants.def:118:1:
note: in instantiation of function template specialization
'llvm::yaml::IO::bitSetCase<llvm::minidump::MemoryProtection>'
requested here
HANDLE_MDMP_PROTECT(0x01, NoAccess, PAGE_NO_ACCESS)
^
/home/src2/llvm-tainted/lib/ObjectYAML/MinidumpYAML.cpp:119:6: note:
expanded from macro 'HANDLE_MDMP_PROTECT'
  IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);
     ^
/home/src2/llvm-tainted/include/llvm/ADT/BitmaskEnum.h:111:3: note:
'operator&' should be declared prior to the call site or in namespace
'llvm::minidump'
E operator&(E LHS, E RHS) {

On Fri, Mar 22, 2019 at 2:46 PM Pavel Labath via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: labath
> Date: Fri Mar 22 07:47:26 2019
> New Revision: 356753
>
> URL: http://llvm.org/viewvc/llvm-project?rev=356753&view=rev
> Log:
> [ObjectYAML] Add basic minidump generation support
>
> Summary:
> This patch adds the ability to read a yaml form of a minidump file and
> write it out as binary. Apart from the minidump header and the stream
> directory, only three basic stream kinds are supported:
> - Text: This kind is used for streams which contain textual data. This
>   is typically the contents of a /proc file on linux (e.g.
>   /proc/PID/maps). In this case, we just put the raw stream contents
>   into the yaml.
> - SystemInfo: This stream contains various bits of information about the
>   host system in binary form. We expose the data in a structured form.
> - Raw: This kind is used as a fallback when we don't have any special
>   knowledge about the stream. In this case, we just print the stream
>   contents in hex.
>
> For this code to be really useful, more stream kinds will need to be
> added (particularly for things like lists of memory regions and loaded
> modules). However, these can be added incrementally.
>
> Reviewers: jhenderson, zturner, clayborg, aprantl
>
> Subscribers: mgorny, lemo, llvm-commits, lldb-commits
>
> Tags: #llvm
>
> Differential Revision: https://reviews.llvm.org/D59482
>
> Added:
>     llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h
>     llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp
>     llvm/trunk/test/tools/yaml2obj/minidump-raw-stream-small-size.yaml
>     llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-long.yaml
>     llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-not-hex.yaml
>     llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-short.yaml
>     llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-long.yaml
>     llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-short.yaml
>     llvm/trunk/tools/yaml2obj/yaml2minidump.cpp
>     llvm/trunk/unittests/ObjectYAML/MinidumpYAMLTest.cpp
> Modified:
>     llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h
>     llvm/trunk/lib/ObjectYAML/CMakeLists.txt
>     llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp
>     llvm/trunk/tools/yaml2obj/CMakeLists.txt
>     llvm/trunk/tools/yaml2obj/yaml2obj.cpp
>     llvm/trunk/tools/yaml2obj/yaml2obj.h
>     llvm/trunk/unittests/ObjectYAML/CMakeLists.txt
>
> Added: llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h (added)
> +++ llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,156 @@
> +//===- 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/BinaryFormat/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 RawContentStream). The mapping
> +/// from Types to Kinds is fixed and given by the static getKind function.
> +struct Stream {
> +  enum class StreamKind {
> +    RawContent,
> +    SystemInfo,
> +    TextContent,
> +  };
> +
> +  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);
> +
> +  /// Create an empty stream of the given Type.
> +  static std::unique_ptr<Stream> create(minidump::StreamType Type);
> +};
> +
> +/// A minidump stream represented as a sequence of hex bytes. This is used as a
> +/// fallback when no other stream kind is suitable.
> +struct RawContentStream : public Stream {
> +  yaml::BinaryRef Content;
> +  yaml::Hex32 Size;
> +
> +  RawContentStream(minidump::StreamType Type, ArrayRef<uint8_t> Content = {})
> +      : Stream(StreamKind::RawContent, Type), Content(Content),
> +        Size(Content.size()) {}
> +
> +  static bool classof(const Stream *S) {
> +    return S->Kind == StreamKind::RawContent;
> +  }
> +};
> +
> +/// SystemInfo minidump stream.
> +struct SystemInfoStream : public Stream {
> +  minidump::SystemInfo Info;
> +
> +  explicit SystemInfoStream(const minidump::SystemInfo &Info)
> +      : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
> +        Info(Info) {}
> +
> +  SystemInfoStream()
> +      : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) {
> +    memset(&Info, 0, sizeof(Info));
> +  }
> +
> +  static bool classof(const Stream *S) {
> +    return S->Kind == StreamKind::SystemInfo;
> +  }
> +};
> +
> +/// 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 TextContentStream : public Stream {
> +  BlockStringRef Text;
> +
> +  TextContentStream(minidump::StreamType Type, StringRef Text = {})
> +      : Stream(StreamKind::TextContent, Type), Text(Text) {}
> +
> +  static bool classof(const Stream *S) {
> +    return S->Kind == StreamKind::TextContent;
> +  }
> +};
> +
> +/// 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.
> +struct Object {
> +  Object() = default;
> +  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;
> +};
> +
> +/// Serialize the minidump file represented by Obj to OS in binary form.
> +void writeAsBinary(Object &Obj, raw_ostream &OS);
> +
> +/// Serialize the yaml string as a minidump file to OS in binary form.
> +Error writeAsBinary(StringRef Yaml, raw_ostream &OS);
> +
> +} // 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 "";
> +  }
> +};
> +
> +template <> struct MappingTraits<std::unique_ptr<MinidumpYAML::Stream>> {
> +  static void mapping(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
> +  static StringRef validate(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
> +};
> +
> +} // 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_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
> +
> +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
> +
> +#endif // LLVM_OBJECTYAML_MINIDUMPYAML_H
>
> Modified: llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h (original)
> +++ llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h Fri Mar 22 07:47:26 2019
> @@ -12,6 +12,7 @@
>  #include "llvm/ObjectYAML/COFFYAML.h"
>  #include "llvm/ObjectYAML/ELFYAML.h"
>  #include "llvm/ObjectYAML/MachOYAML.h"
> +#include "llvm/ObjectYAML/MinidumpYAML.h"
>  #include "llvm/ObjectYAML/WasmYAML.h"
>  #include "llvm/Support/YAMLTraits.h"
>  #include <memory>
> @@ -26,6 +27,7 @@ struct YamlObjectFile {
>    std::unique_ptr<COFFYAML::Object> Coff;
>    std::unique_ptr<MachOYAML::Object> MachO;
>    std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
> +  std::unique_ptr<MinidumpYAML::Object> Minidump;
>    std::unique_ptr<WasmYAML::Object> Wasm;
>  };
>
>
> Modified: llvm/trunk/lib/ObjectYAML/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CMakeLists.txt?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ObjectYAML/CMakeLists.txt (original)
> +++ llvm/trunk/lib/ObjectYAML/CMakeLists.txt Fri Mar 22 07:47:26 2019
> @@ -10,6 +10,7 @@ add_llvm_library(LLVMObjectYAML
>    ELFYAML.cpp
>    MachOYAML.cpp
>    ObjectYAML.cpp
> +  MinidumpYAML.cpp
>    WasmYAML.cpp
>    YAML.cpp
>    )
>
> Added: llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp (added)
> +++ llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,385 @@
> +//===- 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;
> +
> +namespace {
> +class BlobAllocator {
> +public:
> +  size_t tell() const { return NextOffset; }
> +
> +  size_t AllocateCallback(size_t Size,
> +                          std::function<void(raw_ostream &)> Callback) {
> +    size_t Offset = NextOffset;
> +    NextOffset += Size;
> +    Callbacks.push_back(std::move(Callback));
> +    return Offset;
> +  }
> +
> +  size_t AllocateBytes(ArrayRef<uint8_t> Data) {
> +    return AllocateCallback(
> +        Data.size(), [Data](raw_ostream &OS) { OS << toStringRef(Data); });
> +  }
> +
> +  template <typename T> size_t AllocateArray(ArrayRef<T> Data) {
> +    return AllocateBytes({reinterpret_cast<const uint8_t *>(Data.data()),
> +                          sizeof(T) * Data.size()});
> +  }
> +
> +  template <typename T> size_t AllocateObject(const T &Data) {
> +    return AllocateArray(makeArrayRef(Data));
> +  }
> +
> +  void writeTo(raw_ostream &OS) const;
> +
> +private:
> +  size_t NextOffset = 0;
> +
> +  std::vector<std::function<void(raw_ostream &)>> Callbacks;
> +};
> +} // namespace
> +
> +void BlobAllocator::writeTo(raw_ostream &OS) const {
> +  size_t BeginOffset = OS.tell();
> +  for (const auto &Callback : Callbacks)
> +    Callback(OS);
> +  assert(OS.tell() == BeginOffset + NextOffset &&
> +         "Callbacks wrote an unexpected number of bytes.");
> +  (void)BeginOffset;
> +}
> +
> +/// 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 mapRequiredAs(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 mapRequiredHex(yaml::IO &IO, const char *Key,
> +                                  EndianType &Val) {
> +  mapRequiredAs<typename HexType<EndianType>::type>(IO, Key, Val);
> +}
> +
> +/// Perform an optional 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::SystemInfo:
> +    return StreamKind::SystemInfo;
> +  case StreamType::LinuxCPUInfo:
> +  case StreamType::LinuxProcStatus:
> +  case StreamType::LinuxLSBRelease:
> +  case StreamType::LinuxCMDLine:
> +  case StreamType::LinuxMaps:
> +  case StreamType::LinuxProcStat:
> +  case StreamType::LinuxProcUptime:
> +    return StreamKind::TextContent;
> +  default:
> +    return StreamKind::RawContent;
> +  }
> +}
> +
> +std::unique_ptr<Stream> Stream::create(StreamType Type) {
> +  StreamKind Kind = getKind(Type);
> +  switch (Kind) {
> +  case StreamKind::RawContent:
> +    return llvm::make_unique<RawContentStream>(Type);
> +  case StreamKind::SystemInfo:
> +    return llvm::make_unique<SystemInfoStream>();
> +  case StreamKind::TextContent:
> +    return llvm::make_unique<TextContentStream>(Type);
> +  }
> +  llvm_unreachable("Unhandled stream kind!");
> +}
> +
> +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) {
> +  mapRequiredHex(IO, "CPUID", Info.CPUID);
> +  mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0);
> +}
> +
> +namespace {
> +template <std::size_t N> struct FixedSizeHex {
> +  FixedSizeHex(uint8_t (&Storage)[N]) : Storage(Storage) {}
> +
> +  uint8_t (&Storage)[N];
> +};
> +} // namespace
> +
> +namespace llvm {
> +namespace yaml {
> +template <std::size_t N> struct ScalarTraits<FixedSizeHex<N>> {
> +  static void output(const FixedSizeHex<N> &Fixed, void *, raw_ostream &OS) {
> +    OS << toHex(makeArrayRef(Fixed.Storage));
> +  }
> +
> +  static StringRef input(StringRef Scalar, void *, FixedSizeHex<N> &Fixed) {
> +    if (!all_of(Scalar, isHexDigit))
> +      return "Invalid hex digit in input";
> +    if (Scalar.size() < 2 * N)
> +      return "String too short";
> +    if (Scalar.size() > 2 * N)
> +      return "String too long";
> +    copy(fromHex(Scalar), Fixed.Storage);
> +    return "";
> +  }
> +
> +  static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
> +};
> +} // namespace yaml
> +} // namespace llvm
> +void yaml::MappingTraits<CPUInfo::OtherInfo>::mapping(
> +    IO &IO, CPUInfo::OtherInfo &Info) {
> +  FixedSizeHex<sizeof(Info.ProcessorFeatures)> Features(Info.ProcessorFeatures);
> +  IO.mapRequired("Features", Features);
> +}
> +
> +namespace {
> +/// A type which only accepts strings of a fixed size for yaml conversion.
> +template <std::size_t N> struct FixedSizeString {
> +  FixedSizeString(char (&Storage)[N]) : Storage(Storage) {}
> +
> +  char (&Storage)[N];
> +};
> +} // namespace
> +
> +namespace llvm {
> +namespace yaml {
> +template <std::size_t N> struct ScalarTraits<FixedSizeString<N>> {
> +  static void output(const FixedSizeString<N> &Fixed, void *, raw_ostream &OS) {
> +    OS << StringRef(Fixed.Storage, N);
> +  }
> +
> +  static StringRef input(StringRef Scalar, void *, FixedSizeString<N> &Fixed) {
> +    if (Scalar.size() < N)
> +      return "String too short";
> +    if (Scalar.size() > N)
> +      return "String too long";
> +    copy(Scalar, Fixed.Storage);
> +    return "";
> +  }
> +
> +  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
> +};
> +} // namespace yaml
> +} // namespace llvm
> +
> +void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO,
> +                                                    CPUInfo::X86Info &Info) {
> +  FixedSizeString<sizeof(Info.VendorID)> VendorID(Info.VendorID);
> +  IO.mapRequired("Vendor ID", VendorID);
> +
> +  mapRequiredHex(IO, "Version Info", Info.VersionInfo);
> +  mapRequiredHex(IO, "Feature Info", Info.FeatureInfo);
> +  mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);
> +}
> +
> +static void streamMapping(yaml::IO &IO, RawContentStream &Stream) {
> +  IO.mapOptional("Content", Stream.Content);
> +  IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size());
> +}
> +
> +static StringRef streamValidate(RawContentStream &Stream) {
> +  if (Stream.Size.value < Stream.Content.binary_size())
> +    return "Stream size must be greater or equal to the content size";
> +  return "";
> +}
> +
> +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, TextContentStream &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::StreamKind::RawContent:
> +    streamMapping(IO, llvm::cast<RawContentStream>(*S));
> +    break;
> +  case MinidumpYAML::Stream::StreamKind::SystemInfo:
> +    streamMapping(IO, llvm::cast<SystemInfoStream>(*S));
> +    break;
> +  case MinidumpYAML::Stream::StreamKind::TextContent:
> +    streamMapping(IO, llvm::cast<TextContentStream>(*S));
> +    break;
> +  }
> +}
> +
> +StringRef yaml::MappingTraits<std::unique_ptr<Stream>>::validate(
> +    yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
> +  switch (S->Kind) {
> +  case MinidumpYAML::Stream::StreamKind::RawContent:
> +    return streamValidate(cast<RawContentStream>(*S));
> +  case MinidumpYAML::Stream::StreamKind::SystemInfo:
> +  case MinidumpYAML::Stream::StreamKind::TextContent:
> +    return "";
> +  }
> +  llvm_unreachable("Fully covered switch above!");
> +}
> +
> +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);
> +}
> +
> +static Directory layout(BlobAllocator &File, Stream &S) {
> +  Directory Result;
> +  Result.Type = S.Type;
> +  Result.Location.RVA = File.tell();
> +  switch (S.Kind) {
> +  case Stream::StreamKind::RawContent: {
> +    RawContentStream &Raw = cast<RawContentStream>(S);
> +    File.AllocateCallback(Raw.Size, [&Raw](raw_ostream &OS) {
> +      Raw.Content.writeAsBinary(OS);
> +      assert(Raw.Content.binary_size() <= Raw.Size);
> +      OS << std::string(Raw.Size - Raw.Content.binary_size(), '\0');
> +    });
> +    break;
> +  }
> +  case Stream::StreamKind::SystemInfo:
> +    File.AllocateObject(cast<SystemInfoStream>(S).Info);
> +    break;
> +  case Stream::StreamKind::TextContent:
> +    File.AllocateArray(arrayRefFromStringRef(cast<TextContentStream>(S).Text));
> +    break;
> +  }
> +  Result.Location.DataSize = File.tell() - Result.Location.RVA;
> +  return Result;
> +}
> +
> +void MinidumpYAML::writeAsBinary(Object &Obj, raw_ostream &OS) {
> +  BlobAllocator File;
> +  File.AllocateObject(Obj.Header);
> +
> +  std::vector<Directory> StreamDirectory(Obj.Streams.size());
> +  Obj.Header.StreamDirectoryRVA =
> +      File.AllocateArray(makeArrayRef(StreamDirectory));
> +  Obj.Header.NumberOfStreams = StreamDirectory.size();
> +
> +  for (auto &Stream : enumerate(Obj.Streams))
> +    StreamDirectory[Stream.index()] = layout(File, *Stream.value());
> +
> +  File.writeTo(OS);
> +}
> +
> +Error MinidumpYAML::writeAsBinary(StringRef Yaml, raw_ostream &OS) {
> +  yaml::Input Input(Yaml);
> +  Object Obj;
> +  Input >> Obj;
> +  if (std::error_code EC = Input.error())
> +    return errorCodeToError(EC);
> +
> +  writeAsBinary(Obj, OS);
> +  return Error::success();
> +}
>
> Modified: llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp (original)
> +++ llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp Fri Mar 22 07:47:26 2019
> @@ -45,6 +45,9 @@ void MappingTraits<YamlObjectFile>::mapp
>        ObjectFile.FatMachO.reset(new MachOYAML::UniversalBinary());
>        MappingTraits<MachOYAML::UniversalBinary>::mapping(IO,
>                                                           *ObjectFile.FatMachO);
> +    } else if (IO.mapTag("!minidump")) {
> +      ObjectFile.Minidump.reset(new MinidumpYAML::Object());
> +      MappingTraits<MinidumpYAML::Object>::mapping(IO, *ObjectFile.Minidump);
>      } else if (IO.mapTag("!WASM")) {
>        ObjectFile.Wasm.reset(new WasmYAML::Object());
>        MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm);
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-raw-stream-small-size.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-raw-stream-small-size.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-raw-stream-small-size.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-raw-stream-small-size.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,9 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            LinuxAuxv
> +    Size:            7
> +    Content:         DEADBEEFBAADF00D
> +
> +# CHECK: Stream size must be greater or equal to the content size
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-long.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-long.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-long.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-long.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,13 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  PPC
> +    Platform ID:     Linux
> +    CPU:
> +      Features:        000102030405060708090a0b0c0d0e0f0
> +
> +
> +# CHECK: String too long
> +# CHECK-NEXT: Features:        000102030405060708090a0b0c0d0e0f0
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-not-hex.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-not-hex.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-not-hex.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-not-hex.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,13 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  PPC
> +    Platform ID:     Linux
> +    CPU:
> +      Features:        000102030405060708090a0b0c0d0e0g
> +
> +
> +# CHECK: Invalid hex digit in input
> +# CHECK-NEXT: Features:        000102030405060708090a0b0c0d0e0g
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-short.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-short.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-short.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-other-short.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,13 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  PPC
> +    Platform ID:     Linux
> +    CPU:
> +      Features:        000102030405060708090a0b0c0d0e0
> +
> +
> +# CHECK: String too short
> +# CHECK-NEXT: Features:        000102030405060708090a0b0c0d0e0
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-long.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-long.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-long.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-long.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,15 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  X86
> +    Platform ID:     Linux
> +    CPU:
> +      Vendor ID:       LLVMLLVMLLVML
> +      Version Info:    0x01020304
> +      Feature Info:    0x05060708
> +      AMD Extended Features: 0x09000102
> +
> +# CHECK: String too long
> +# CHECK-NEXT: Vendor ID:       LLVMLLVMLLVML
>
> Added: llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-short.yaml
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-short.yaml?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-short.yaml (added)
> +++ llvm/trunk/test/tools/yaml2obj/minidump-systeminfo-x86-short.yaml Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,15 @@
> +# RUN: not yaml2obj %s 2>&1 | FileCheck %s
> +
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  X86
> +    Platform ID:     Linux
> +    CPU:
> +      Vendor ID:       LLVMLLVMLLV
> +      Version Info:    0x01020304
> +      Feature Info:    0x05060708
> +      AMD Extended Features: 0x09000102
> +
> +# CHECK: String too short
> +# CHECK-NEXT: Vendor ID:       LLVMLLVMLLV
>
> Modified: llvm/trunk/tools/yaml2obj/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/CMakeLists.txt?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/tools/yaml2obj/CMakeLists.txt (original)
> +++ llvm/trunk/tools/yaml2obj/CMakeLists.txt Fri Mar 22 07:47:26 2019
> @@ -11,5 +11,6 @@ add_llvm_tool(yaml2obj
>    yaml2coff.cpp
>    yaml2elf.cpp
>    yaml2macho.cpp
> +  yaml2minidump.cpp
>    yaml2wasm.cpp
>    )
>
> Added: llvm/trunk/tools/yaml2obj/yaml2minidump.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2minidump.cpp?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/tools/yaml2obj/yaml2minidump.cpp (added)
> +++ llvm/trunk/tools/yaml2obj/yaml2minidump.cpp Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,18 @@
> +//===- yaml2minidump.cpp - Convert a YAML file to a minidump file ---------===//
> +//
> +// 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 "yaml2obj.h"
> +#include "llvm/ObjectYAML/MinidumpYAML.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out) {
> +  writeAsBinary(Doc, Out);
> +  return 0;
> +}
>
> Modified: llvm/trunk/tools/yaml2obj/yaml2obj.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2obj.cpp?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/tools/yaml2obj/yaml2obj.cpp (original)
> +++ llvm/trunk/tools/yaml2obj/yaml2obj.cpp Fri Mar 22 07:47:26 2019
> @@ -56,6 +56,8 @@ static int convertYAML(yaml::Input &YIn,
>          return yaml2coff(*Doc.Coff, Out);
>        if (Doc.MachO || Doc.FatMachO)
>          return yaml2macho(Doc, Out);
> +      if (Doc.Minidump)
> +        return yaml2minidump(*Doc.Minidump, Out);
>        if (Doc.Wasm)
>          return yaml2wasm(*Doc.Wasm, Out);
>        error("yaml2obj: Unknown document type!");
>
> Modified: llvm/trunk/tools/yaml2obj/yaml2obj.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2obj.h?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/tools/yaml2obj/yaml2obj.h (original)
> +++ llvm/trunk/tools/yaml2obj/yaml2obj.h Fri Mar 22 07:47:26 2019
> @@ -22,6 +22,10 @@ namespace ELFYAML {
>  struct Object;
>  }
>
> +namespace MinidumpYAML {
> +struct Object;
> +}
> +
>  namespace WasmYAML {
>  struct Object;
>  }
> @@ -35,6 +39,7 @@ struct YamlObjectFile;
>  int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out);
>  int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out);
>  int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out);
> +int yaml2minidump(llvm::MinidumpYAML::Object &Doc, llvm::raw_ostream &Out);
>  int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out);
>
>  #endif
>
> Modified: llvm/trunk/unittests/ObjectYAML/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ObjectYAML/CMakeLists.txt?rev=356753&r1=356752&r2=356753&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ObjectYAML/CMakeLists.txt (original)
> +++ llvm/trunk/unittests/ObjectYAML/CMakeLists.txt Fri Mar 22 07:47:26 2019
> @@ -1,8 +1,11 @@
>  set(LLVM_LINK_COMPONENTS
> +  Object
>    ObjectYAML
>    )
>
>  add_llvm_unittest(ObjectYAMLTests
> +  MinidumpYAMLTest.cpp
>    YAMLTest.cpp
>    )
>
> +target_link_libraries(ObjectYAMLTests PRIVATE LLVMTestingSupport)
>
> Added: llvm/trunk/unittests/ObjectYAML/MinidumpYAMLTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ObjectYAML/MinidumpYAMLTest.cpp?rev=356753&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/ObjectYAML/MinidumpYAMLTest.cpp (added)
> +++ llvm/trunk/unittests/ObjectYAML/MinidumpYAMLTest.cpp Fri Mar 22 07:47:26 2019
> @@ -0,0 +1,141 @@
> +//===- MinidumpYAMLTest.cpp - Tests for Minidump<->YAML code --------------===//
> +//
> +// 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"
> +#include "llvm/Object/Minidump.h"
> +#include "llvm/ObjectYAML/ObjectYAML.h"
> +#include "llvm/Testing/Support/Error.h"
> +#include "gtest/gtest.h"
> +
> +using namespace llvm;
> +using namespace llvm::minidump;
> +
> +static Expected<std::unique_ptr<object::MinidumpFile>>
> +toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
> +  Storage.clear();
> +  raw_svector_ostream OS(Storage);
> +  if (Error E = MinidumpYAML::writeAsBinary(Yaml, OS))
> +    return std::move(E);
> +
> +  return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary"));
> +}
> +
> +TEST(MinidumpYAML, Basic) {
> +  SmallString<0> Storage;
> +  auto ExpectedFile = toBinary(Storage, R"(
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  ARM64
> +    Platform ID:     Linux
> +    CSD Version RVA: 0x01020304
> +    CPU:
> +      CPUID:           0x05060708
> +  - Type:            LinuxMaps
> +    Text:             |
> +      400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process
> +      400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process
> +
> +  - Type:            LinuxAuxv
> +    Content:         DEADBEEFBAADF00D)");
> +  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
> +  object::MinidumpFile &File = **ExpectedFile;
> +
> +  ASSERT_EQ(3u, File.streams().size());
> +
> +  EXPECT_EQ(StreamType::SystemInfo, File.streams()[0].Type);
> +  auto ExpectedSysInfo = File.getSystemInfo();
> +  ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
> +  const SystemInfo &SysInfo = *ExpectedSysInfo;
> +  EXPECT_EQ(ProcessorArchitecture::ARM64, SysInfo.ProcessorArch);
> +  EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
> +  EXPECT_EQ(0x01020304u, SysInfo.CSDVersionRVA);
> +  EXPECT_EQ(0x05060708u, SysInfo.CPU.Arm.CPUID);
> +
> +  EXPECT_EQ(StreamType::LinuxMaps, File.streams()[1].Type);
> +  EXPECT_EQ("400d9000-400db000 r-xp 00000000 b3:04 227        "
> +            "/system/bin/app_process\n"
> +            "400db000-400dc000 r--p 00001000 b3:04 227        "
> +            "/system/bin/app_process\n",
> +            toStringRef(*File.getRawStream(StreamType::LinuxMaps)));
> +
> +  EXPECT_EQ(StreamType::LinuxAuxv, File.streams()[2].Type);
> +  EXPECT_EQ((ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D}),
> +            File.getRawStream(StreamType::LinuxAuxv));
> +}
> +
> +TEST(MinidumpYAML, RawContent) {
> +  SmallString<0> Storage;
> +  auto ExpectedFile = toBinary(Storage, R"(
> +--- !minidump
> +Streams:
> +  - Type:            LinuxAuxv
> +    Size:            9
> +    Content:         DEADBEEFBAADF00D)");
> +  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
> +  object::MinidumpFile &File = **ExpectedFile;
> +
> +  EXPECT_EQ(
> +      (ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, 0x00}),
> +      File.getRawStream(StreamType::LinuxAuxv));
> +}
> +
> +TEST(MinidumpYAML, X86SystemInfo) {
> +  SmallString<0> Storage;
> +  auto ExpectedFile = toBinary(Storage, R"(
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  X86
> +    Platform ID:     Linux
> +    CPU:
> +      Vendor ID:       LLVMLLVMLLVM
> +      Version Info:    0x01020304
> +      Feature Info:    0x05060708
> +      AMD Extended Features: 0x09000102)");
> +  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
> +  object::MinidumpFile &File = **ExpectedFile;
> +
> +  ASSERT_EQ(1u, File.streams().size());
> +
> +  auto ExpectedSysInfo = File.getSystemInfo();
> +  ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
> +  const SystemInfo &SysInfo = *ExpectedSysInfo;
> +  EXPECT_EQ(ProcessorArchitecture::X86, SysInfo.ProcessorArch);
> +  EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
> +  EXPECT_EQ("LLVMLLVMLLVM", StringRef(SysInfo.CPU.X86.VendorID,
> +                                      sizeof(SysInfo.CPU.X86.VendorID)));
> +  EXPECT_EQ(0x01020304u, SysInfo.CPU.X86.VersionInfo);
> +  EXPECT_EQ(0x05060708u, SysInfo.CPU.X86.FeatureInfo);
> +  EXPECT_EQ(0x09000102u, SysInfo.CPU.X86.AMDExtendedFeatures);
> +}
> +
> +TEST(MinidumpYAML, OtherSystemInfo) {
> +  SmallString<0> Storage;
> +  auto ExpectedFile = toBinary(Storage, R"(
> +--- !minidump
> +Streams:
> +  - Type:            SystemInfo
> +    Processor Arch:  PPC
> +    Platform ID:     Linux
> +    CPU:
> +      Features:        000102030405060708090a0b0c0d0e0f)");
> +  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
> +  object::MinidumpFile &File = **ExpectedFile;
> +
> +  ASSERT_EQ(1u, File.streams().size());
> +
> +  auto ExpectedSysInfo = File.getSystemInfo();
> +  ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
> +  const SystemInfo &SysInfo = *ExpectedSysInfo;
> +  EXPECT_EQ(ProcessorArchitecture::PPC, SysInfo.ProcessorArch);
> +  EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
> +  EXPECT_EQ(
> +      (ArrayRef<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
> +      makeArrayRef(SysInfo.CPU.Other.ProcessorFeatures));
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list