MinidumpYAML.h revision 360784
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 17namespace llvm { 18namespace 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. 27struct 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 57namespace 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. 61template <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. 73struct 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. 84struct 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. 94struct 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 103using ModuleListStream = detail::ListStream<detail::ParsedModule>; 104using ThreadListStream = detail::ListStream<detail::ParsedThread>; 105using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>; 106 107/// ExceptionStream minidump stream. 108struct 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. 128struct 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. 148struct 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. 162struct 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. 182LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef) 183 184/// A minidump stream containing textual data (typically, the contents of a 185/// /proc/<pid> file on linux). 186struct 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. 201struct 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 223namespace yaml { 224template <> 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 237template <> struct MappingTraits<std::unique_ptr<MinidumpYAML::Stream>> { 238 static void mapping(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S); 239 static StringRef validate(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S); 240}; 241 242template <> 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 251LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryProtection) 252LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryState) 253LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryType) 254 255LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture) 256LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform) 257LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType) 258 259LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo) 260LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo) 261LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info) 262LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::Exception) 263LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::MemoryInfo) 264LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo) 265 266LLVM_YAML_DECLARE_MAPPING_TRAITS( 267 llvm::MinidumpYAML::MemoryListStream::entry_type) 268LLVM_YAML_DECLARE_MAPPING_TRAITS( 269 llvm::MinidumpYAML::ModuleListStream::entry_type) 270LLVM_YAML_DECLARE_MAPPING_TRAITS( 271 llvm::MinidumpYAML::ThreadListStream::entry_type) 272 273LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>) 274LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type) 275LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type) 276LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type) 277LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::minidump::MemoryInfo) 278 279LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object) 280 281#endif // LLVM_OBJECTYAML_MINIDUMPYAML_H 282