blob: 39fdd62e017b74a781729458157eb6dfde912b13 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===- 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 MemoryList,
30 ModuleList,
31 RawContent,
32 SystemInfo,
33 TextContent,
34 ThreadList,
35 };
36
37 Stream(StreamKind Kind, minidump::StreamType Type) : Kind(Kind), Type(Type) {}
38 virtual ~Stream(); // anchor
39
40 const StreamKind Kind;
41 const minidump::StreamType Type;
42
43 /// Get the stream Kind used for representing streams of a given Type.
44 static StreamKind getKind(minidump::StreamType Type);
45
46 /// Create an empty stream of the given Type.
47 static std::unique_ptr<Stream> create(minidump::StreamType Type);
48
49 /// Create a stream from the given stream directory entry.
50 static Expected<std::unique_ptr<Stream>>
51 create(const minidump::Directory &StreamDesc,
52 const object::MinidumpFile &File);
53};
54
55namespace detail {
56/// A stream representing a list of abstract entries in a minidump stream. Its
57/// instantiations can be used to represent the ModuleList stream and other
58/// streams with a similar structure.
59template <typename EntryT> struct ListStream : public Stream {
60 using entry_type = EntryT;
61
62 std::vector<entry_type> Entries;
63
64 explicit ListStream(std::vector<entry_type> Entries = {})
65 : Stream(EntryT::Kind, EntryT::Type), Entries(std::move(Entries)) {}
66
67 static bool classof(const Stream *S) { return S->Kind == EntryT::Kind; }
68};
69
70/// A structure containing all data belonging to a single minidump module.
71struct ParsedModule {
72 static constexpr Stream::StreamKind Kind = Stream::StreamKind::ModuleList;
73 static constexpr minidump::StreamType Type = minidump::StreamType::ModuleList;
74
75 minidump::Module Entry;
76 std::string Name;
77 yaml::BinaryRef CvRecord;
78 yaml::BinaryRef MiscRecord;
79};
80
81/// A structure containing all data belonging to a single minidump thread.
82struct ParsedThread {
83 static constexpr Stream::StreamKind Kind = Stream::StreamKind::ThreadList;
84 static constexpr minidump::StreamType Type = minidump::StreamType::ThreadList;
85
86 minidump::Thread Entry;
87 yaml::BinaryRef Stack;
88 yaml::BinaryRef Context;
89};
90
91/// A structure containing all data describing a single memory region.
92struct ParsedMemoryDescriptor {
93 static constexpr Stream::StreamKind Kind = Stream::StreamKind::MemoryList;
94 static constexpr minidump::StreamType Type = minidump::StreamType::MemoryList;
95
96 minidump::MemoryDescriptor Entry;
97 yaml::BinaryRef Content;
98};
99} // namespace detail
100
101using ModuleListStream = detail::ListStream<detail::ParsedModule>;
102using ThreadListStream = detail::ListStream<detail::ParsedThread>;
103using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
104
105/// A minidump stream represented as a sequence of hex bytes. This is used as a
106/// fallback when no other stream kind is suitable.
107struct RawContentStream : public Stream {
108 yaml::BinaryRef Content;
109 yaml::Hex32 Size;
110
111 RawContentStream(minidump::StreamType Type, ArrayRef<uint8_t> Content = {})
112 : Stream(StreamKind::RawContent, Type), Content(Content),
113 Size(Content.size()) {}
114
115 static bool classof(const Stream *S) {
116 return S->Kind == StreamKind::RawContent;
117 }
118};
119
120/// SystemInfo minidump stream.
121struct SystemInfoStream : public Stream {
122 minidump::SystemInfo Info;
123 std::string CSDVersion;
124
125 explicit SystemInfoStream(const minidump::SystemInfo &Info,
126 std::string CSDVersion)
127 : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
128 Info(Info), CSDVersion(std::move(CSDVersion)) {}
129
130 SystemInfoStream()
131 : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) {
132 memset(&Info, 0, sizeof(Info));
133 }
134
135 static bool classof(const Stream *S) {
136 return S->Kind == StreamKind::SystemInfo;
137 }
138};
139
140/// A StringRef, which is printed using YAML block notation.
141LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef)
142
143/// A minidump stream containing textual data (typically, the contents of a
144/// /proc/<pid> file on linux).
145struct TextContentStream : public Stream {
146 BlockStringRef Text;
147
148 TextContentStream(minidump::StreamType Type, StringRef Text = {})
149 : Stream(StreamKind::TextContent, Type), Text(Text) {}
150
151 static bool classof(const Stream *S) {
152 return S->Kind == StreamKind::TextContent;
153 }
154};
155
156/// The top level structure representing a minidump object, consisting of a
157/// minidump header, and zero or more streams. To construct an Object from a
158/// minidump file, use the static create function. To serialize to/from yaml,
159/// use the appropriate streaming operator on a yaml stream.
160struct Object {
161 Object() = default;
162 Object(const Object &) = delete;
163 Object &operator=(const Object &) = delete;
164 Object(Object &&) = default;
165 Object &operator=(Object &&) = default;
166
167 Object(const minidump::Header &Header,
168 std::vector<std::unique_ptr<Stream>> Streams)
169 : Header(Header), Streams(std::move(Streams)) {}
170
171 /// The minidump header.
172 minidump::Header Header;
173
174 /// The list of streams in this minidump object.
175 std::vector<std::unique_ptr<Stream>> Streams;
176
177 static Expected<Object> create(const object::MinidumpFile &File);
178};
179
180/// Serialize the minidump file represented by Obj to OS in binary form.
181void writeAsBinary(Object &Obj, raw_ostream &OS);
182
183/// Serialize the yaml string as a minidump file to OS in binary form.
184Error writeAsBinary(StringRef Yaml, raw_ostream &OS);
185
186} // namespace MinidumpYAML
187
188namespace yaml {
189template <> struct BlockScalarTraits<MinidumpYAML::BlockStringRef> {
190 static void output(const MinidumpYAML::BlockStringRef &Text, void *,
191 raw_ostream &OS) {
192 OS << Text;
193 }
194
195 static StringRef input(StringRef Scalar, void *,
196 MinidumpYAML::BlockStringRef &Text) {
197 Text = Scalar;
198 return "";
199 }
200};
201
202template <> struct MappingTraits<std::unique_ptr<MinidumpYAML::Stream>> {
203 static void mapping(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
204 static StringRef validate(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S);
205};
206
207template <> struct MappingContextTraits<minidump::MemoryDescriptor, BinaryRef> {
208 static void mapping(IO &IO, minidump::MemoryDescriptor &Memory,
209 BinaryRef &Content);
210};
211
212} // namespace yaml
213
214} // namespace llvm
215
216LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
217LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
218LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
219
220LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
221LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
222LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
223LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
224
225LLVM_YAML_DECLARE_MAPPING_TRAITS(
226 llvm::MinidumpYAML::MemoryListStream::entry_type)
227LLVM_YAML_DECLARE_MAPPING_TRAITS(
228 llvm::MinidumpYAML::ModuleListStream::entry_type)
229LLVM_YAML_DECLARE_MAPPING_TRAITS(
230 llvm::MinidumpYAML::ThreadListStream::entry_type)
231
232LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
233LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type)
234LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type)
235LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type)
236
237LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
238
239#endif // LLVM_OBJECTYAML_MINIDUMPYAML_H