]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ObjectYAML/MinidumpYAML.h
Merge libunwind trunk r366426, resolve conflicts, and add FREEBSD-Xlist.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ObjectYAML / MinidumpYAML.h
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     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
55 namespace 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.
59 template <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.
71 struct 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.
82 struct 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.
92 struct 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
101 using ModuleListStream = detail::ListStream<detail::ParsedModule>;
102 using ThreadListStream = detail::ListStream<detail::ParsedThread>;
103 using 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.
107 struct 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.
121 struct 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.
141 LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef)
142
143 /// A minidump stream containing textual data (typically, the contents of a
144 /// /proc/<pid> file on linux).
145 struct 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.
160 struct 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.
181 void writeAsBinary(Object &Obj, raw_ostream &OS);
182
183 /// Serialize the yaml string as a minidump file to OS in binary form.
184 Error writeAsBinary(StringRef Yaml, raw_ostream &OS);
185
186 } // namespace MinidumpYAML
187
188 namespace yaml {
189 template <> 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
202 template <> 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
207 template <> 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
216 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
217 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
218 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
219
220 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
221 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
222 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
223 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
224
225 LLVM_YAML_DECLARE_MAPPING_TRAITS(
226     llvm::MinidumpYAML::MemoryListStream::entry_type)
227 LLVM_YAML_DECLARE_MAPPING_TRAITS(
228     llvm::MinidumpYAML::ModuleListStream::entry_type)
229 LLVM_YAML_DECLARE_MAPPING_TRAITS(
230     llvm::MinidumpYAML::ThreadListStream::entry_type)
231
232 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
233 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type)
234 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type)
235 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type)
236
237 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
238
239 #endif // LLVM_OBJECTYAML_MINIDUMPYAML_H