MinidumpYAML.h 9.7 KB

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