Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 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 |