Home | History | Annotate | Line # | Download | only in ObjectYAML
      1 //===- MinidumpYAML.h - Minidump YAMLIO implementation ----------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_OBJECTYAML_MINIDUMPYAML_H
     10 #define LLVM_OBJECTYAML_MINIDUMPYAML_H
     11 
     12 #include "llvm/BinaryFormat/Minidump.h"
     13 #include "llvm/Object/Minidump.h"
     14 #include "llvm/ObjectYAML/YAML.h"
     15 #include "llvm/Support/YAMLTraits.h"
     16 
     17 namespace llvm {
     18 namespace MinidumpYAML {
     19 
     20 /// The base class for all minidump streams. The "Type" of the stream
     21 /// corresponds to the Stream Type field in the minidump file. The "Kind" field
     22 /// specifies how are we going to treat it. For highly specialized streams (e.g.
     23 /// SystemInfo), there is a 1:1 mapping between Types and Kinds, but in general
     24 /// one stream Kind can be used to represent multiple stream Types (e.g. any
     25 /// unrecognised stream Type will be handled via RawContentStream). The mapping
     26 /// from Types to Kinds is fixed and given by the static getKind function.
     27 struct Stream {
     28   enum class StreamKind {
     29     Exception,
     30     MemoryInfoList,
     31     MemoryList,
     32     ModuleList,
     33     RawContent,
     34     SystemInfo,
     35     TextContent,
     36     ThreadList,
     37   };
     38 
     39   Stream(StreamKind Kind, minidump::StreamType Type) : Kind(Kind), Type(Type) {}
     40   virtual ~Stream(); // anchor
     41 
     42   const StreamKind Kind;
     43   const minidump::StreamType Type;
     44 
     45   /// Get the stream Kind used for representing streams of a given Type.
     46   static StreamKind getKind(minidump::StreamType Type);
     47 
     48   /// Create an empty stream of the given Type.
     49   static std::unique_ptr<Stream> create(minidump::StreamType Type);
     50 
     51   /// Create a stream from the given stream directory entry.
     52   static Expected<std::unique_ptr<Stream>>
     53   create(const minidump::Directory &StreamDesc,
     54          const object::MinidumpFile &File);
     55 };
     56 
     57 namespace detail {
     58 /// A stream representing a list of abstract entries in a minidump stream. Its
     59 /// instantiations can be used to represent the ModuleList stream and other
     60 /// streams with a similar structure.
     61 template <typename EntryT> struct ListStream : public Stream {
     62   using entry_type = EntryT;
     63 
     64   std::vector<entry_type> Entries;
     65 
     66   explicit ListStream(std::vector<entry_type> Entries = {})
     67       : Stream(EntryT::Kind, EntryT::Type), Entries(std::move(Entries)) {}
     68 
     69   static bool classof(const Stream *S) { return S->Kind == EntryT::Kind; }
     70 };
     71 
     72 /// A structure containing all data belonging to a single minidump module.
     73 struct ParsedModule {
     74   static constexpr Stream::StreamKind Kind = Stream::StreamKind::ModuleList;
     75   static constexpr minidump::StreamType Type = minidump::StreamType::ModuleList;
     76 
     77   minidump::Module Entry;
     78   std::string Name;
     79   yaml::BinaryRef CvRecord;
     80   yaml::BinaryRef MiscRecord;
     81 };
     82 
     83 /// A structure containing all data belonging to a single minidump thread.
     84 struct ParsedThread {
     85   static constexpr Stream::StreamKind Kind = Stream::StreamKind::ThreadList;
     86   static constexpr minidump::StreamType Type = minidump::StreamType::ThreadList;
     87 
     88   minidump::Thread Entry;
     89   yaml::BinaryRef Stack;
     90   yaml::BinaryRef Context;
     91 };
     92 
     93 /// A structure containing all data describing a single memory region.
     94 struct ParsedMemoryDescriptor {
     95   static constexpr Stream::StreamKind Kind = Stream::StreamKind::MemoryList;
     96   static constexpr minidump::StreamType Type = minidump::StreamType::MemoryList;
     97 
     98   minidump::MemoryDescriptor Entry;
     99   yaml::BinaryRef Content;
    100 };
    101 } // namespace detail
    102 
    103 using ModuleListStream = detail::ListStream<detail::ParsedModule>;
    104 using ThreadListStream = detail::ListStream<detail::ParsedThread>;
    105 using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
    106 
    107 /// ExceptionStream minidump stream.
    108 struct ExceptionStream : public Stream {
    109   minidump::ExceptionStream MDExceptionStream;
    110   yaml::BinaryRef ThreadContext;
    111 
    112   ExceptionStream()
    113       : Stream(StreamKind::Exception, minidump::StreamType::Exception),
    114         MDExceptionStream({}) {}
    115 
    116   explicit ExceptionStream(const minidump::ExceptionStream &MDExceptionStream,
    117                            ArrayRef<uint8_t> ThreadContext)
    118       : Stream(StreamKind::Exception, minidump::StreamType::Exception),
    119         MDExceptionStream(MDExceptionStream), ThreadContext(ThreadContext) {}
    120 
    121   static bool classof(const Stream *S) {
    122     return S->Kind == StreamKind::Exception;
    123   }
    124 };
    125 
    126 /// A structure containing the list of MemoryInfo entries comprising a
    127 /// MemoryInfoList stream.
    128 struct MemoryInfoListStream : public Stream {
    129   std::vector<minidump::MemoryInfo> Infos;
    130 
    131   MemoryInfoListStream()
    132       : Stream(StreamKind::MemoryInfoList,
    133                minidump::StreamType::MemoryInfoList) {}
    134 
    135   explicit MemoryInfoListStream(
    136       iterator_range<object::MinidumpFile::MemoryInfoIterator> Range)
    137       : Stream(StreamKind::MemoryInfoList,
    138                minidump::StreamType::MemoryInfoList),
    139         Infos(Range.begin(), Range.end()) {}
    140 
    141   static bool classof(const Stream *S) {
    142     return S->Kind == StreamKind::MemoryInfoList;
    143   }
    144 };
    145 
    146 /// A minidump stream represented as a sequence of hex bytes. This is used as a
    147 /// fallback when no other stream kind is suitable.
    148 struct RawContentStream : public Stream {
    149   yaml::BinaryRef Content;
    150   yaml::Hex32 Size;
    151 
    152   RawContentStream(minidump::StreamType Type, ArrayRef<uint8_t> Content = {})
    153       : Stream(StreamKind::RawContent, Type), Content(Content),
    154         Size(Content.size()) {}
    155 
    156   static bool classof(const Stream *S) {
    157     return S->Kind == StreamKind::RawContent;
    158   }
    159 };
    160 
    161 /// SystemInfo minidump stream.
    162 struct SystemInfoStream : public Stream {
    163   minidump::SystemInfo Info;
    164   std::string CSDVersion;
    165 
    166   SystemInfoStream()
    167       : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) {
    168     memset(&Info, 0, sizeof(Info));
    169   }
    170 
    171   explicit SystemInfoStream(const minidump::SystemInfo &Info,
    172                             std::string CSDVersion)
    173       : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
    174         Info(Info), CSDVersion(std::move(CSDVersion)) {}
    175 
    176   static bool classof(const Stream *S) {
    177     return S->Kind == StreamKind::SystemInfo;
    178   }
    179 };
    180 
    181 /// A StringRef, which is printed using YAML block notation.
    182 LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef)
    183 
    184 /// A minidump stream containing textual data (typically, the contents of a
    185 /// /proc/<pid> file on linux).
    186 struct TextContentStream : public Stream {
    187   BlockStringRef Text;
    188 
    189   TextContentStream(minidump::StreamType Type, StringRef Text = {})
    190       : Stream(StreamKind::TextContent, Type), Text(Text) {}
    191 
    192   static bool classof(const Stream *S) {
    193     return S->Kind == StreamKind::TextContent;
    194   }
    195 };
    196 
    197 /// The top level structure representing a minidump object, consisting of a
    198 /// minidump header, and zero or more streams. To construct an Object from a
    199 /// minidump file, use the static create function. To serialize to/from yaml,
    200 /// use the appropriate streaming operator on a yaml stream.
    201 struct Object {
    202   Object() = default;
    203   Object(const Object &) = delete;
    204   Object &operator=(const Object &) = delete;
    205   Object(Object &&) = default;
    206   Object &operator=(Object &&) = default;
    207 
    208   Object(const minidump::Header &Header,
    209          std::vector<std::unique_ptr<Stream>> Streams)
    210       : Header(Header), Streams(std::move(Streams)) {}
    211 
    212   /// The minidump header.
    213   minidump::Header Header;
    214 
    215   /// The list of streams in this minidump object.
    216   std::vector<std::unique_ptr<Stream>> Streams;
    217 
    218   static Expected<Object> create(const object::MinidumpFile &File);
    219 };
    220 
    221 } // namespace MinidumpYAML
    222 
    223 namespace yaml {
    224 template <> struct BlockScalarTraits<MinidumpYAML::BlockStringRef> {
    225   static void output(const MinidumpYAML::BlockStringRef &Text, void *,
    226                      raw_ostream &OS) {
    227     OS << Text;
    228   }
    229 
    230   static StringRef input(StringRef Scalar, void *,
    231                          MinidumpYAML::BlockStringRef &Text) {
    232     Text = Scalar;
    233     return "";
    234   }
    235 };
    236 
    237 template <> struct MappingTraits<std::unique_ptr<MinidumpYAML::Stream>> {
    238   static void mapping(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
    239   static std::string validate(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
    240 };
    241 
    242 template <> struct MappingContextTraits<minidump::MemoryDescriptor, BinaryRef> {
    243   static void mapping(IO &IO, minidump::MemoryDescriptor &Memory,
    244                       BinaryRef &Content);
    245 };
    246 
    247 } // namespace yaml
    248 
    249 } // namespace llvm
    250 
    251 LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryProtection)
    252 LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryState)
    253 LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryType)
    254 
    255 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
    256 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
    257 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
    258 
    259 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
    260 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
    261 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
    262 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::Exception)
    263 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::MemoryInfo)
    264 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
    265 
    266 LLVM_YAML_DECLARE_MAPPING_TRAITS(
    267     llvm::MinidumpYAML::MemoryListStream::entry_type)
    268 LLVM_YAML_DECLARE_MAPPING_TRAITS(
    269     llvm::MinidumpYAML::ModuleListStream::entry_type)
    270 LLVM_YAML_DECLARE_MAPPING_TRAITS(
    271     llvm::MinidumpYAML::ThreadListStream::entry_type)
    272 
    273 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
    274 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type)
    275 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type)
    276 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type)
    277 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::minidump::MemoryInfo)
    278 
    279 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
    280 
    281 #endif // LLVM_OBJECTYAML_MINIDUMPYAML_H
    282