LLVM  10.0.0svn
MinidumpYAML.cpp
Go to the documentation of this file.
1 //===- MinidumpYAML.cpp - Minidump YAMLIO implementation ------------------===//
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 
10 #include "llvm/Support/Allocator.h"
12 
13 using namespace llvm;
14 using namespace llvm::MinidumpYAML;
15 using namespace llvm::minidump;
16 
17 namespace {
18 /// A helper class to manage the placement of various structures into the final
19 /// minidump binary. Space for objects can be allocated via various allocate***
20 /// methods, while the final minidump file is written by calling the writeTo
21 /// method. The plain versions of allocation functions take a reference to the
22 /// data which is to be written (and hence the data must be available until
23 /// writeTo is called), while the "New" versions allocate the data in an
24 /// allocator-managed buffer, which is available until the allocator object is
25 /// destroyed. For both kinds of functions, it is possible to modify the
26 /// data for which the space has been "allocated" until the final writeTo call.
27 /// This is useful for "linking" the allocated structures via their offsets.
28 class BlobAllocator {
29 public:
30  size_t tell() const { return NextOffset; }
31 
32  size_t allocateCallback(size_t Size,
33  std::function<void(raw_ostream &)> Callback) {
34  size_t Offset = NextOffset;
35  NextOffset += Size;
36  Callbacks.push_back(std::move(Callback));
37  return Offset;
38  }
39 
40  size_t allocateBytes(ArrayRef<uint8_t> Data) {
41  return allocateCallback(
42  Data.size(), [Data](raw_ostream &OS) { OS << toStringRef(Data); });
43  }
44 
45  size_t allocateBytes(yaml::BinaryRef Data) {
46  return allocateCallback(Data.binary_size(), [Data](raw_ostream &OS) {
47  Data.writeAsBinary(OS);
48  });
49  }
50 
51  template <typename T> size_t allocateArray(ArrayRef<T> Data) {
52  return allocateBytes({reinterpret_cast<const uint8_t *>(Data.data()),
53  sizeof(T) * Data.size()});
54  }
55 
56  template <typename T, typename RangeType>
57  std::pair<size_t, MutableArrayRef<T>>
58  allocateNewArray(const iterator_range<RangeType> &Range);
59 
60  template <typename T> size_t allocateObject(const T &Data) {
61  return allocateArray(makeArrayRef(Data));
62  }
63 
64  template <typename T, typename... Types>
65  std::pair<size_t, T *> allocateNewObject(Types &&... Args) {
66  T *Object = new (Temporaries.Allocate<T>()) T(std::forward<Types>(Args)...);
67  return {allocateObject(*Object), Object};
68  }
69 
70  size_t allocateString(StringRef Str);
71 
72  void writeTo(raw_ostream &OS) const;
73 
74 private:
75  size_t NextOffset = 0;
76 
77  BumpPtrAllocator Temporaries;
78  std::vector<std::function<void(raw_ostream &)>> Callbacks;
79 };
80 } // namespace
81 
82 template <typename T, typename RangeType>
83 std::pair<size_t, MutableArrayRef<T>>
84 BlobAllocator::allocateNewArray(const iterator_range<RangeType> &Range) {
85  size_t Num = std::distance(Range.begin(), Range.end());
86  MutableArrayRef<T> Array(Temporaries.Allocate<T>(Num), Num);
87  std::uninitialized_copy(Range.begin(), Range.end(), Array.begin());
88  return {allocateArray(Array), Array};
89 }
90 
91 size_t BlobAllocator::allocateString(StringRef Str) {
93  bool OK = convertUTF8ToUTF16String(Str, WStr);
94  assert(OK && "Invalid UTF8 in Str?");
95  (void)OK;
96 
97  // The utf16 string is null-terminated, but the terminator is not counted in
98  // the string size.
99  WStr.push_back(0);
100  size_t Result =
101  allocateNewObject<support::ulittle32_t>(2 * (WStr.size() - 1)).first;
102  allocateNewArray<support::ulittle16_t>(make_range(WStr.begin(), WStr.end()));
103  return Result;
104 }
105 
106 void BlobAllocator::writeTo(raw_ostream &OS) const {
107  size_t BeginOffset = OS.tell();
108  for (const auto &Callback : Callbacks)
109  Callback(OS);
110  assert(OS.tell() == BeginOffset + NextOffset &&
111  "Callbacks wrote an unexpected number of bytes.");
112  (void)BeginOffset;
113 }
114 
115 /// Perform an optional yaml-mapping of an endian-aware type EndianType. The
116 /// only purpose of this function is to avoid casting the Default value to the
117 /// endian type;
118 template <typename EndianType>
119 static inline void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val,
120  typename EndianType::value_type Default) {
121  IO.mapOptional(Key, Val, EndianType(Default));
122 }
123 
124 /// Yaml-map an endian-aware type EndianType as some other type MapType.
125 template <typename MapType, typename EndianType>
126 static inline void mapRequiredAs(yaml::IO &IO, const char *Key,
127  EndianType &Val) {
128  MapType Mapped = static_cast<typename EndianType::value_type>(Val);
129  IO.mapRequired(Key, Mapped);
130  Val = static_cast<typename EndianType::value_type>(Mapped);
131 }
132 
133 /// Perform an optional yaml-mapping of an endian-aware type EndianType as some
134 /// other type MapType.
135 template <typename MapType, typename EndianType>
136 static inline void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val,
137  MapType Default) {
138  MapType Mapped = static_cast<typename EndianType::value_type>(Val);
139  IO.mapOptional(Key, Mapped, Default);
140  Val = static_cast<typename EndianType::value_type>(Mapped);
141 }
142 
143 namespace {
144 /// Return the appropriate yaml Hex type for a given endian-aware type.
145 template <typename EndianType> struct HexType;
146 template <> struct HexType<support::ulittle16_t> { using type = yaml::Hex16; };
147 template <> struct HexType<support::ulittle32_t> { using type = yaml::Hex32; };
148 template <> struct HexType<support::ulittle64_t> { using type = yaml::Hex64; };
149 } // namespace
150 
151 /// Yaml-map an endian-aware type as an appropriately-sized hex value.
152 template <typename EndianType>
153 static inline void mapRequiredHex(yaml::IO &IO, const char *Key,
154  EndianType &Val) {
155  mapRequiredAs<typename HexType<EndianType>::type>(IO, Key, Val);
156 }
157 
158 /// Perform an optional yaml-mapping of an endian-aware type as an
159 /// appropriately-sized hex value.
160 template <typename EndianType>
161 static inline void mapOptionalHex(yaml::IO &IO, const char *Key,
162  EndianType &Val,
163  typename EndianType::value_type Default) {
164  mapOptionalAs<typename HexType<EndianType>::type>(IO, Key, Val, Default);
165 }
166 
167 Stream::~Stream() = default;
168 
170  switch (Type) {
171  case StreamType::MemoryList:
172  return StreamKind::MemoryList;
173  case StreamType::ModuleList:
174  return StreamKind::ModuleList;
175  case StreamType::SystemInfo:
176  return StreamKind::SystemInfo;
177  case StreamType::LinuxCPUInfo:
178  case StreamType::LinuxProcStatus:
179  case StreamType::LinuxLSBRelease:
180  case StreamType::LinuxCMDLine:
181  case StreamType::LinuxMaps:
182  case StreamType::LinuxProcStat:
183  case StreamType::LinuxProcUptime:
184  return StreamKind::TextContent;
185  case StreamType::ThreadList:
186  return StreamKind::ThreadList;
187  default:
188  return StreamKind::RawContent;
189  }
190 }
191 
192 std::unique_ptr<Stream> Stream::create(StreamType Type) {
193  StreamKind Kind = getKind(Type);
194  switch (Kind) {
195  case StreamKind::MemoryList:
196  return llvm::make_unique<MemoryListStream>();
197  case StreamKind::ModuleList:
198  return llvm::make_unique<ModuleListStream>();
199  case StreamKind::RawContent:
200  return llvm::make_unique<RawContentStream>(Type);
201  case StreamKind::SystemInfo:
202  return llvm::make_unique<SystemInfoStream>();
203  case StreamKind::TextContent:
204  return llvm::make_unique<TextContentStream>(Type);
205  case StreamKind::ThreadList:
206  return llvm::make_unique<ThreadListStream>();
207  }
208  llvm_unreachable("Unhandled stream kind!");
209 }
210 
211 void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
212  IO &IO, ProcessorArchitecture &Arch) {
213 #define HANDLE_MDMP_ARCH(CODE, NAME) \
214  IO.enumCase(Arch, #NAME, ProcessorArchitecture::NAME);
215 #include "llvm/BinaryFormat/MinidumpConstants.def"
216  IO.enumFallback<Hex16>(Arch);
217 }
218 
219 void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO,
220  OSPlatform &Plat) {
221 #define HANDLE_MDMP_PLATFORM(CODE, NAME) \
222  IO.enumCase(Plat, #NAME, OSPlatform::NAME);
223 #include "llvm/BinaryFormat/MinidumpConstants.def"
224  IO.enumFallback<Hex32>(Plat);
225 }
226 
227 void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO,
228  StreamType &Type) {
229 #define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) \
230  IO.enumCase(Type, #NAME, StreamType::NAME);
231 #include "llvm/BinaryFormat/MinidumpConstants.def"
232  IO.enumFallback<Hex32>(Type);
233 }
234 
237  mapRequiredHex(IO, "CPUID", Info.CPUID);
238  mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0);
239 }
240 
241 namespace {
242 template <std::size_t N> struct FixedSizeHex {
243  FixedSizeHex(uint8_t (&Storage)[N]) : Storage(Storage) {}
244 
245  uint8_t (&Storage)[N];
246 };
247 } // namespace
248 
249 namespace llvm {
250 namespace yaml {
251 template <std::size_t N> struct ScalarTraits<FixedSizeHex<N>> {
252  static void output(const FixedSizeHex<N> &Fixed, void *, raw_ostream &OS) {
253  OS << toHex(makeArrayRef(Fixed.Storage));
254  }
255 
256  static StringRef input(StringRef Scalar, void *, FixedSizeHex<N> &Fixed) {
257  if (!all_of(Scalar, isHexDigit))
258  return "Invalid hex digit in input";
259  if (Scalar.size() < 2 * N)
260  return "String too short";
261  if (Scalar.size() > 2 * N)
262  return "String too long";
263  copy(fromHex(Scalar), Fixed.Storage);
264  return "";
265  }
266 
267  static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
268 };
269 } // namespace yaml
270 } // namespace llvm
272  IO &IO, CPUInfo::OtherInfo &Info) {
273  FixedSizeHex<sizeof(Info.ProcessorFeatures)> Features(Info.ProcessorFeatures);
274  IO.mapRequired("Features", Features);
275 }
276 
277 namespace {
278 /// A type which only accepts strings of a fixed size for yaml conversion.
279 template <std::size_t N> struct FixedSizeString {
280  FixedSizeString(char (&Storage)[N]) : Storage(Storage) {}
281 
282  char (&Storage)[N];
283 };
284 } // namespace
285 
286 namespace llvm {
287 namespace yaml {
288 template <std::size_t N> struct ScalarTraits<FixedSizeString<N>> {
289  static void output(const FixedSizeString<N> &Fixed, void *, raw_ostream &OS) {
290  OS << StringRef(Fixed.Storage, N);
291  }
292 
293  static StringRef input(StringRef Scalar, void *, FixedSizeString<N> &Fixed) {
294  if (Scalar.size() < N)
295  return "String too short";
296  if (Scalar.size() > N)
297  return "String too long";
298  copy(Scalar, Fixed.Storage);
299  return "";
300  }
301 
302  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
303 };
304 } // namespace yaml
305 } // namespace llvm
306 
308  CPUInfo::X86Info &Info) {
309  FixedSizeString<sizeof(Info.VendorID)> VendorID(Info.VendorID);
310  IO.mapRequired("Vendor ID", VendorID);
311 
312  mapRequiredHex(IO, "Version Info", Info.VersionInfo);
313  mapRequiredHex(IO, "Feature Info", Info.FeatureInfo);
314  mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);
315 }
316 
318  VSFixedFileInfo &Info) {
319  mapOptionalHex(IO, "Signature", Info.Signature, 0);
320  mapOptionalHex(IO, "Struct Version", Info.StructVersion, 0);
321  mapOptionalHex(IO, "File Version High", Info.FileVersionHigh, 0);
322  mapOptionalHex(IO, "File Version Low", Info.FileVersionLow, 0);
323  mapOptionalHex(IO, "Product Version High", Info.ProductVersionHigh, 0);
324  mapOptionalHex(IO, "Product Version Low", Info.ProductVersionLow, 0);
325  mapOptionalHex(IO, "File Flags Mask", Info.FileFlagsMask, 0);
326  mapOptionalHex(IO, "File Flags", Info.FileFlags, 0);
327  mapOptionalHex(IO, "File OS", Info.FileOS, 0);
328  mapOptionalHex(IO, "File Type", Info.FileType, 0);
329  mapOptionalHex(IO, "File Subtype", Info.FileSubtype, 0);
330  mapOptionalHex(IO, "File Date High", Info.FileDateHigh, 0);
331  mapOptionalHex(IO, "File Date Low", Info.FileDateLow, 0);
332 }
333 
335  IO &IO, ModuleListStream::entry_type &M) {
336  mapRequiredHex(IO, "Base of Image", M.Entry.BaseOfImage);
337  mapRequiredHex(IO, "Size of Image", M.Entry.SizeOfImage);
338  mapOptionalHex(IO, "Checksum", M.Entry.Checksum, 0);
339  IO.mapOptional("Time Date Stamp", M.Entry.TimeDateStamp,
341  IO.mapRequired("Module Name", M.Name);
342  IO.mapOptional("Version Info", M.Entry.VersionInfo, VSFixedFileInfo());
343  IO.mapRequired("CodeView Record", M.CvRecord);
344  IO.mapOptional("Misc Record", M.MiscRecord, yaml::BinaryRef());
345  mapOptionalHex(IO, "Reserved0", M.Entry.Reserved0, 0);
346  mapOptionalHex(IO, "Reserved1", M.Entry.Reserved1, 0);
347 }
348 
349 static void streamMapping(yaml::IO &IO, RawContentStream &Stream) {
350  IO.mapOptional("Content", Stream.Content);
351  IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size());
352 }
353 
355  if (Stream.Size.value < Stream.Content.binary_size())
356  return "Stream size must be greater or equal to the content size";
357  return "";
358 }
359 
361  IO &IO, MemoryListStream::entry_type &Range) {
362  MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
363  IO, Range.Entry, Range.Content);
364 }
365 
366 static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {
367  IO.mapRequired("Memory Ranges", Stream.Entries);
368 }
369 
370 static void streamMapping(yaml::IO &IO, ModuleListStream &Stream) {
371  IO.mapRequired("Modules", Stream.Entries);
372 }
373 
374 static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) {
375  SystemInfo &Info = Stream.Info;
376  IO.mapRequired("Processor Arch", Info.ProcessorArch);
377  mapOptional(IO, "Processor Level", Info.ProcessorLevel, 0);
378  mapOptional(IO, "Processor Revision", Info.ProcessorRevision, 0);
379  IO.mapOptional("Number of Processors", Info.NumberOfProcessors, 0);
380  IO.mapOptional("Product type", Info.ProductType, 0);
381  mapOptional(IO, "Major Version", Info.MajorVersion, 0);
382  mapOptional(IO, "Minor Version", Info.MinorVersion, 0);
383  mapOptional(IO, "Build Number", Info.BuildNumber, 0);
384  IO.mapRequired("Platform ID", Info.PlatformId);
385  IO.mapOptional("CSD Version", Stream.CSDVersion, "");
386  mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);
387  mapOptionalHex(IO, "Reserved", Info.Reserved, 0);
388  switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {
389  case ProcessorArchitecture::X86:
390  case ProcessorArchitecture::AMD64:
391  IO.mapOptional("CPU", Info.CPU.X86);
392  break;
394  case ProcessorArchitecture::ARM64:
395  IO.mapOptional("CPU", Info.CPU.Arm);
396  break;
397  default:
398  IO.mapOptional("CPU", Info.CPU.Other);
399  break;
400  }
401 }
402 
403 static void streamMapping(yaml::IO &IO, TextContentStream &Stream) {
404  IO.mapOptional("Text", Stream.Text);
405 }
406 
407 void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
408  IO &IO, MemoryDescriptor &Memory, BinaryRef &Content) {
409  mapRequiredHex(IO, "Start of Memory Range", Memory.StartOfMemoryRange);
410  IO.mapRequired("Content", Content);
411 }
412 
414  IO &IO, ThreadListStream::entry_type &T) {
415  mapRequiredHex(IO, "Thread Id", T.Entry.ThreadId);
416  mapOptionalHex(IO, "Suspend Count", T.Entry.SuspendCount, 0);
417  mapOptionalHex(IO, "Priority Class", T.Entry.PriorityClass, 0);
418  mapOptionalHex(IO, "Priority", T.Entry.Priority, 0);
419  mapOptionalHex(IO, "Environment Block", T.Entry.EnvironmentBlock, 0);
420  IO.mapRequired("Context", T.Context);
421  IO.mapRequired("Stack", T.Entry.Stack, T.Stack);
422 }
423 
424 static void streamMapping(yaml::IO &IO, ThreadListStream &Stream) {
425  IO.mapRequired("Threads", Stream.Entries);
426 }
427 
429  yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
430  StreamType Type;
431  if (IO.outputting())
432  Type = S->Type;
433  IO.mapRequired("Type", Type);
434 
435  if (!IO.outputting())
437  switch (S->Kind) {
439  streamMapping(IO, llvm::cast<MemoryListStream>(*S));
440  break;
442  streamMapping(IO, llvm::cast<ModuleListStream>(*S));
443  break;
445  streamMapping(IO, llvm::cast<RawContentStream>(*S));
446  break;
448  streamMapping(IO, llvm::cast<SystemInfoStream>(*S));
449  break;
451  streamMapping(IO, llvm::cast<TextContentStream>(*S));
452  break;
454  streamMapping(IO, llvm::cast<ThreadListStream>(*S));
455  break;
456  }
457 }
458 
460  yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
461  switch (S->Kind) {
463  return streamValidate(cast<RawContentStream>(*S));
469  return "";
470  }
471  llvm_unreachable("Fully covered switch above!");
472 }
473 
475  IO.mapTag("!minidump", true);
476  mapOptionalHex(IO, "Signature", O.Header.Signature, Header::MagicSignature);
477  mapOptionalHex(IO, "Version", O.Header.Version, Header::MagicVersion);
478  mapOptionalHex(IO, "Flags", O.Header.Flags, 0);
479  IO.mapRequired("Streams", O.Streams);
480 }
481 
482 static LocationDescriptor layout(BlobAllocator &File, yaml::BinaryRef Data) {
483  return {support::ulittle32_t(Data.binary_size()),
484  support::ulittle32_t(File.allocateBytes(Data))};
485 }
486 
487 static void layout(BlobAllocator &File, MemoryListStream::entry_type &Range) {
488  Range.Entry.Memory = layout(File, Range.Content);
489 }
490 
491 static void layout(BlobAllocator &File, ModuleListStream::entry_type &M) {
492  M.Entry.ModuleNameRVA = File.allocateString(M.Name);
493 
494  M.Entry.CvRecord = layout(File, M.CvRecord);
495  M.Entry.MiscRecord = layout(File, M.MiscRecord);
496 }
497 
498 static void layout(BlobAllocator &File, ThreadListStream::entry_type &T) {
499  T.Entry.Stack.Memory = layout(File, T.Stack);
500  T.Entry.Context = layout(File, T.Context);
501 }
502 
503 template <typename EntryT>
504 static size_t layout(BlobAllocator &File,
506 
507  File.allocateNewObject<support::ulittle32_t>(S.Entries.size());
508  for (auto &E : S.Entries)
509  File.allocateObject(E.Entry);
510 
511  size_t DataEnd = File.tell();
512 
513  // Lay out the auxiliary data, (which is not a part of the stream).
514  DataEnd = File.tell();
515  for (auto &E : S.Entries)
516  layout(File, E);
517 
518  return DataEnd;
519 }
520 
521 static Directory layout(BlobAllocator &File, Stream &S) {
522  Directory Result;
523  Result.Type = S.Type;
524  Result.Location.RVA = File.tell();
525  Optional<size_t> DataEnd;
526  switch (S.Kind) {
528  DataEnd = layout(File, cast<MemoryListStream>(S));
529  break;
531  DataEnd = layout(File, cast<ModuleListStream>(S));
532  break;
534  RawContentStream &Raw = cast<RawContentStream>(S);
535  File.allocateCallback(Raw.Size, [&Raw](raw_ostream &OS) {
536  Raw.Content.writeAsBinary(OS);
537  assert(Raw.Content.binary_size() <= Raw.Size);
538  OS << std::string(Raw.Size - Raw.Content.binary_size(), '\0');
539  });
540  break;
541  }
543  SystemInfoStream &SystemInfo = cast<SystemInfoStream>(S);
544  File.allocateObject(SystemInfo.Info);
545  // The CSD string is not a part of the stream.
546  DataEnd = File.tell();
547  SystemInfo.Info.CSDVersionRVA = File.allocateString(SystemInfo.CSDVersion);
548  break;
549  }
551  File.allocateArray(arrayRefFromStringRef(cast<TextContentStream>(S).Text));
552  break;
554  DataEnd = layout(File, cast<ThreadListStream>(S));
555  break;
556  }
557  // If DataEnd is not set, we assume everything we generated is a part of the
558  // stream.
559  Result.Location.DataSize =
560  DataEnd.getValueOr(File.tell()) - Result.Location.RVA;
561  return Result;
562 }
563 
565  BlobAllocator File;
566  File.allocateObject(Obj.Header);
567 
568  std::vector<Directory> StreamDirectory(Obj.Streams.size());
570  File.allocateArray(makeArrayRef(StreamDirectory));
571  Obj.Header.NumberOfStreams = StreamDirectory.size();
572 
573  for (auto &Stream : enumerate(Obj.Streams))
574  StreamDirectory[Stream.index()] = layout(File, *Stream.value());
575 
576  File.writeTo(OS);
577 }
578 
580  yaml::Input Input(Yaml);
581  Object Obj;
582  Input >> Obj;
583  if (std::error_code EC = Input.error())
584  return errorCodeToError(EC);
585 
586  writeAsBinary(Obj, OS);
587  return Error::success();
588 }
589 
591 Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
592  StreamKind Kind = getKind(StreamDesc.Type);
593  switch (Kind) {
594  case StreamKind::MemoryList: {
595  auto ExpectedList = File.getMemoryList();
596  if (!ExpectedList)
597  return ExpectedList.takeError();
598  std::vector<MemoryListStream::entry_type> Ranges;
599  for (const MemoryDescriptor &MD : *ExpectedList) {
600  auto ExpectedContent = File.getRawData(MD.Memory);
601  if (!ExpectedContent)
602  return ExpectedContent.takeError();
603  Ranges.push_back({MD, *ExpectedContent});
604  }
605  return llvm::make_unique<MemoryListStream>(std::move(Ranges));
606  }
607  case StreamKind::ModuleList: {
608  auto ExpectedList = File.getModuleList();
609  if (!ExpectedList)
610  return ExpectedList.takeError();
611  std::vector<ModuleListStream::entry_type> Modules;
612  for (const Module &M : *ExpectedList) {
613  auto ExpectedName = File.getString(M.ModuleNameRVA);
614  if (!ExpectedName)
615  return ExpectedName.takeError();
616  auto ExpectedCv = File.getRawData(M.CvRecord);
617  if (!ExpectedCv)
618  return ExpectedCv.takeError();
619  auto ExpectedMisc = File.getRawData(M.MiscRecord);
620  if (!ExpectedMisc)
621  return ExpectedMisc.takeError();
622  Modules.push_back(
623  {M, std::move(*ExpectedName), *ExpectedCv, *ExpectedMisc});
624  }
625  return llvm::make_unique<ModuleListStream>(std::move(Modules));
626  }
627  case StreamKind::RawContent:
628  return llvm::make_unique<RawContentStream>(StreamDesc.Type,
629  File.getRawStream(StreamDesc));
630  case StreamKind::SystemInfo: {
631  auto ExpectedInfo = File.getSystemInfo();
632  if (!ExpectedInfo)
633  return ExpectedInfo.takeError();
634  auto ExpectedCSDVersion = File.getString(ExpectedInfo->CSDVersionRVA);
635  if (!ExpectedCSDVersion)
636  return ExpectedInfo.takeError();
637  return llvm::make_unique<SystemInfoStream>(*ExpectedInfo,
638  std::move(*ExpectedCSDVersion));
639  }
640  case StreamKind::TextContent:
641  return llvm::make_unique<TextContentStream>(
642  StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc)));
643  case StreamKind::ThreadList: {
644  auto ExpectedList = File.getThreadList();
645  if (!ExpectedList)
646  return ExpectedList.takeError();
647  std::vector<ThreadListStream::entry_type> Threads;
648  for (const Thread &T : *ExpectedList) {
649  auto ExpectedStack = File.getRawData(T.Stack.Memory);
650  if (!ExpectedStack)
651  return ExpectedStack.takeError();
652  auto ExpectedContext = File.getRawData(T.Context);
653  if (!ExpectedContext)
654  return ExpectedContext.takeError();
655  Threads.push_back({T, *ExpectedStack, *ExpectedContext});
656  }
657  return llvm::make_unique<ThreadListStream>(std::move(Threads));
658  }
659  }
660  llvm_unreachable("Unhandled stream kind!");
661 }
662 
664  std::vector<std::unique_ptr<Stream>> Streams;
665  Streams.reserve(File.streams().size());
666  for (const Directory &StreamDesc : File.streams()) {
667  auto ExpectedStream = Stream::create(StreamDesc, File);
668  if (!ExpectedStream)
669  return ExpectedStream.takeError();
670  Streams.push_back(std::move(*ExpectedStream));
671  }
672  return Object(File.header(), std::move(Streams));
673 }
support::ulittle32_t FeatureInfo
Definition: Minidump.h:99
static void output(const FixedSizeString< N > &Fixed, void *, raw_ostream &OS)
SystemInfo minidump stream.
Definition: MinidumpYAML.h:121
static Expected< Object > create(const object::MinidumpFile &File)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Specifies the location (and size) of various objects in the minidump file.
Definition: Minidump.h:56
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
static void mapRequiredHex(yaml::IO &IO, const char *Key, EndianType &Val)
Yaml-map an endian-aware type as an appropriately-sized hex value.
support::ulittle32_t NumberOfStreams
Definition: Minidump.h:37
static StringRef input(StringRef Scalar, void *, FixedSizeHex< N > &Fixed)
This class provides various memory handling functions that manipulate MemoryBlock instances...
Definition: Memory.h:53
struct llvm::minidump::CPUInfo::X86Info X86
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:266
support::ulittle32_t Signature
Definition: Minidump.h:33
ProcessorArchitecture
The processor architecture of the system that generated this minidump.
Definition: Minidump.h:81
ArrayRef< uint8_t > arrayRefFromStringRef(StringRef Input)
Construct a string ref from an array ref of unsigned chars.
Definition: StringExtras.h:60
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1192
struct llvm::minidump::CPUInfo::OtherInfo Other
detail::packed_endian_specific_integral< uint16_t, little, unaligned > ulittle16_t
Definition: Endian.h:272
static StringRef input(StringRef Scalar, void *, FixedSizeString< N > &Fixed)
ArrayRef< minidump::Directory > streams() const
Returns the list of streams (stream directory entries) in this file.
Definition: Minidump.h:35
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
std::string fromHex(StringRef Input)
Convert hexadecimal string Input to its binary representation.
Definition: StringExtras.h:170
Expected< std::string > getString(size_t Offset) const
Returns the minidump string at the given offset.
Definition: Minidump.cpp:25
detail::packed_endian_specific_integral< uint64_t, little, unaligned > ulittle64_t
Definition: Endian.h:276
support::ulittle32_t Signature
Definition: Minidump.h:136
minidump::Header Header
The minidump header.
Definition: MinidumpYAML.h:172
OSPlatform
The OS Platform of the system that generated this minidump.
Definition: Minidump.h:88
support::ulittle32_t BuildNumber
Definition: Minidump.h:124
support::ulittle64_t Flags
Definition: Minidump.h:41
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:450
StreamType
The type of a minidump stream identifies its contents.
Definition: Minidump.h:47
support::ulittle32_t ElfHWCaps
Definition: Minidump.h:104
const minidump::Header & header() const
Returns the contents of the minidump header.
Definition: Minidump.h:32
support::ulittle32_t FileOS
Definition: Minidump.h:144
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
support::ulittle32_t StreamDirectoryRVA
Definition: Minidump.h:38
support::little_t< ProcessorArchitecture > ProcessorArch
Definition: Minidump.h:115
Key
PAL metadata keys.
support::ulittle32_t MajorVersion
Definition: Minidump.h:122
support::ulittle32_t VersionInfo
Definition: Minidump.h:98
Expected< const minidump::SystemInfo & > getSystemInfo() const
Returns the contents of the SystemInfo stream, cast to the appropriate type.
Definition: Minidump.h:61
Expected< ArrayRef< minidump::Module > > getModuleList() const
Returns the module list embedded in the ModuleList stream.
Definition: Minidump.h:70
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
void writeAsBinary(Object &Obj, raw_ostream &OS)
Serialize the minidump file represented by Obj to OS in binary form.
bool convertUTF8ToUTF16String(StringRef SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
static void streamMapping(yaml::IO &IO, RawContentStream &Stream)
support::ulittle32_t FileSubtype
Definition: Minidump.h:146
Analysis containing CSE Info
Definition: CSEInfo.cpp:20
support::ulittle16_t SuiteMask
Definition: Minidump.h:128
static void output(const FixedSizeHex< N > &Fixed, void *, raw_ostream &OS)
The top level structure representing a minidump object, consisting of a minidump header, and zero or more streams.
Definition: MinidumpYAML.h:160
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:290
support::ulittle16_t Reserved
Definition: Minidump.h:129
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:274
support::ulittle64_t StartOfMemoryRange
Definition: Minidump.h:65
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:140
support::ulittle32_t AMDExtendedFeatures
Definition: Minidump.h:100
Instrumentation for Order File
static void mapRequiredAs(yaml::IO &IO, const char *Key, EndianType &Val)
Yaml-map an endian-aware type EndianType as some other type MapType.
static StreamKind getKind(minidump::StreamType Type)
Get the stream Kind used for representing streams of a given Type.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.
Definition: StringExtras.h:79
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:87
void writeAsBinary(raw_ostream &OS) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
Definition: YAML.cpp:40
Expected< ArrayRef< minidump::MemoryDescriptor > > getMemoryList() const
Returns the list of memory ranges embedded in the MemoryList stream.
Definition: Minidump.h:88
Expected< ArrayRef< uint8_t > > getRawData(minidump::LocationDescriptor Desc) const
Returns the raw contents of an object given by the LocationDescriptor.
Definition: Minidump.h:49
static QuotingType mustQuote(StringRef S)
static void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val, MapType Default)
Perform an optional yaml-mapping of an endian-aware type EndianType as some other type MapType...
Expected< ArrayRef< minidump::Thread > > getThreadList() const
Returns the thread list embedded in the ThreadList stream.
Definition: Minidump.h:79
static LocationDescriptor layout(BlobAllocator &File, yaml::BinaryRef Data)
A stream representing a list of abstract entries in a minidump stream.
Definition: MinidumpYAML.h:59
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition: StringExtras.h:52
size_t size() const
Definition: SmallVector.h:52
ArrayRef< uint8_t > getRawStream(const minidump::Directory &Stream) const
Returns the raw contents of the stream given by the directory entry.
Definition: Minidump.h:38
Describes a single memory range (both its VM address and where to find it in the file) of the process...
Definition: Minidump.h:64
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const T * data() const
Definition: ArrayRef.h:145
struct llvm::minidump::CPUInfo::ArmInfo Arm
support::ulittle32_t FileDateLow
Definition: Minidump.h:148
ArrayRef< uint8_t >::size_type binary_size() const
The number of bytes that are represented by this BinaryRef.
Definition: YAML.h:80
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
support::ulittle32_t Version
Definition: Minidump.h:36
The base class for all minidump streams.
Definition: MinidumpYAML.h:27
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
support::ulittle16_t ProcessorRevision
Definition: Minidump.h:117
support::ulittle32_t MinorVersion
Definition: Minidump.h:123
std::vector< std::unique_ptr< Stream > > Streams
The list of streams in this minidump object.
Definition: MinidumpYAML.h:175
A minidump stream represented as a sequence of hex bytes.
Definition: MinidumpYAML.h:107
LocationDescriptor Location
Definition: Minidump.h:75
A range adaptor for a pair of iterators.
static void mapOptionalHex(yaml::IO &IO, const char *Key, EndianType &Val, typename EndianType::value_type Default)
Perform an optional yaml-mapping of an endian-aware type as an appropriately-sized hex value...
support::ulittle32_t RVA
Definition: Minidump.h:58
static StringRef streamValidate(RawContentStream &Stream)
Specialized YAMLIO scalar type for representing a binary blob.
Definition: YAML.h:63
A StringRef, which is printed using YAML block notation.
Definition: MinidumpYAML.h:145
support::ulittle32_t FileFlags
Definition: Minidump.h:143
support::ulittle32_t DataSize
Definition: Minidump.h:57
support::ulittle16_t ProcessorLevel
Definition: Minidump.h:116
support::ulittle32_t FileVersionLow
Definition: Minidump.h:139
support::little_t< OSPlatform > PlatformId
Definition: Minidump.h:125
support::ulittle32_t FileVersionHigh
Definition: Minidump.h:138
support::ulittle32_t ProductVersionLow
Definition: Minidump.h:141
#define N
Specifies the location and type of a single stream in the minidump file.
Definition: Minidump.h:73
support::ulittle32_t FileDateHigh
Definition: Minidump.h:147
support::ulittle32_t FileType
Definition: Minidump.h:145
uint32_t Size
Definition: Profile.cpp:46
support::ulittle32_t CSDVersionRVA
Definition: Minidump.h:126
support::ulittle32_t StructVersion
Definition: Minidump.h:137
support::ulittle32_t ProductVersionHigh
Definition: Minidump.h:140
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
IteratorT begin() const
Describes a single thread in the minidump file.
Definition: Minidump.h:172
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:99
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
const StreamKind Kind
Definition: MinidumpYAML.h:40
std::string toHex(StringRef Input, bool LowerCase=false)
Convert buffer Input to its hexadecimal representation.
Definition: StringExtras.h:141
static QuotingType mustQuote(StringRef S)
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1244
IteratorT end() const
static std::unique_ptr< Stream > create(minidump::StreamType Type)
Create an empty stream of the given Type.
const minidump::StreamType Type
Definition: MinidumpYAML.h:41
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
A class providing access to the contents of a minidump file.
Definition: Minidump.h:22
support::ulittle32_t CPUID
Definition: Minidump.h:103
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
static void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val, typename EndianType::value_type Default)
Perform an optional yaml-mapping of an endian-aware type EndianType.
detail::enumerator< R > enumerate(R &&TheRange)
Given an input range, returns a new range whose values are are pair (A,B) such that A is the 0-based ...
Definition: STLExtras.h:1576
support::ulittle32_t FileFlagsMask
Definition: Minidump.h:142
support::little_t< StreamType > Type
Definition: Minidump.h:74
The SystemInfo stream, containing various information about the system where this minidump was genera...
Definition: Minidump.h:114
std::vector< entry_type > Entries
Definition: MinidumpYAML.h:62