19 template <
typename EndianType>
20 static inline void mapOptional(yaml::IO &IO,
const char *
Key, EndianType &Val,
21 typename EndianType::value_type Default) {
22 IO.mapOptional(
Key, Val, EndianType(Default));
26 template <
typename MapType,
typename EndianType>
29 MapType Mapped =
static_cast<typename EndianType::value_type
>(Val);
30 IO.mapRequired(
Key, Mapped);
31 Val =
static_cast<typename EndianType::value_type
>(Mapped);
36 template <
typename MapType,
typename EndianType>
39 MapType Mapped =
static_cast<typename EndianType::value_type
>(Val);
40 IO.mapOptional(
Key, Mapped, Default);
41 Val =
static_cast<typename EndianType::value_type
>(Mapped);
46 template <
typename EndianType>
struct HexType;
53 template <
typename EndianType>
61 template <
typename EndianType>
64 typename EndianType::value_type Default) {
72 case StreamType::Exception:
73 return StreamKind::Exception;
74 case StreamType::MemoryInfoList:
75 return StreamKind::MemoryInfoList;
76 case StreamType::MemoryList:
77 return StreamKind::MemoryList;
78 case StreamType::ModuleList:
79 return StreamKind::ModuleList;
80 case StreamType::SystemInfo:
81 return StreamKind::SystemInfo;
82 case StreamType::LinuxCPUInfo:
83 case StreamType::LinuxProcStatus:
84 case StreamType::LinuxLSBRelease:
85 case StreamType::LinuxCMDLine:
86 case StreamType::LinuxMaps:
87 case StreamType::LinuxProcStat:
88 case StreamType::LinuxProcUptime:
89 return StreamKind::TextContent;
90 case StreamType::ThreadList:
91 return StreamKind::ThreadList;
93 return StreamKind::RawContent;
100 case StreamKind::Exception:
101 return std::make_unique<ExceptionStream>();
102 case StreamKind::MemoryInfoList:
103 return std::make_unique<MemoryInfoListStream>();
104 case StreamKind::MemoryList:
105 return std::make_unique<MemoryListStream>();
106 case StreamKind::ModuleList:
107 return std::make_unique<ModuleListStream>();
108 case StreamKind::RawContent:
109 return std::make_unique<RawContentStream>(
Type);
110 case StreamKind::SystemInfo:
111 return std::make_unique<SystemInfoStream>();
112 case StreamKind::TextContent:
113 return std::make_unique<TextContentStream>(
Type);
114 case StreamKind::ThreadList:
115 return std::make_unique<ThreadListStream>();
120 void yaml::ScalarBitSetTraits<MemoryProtection>::bitset(
122 #define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) \
123 IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);
124 #include "llvm/BinaryFormat/MinidumpConstants.def"
127 void yaml::ScalarBitSetTraits<MemoryState>::bitset(IO &IO,
MemoryState &State) {
128 #define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) \
129 IO.bitSetCase(State, #NATIVENAME, MemoryState::NAME);
130 #include "llvm/BinaryFormat/MinidumpConstants.def"
133 void yaml::ScalarBitSetTraits<MemoryType>::bitset(IO &IO,
MemoryType &
Type) {
134 #define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) \
135 IO.bitSetCase(Type, #NATIVENAME, MemoryType::NAME);
136 #include "llvm/BinaryFormat/MinidumpConstants.def"
139 void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
141 #define HANDLE_MDMP_ARCH(CODE, NAME) \
142 IO.enumCase(Arch, #NAME, ProcessorArchitecture::NAME);
143 #include "llvm/BinaryFormat/MinidumpConstants.def"
144 IO.enumFallback<Hex16>(Arch);
147 void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO,
149 #define HANDLE_MDMP_PLATFORM(CODE, NAME) \
150 IO.enumCase(Plat, #NAME, OSPlatform::NAME);
151 #include "llvm/BinaryFormat/MinidumpConstants.def"
152 IO.enumFallback<Hex32>(Plat);
155 void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO,
157 #define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) \
158 IO.enumCase(Type, #NAME, StreamType::NAME);
159 #include "llvm/BinaryFormat/MinidumpConstants.def"
160 IO.enumFallback<Hex32>(
Type);
170 template <std::
size_t N>
struct FixedSizeHex {
171 FixedSizeHex(uint8_t (&Storage)[
N]) : Storage(Storage) {}
173 uint8_t (&Storage)[
N];
179 template <std::
size_t N>
struct ScalarTraits<FixedSizeHex<
N>> {
186 return "Invalid hex digit in input";
187 if (Scalar.size() < 2 *
N)
188 return "String too short";
189 if (Scalar.size() > 2 *
N)
190 return "String too long";
201 FixedSizeHex<
sizeof(
Info.ProcessorFeatures)> Features(
Info.ProcessorFeatures);
202 IO.mapRequired(
"Features", Features);
207 template <std::
size_t N>
struct FixedSizeString {
208 FixedSizeString(
char (&Storage)[
N]) : Storage(Storage) {}
216 template <std::
size_t N>
struct ScalarTraits<FixedSizeString<
N>> {
222 if (Scalar.size() <
N)
223 return "String too short";
224 if (Scalar.size() >
N)
225 return "String too long";
237 FixedSizeString<
sizeof(
Info.VendorID)> VendorID(
Info.VendorID);
238 IO.mapRequired(
"Vendor ID", VendorID);
248 mapRequiredAs<MemoryProtection>(IO,
"Allocation Protect",
249 Info.AllocationProtect);
252 mapRequiredAs<MemoryState>(IO,
"State",
Info.State);
253 mapOptionalAs<MemoryProtection>(IO,
"Protect",
Info.Protect,
254 Info.AllocationProtect);
255 mapRequiredAs<MemoryType>(IO,
"Type",
Info.Type);
281 mapOptional(IO,
"Time Date Stamp",
M.Entry.TimeDateStamp, 0);
282 IO.mapRequired(
"Module Name",
M.Name);
284 IO.mapRequired(
"CodeView Record",
M.CvRecord);
291 IO.mapOptional(
"Content",
Stream.Content);
292 IO.mapOptional(
"Size",
Stream.Size,
Stream.Content.binary_size());
297 return "Stream size must be greater or equal to the content size";
303 MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
304 IO, Range.Entry, Range.Content);
308 IO.mapRequired(
"Memory Ranges",
Stream.Infos);
312 IO.mapRequired(
"Memory Ranges",
Stream.Entries);
316 IO.mapRequired(
"Modules",
Stream.Entries);
321 IO.mapRequired(
"Processor Arch",
Info.ProcessorArch);
324 IO.mapOptional(
"Number of Processors",
Info.NumberOfProcessors, 0);
325 IO.mapOptional(
"Product type",
Info.ProductType, 0);
329 IO.mapRequired(
"Platform ID",
Info.PlatformId);
330 IO.mapOptional(
"CSD Version",
Stream.CSDVersion,
"");
335 case ProcessorArchitecture::AMD64:
336 IO.mapOptional(
"CPU",
Info.CPU.X86);
338 case ProcessorArchitecture::ARM:
339 case ProcessorArchitecture::ARM64:
340 case ProcessorArchitecture::BP_ARM64:
341 IO.mapOptional(
"CPU",
Info.CPU.Arm);
344 IO.mapOptional(
"CPU",
Info.CPU.Other);
350 IO.mapOptional(
"Text",
Stream.Text);
353 void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
356 IO.mapRequired(
"Content",
Content);
366 IO.mapRequired(
"Context",
T.Context);
367 IO.mapRequired(
"Stack",
T.Entry.Stack,
T.Stack);
371 IO.mapRequired(
"Threads",
Stream.Entries);
376 IO.mapRequired(
"Exception Record",
Stream.MDExceptionStream.ExceptionRecord);
377 IO.mapRequired(
"Thread Context",
Stream.ThreadContext);
401 yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &
S) {
405 IO.mapRequired(
"Type",
Type);
407 if (!IO.outputting())
438 yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &
S) {
455 IO.mapTag(
"!minidump",
true);
456 mapOptionalHex(IO,
"Signature",
O.Header.Signature, Header::MagicSignature);
459 IO.mapRequired(
"Streams",
O.Streams);
466 case StreamKind::Exception: {
468 File.getExceptionStream();
469 if (!ExpectedExceptionStream)
470 return ExpectedExceptionStream.
takeError();
472 File.getRawData(ExpectedExceptionStream->ThreadContext);
473 if (!ExpectedThreadContext)
474 return ExpectedThreadContext.
takeError();
475 return std::make_unique<ExceptionStream>(*ExpectedExceptionStream,
476 *ExpectedThreadContext);
478 case StreamKind::MemoryInfoList: {
479 if (
auto ExpectedList = File.getMemoryInfoList())
480 return std::make_unique<MemoryInfoListStream>(*ExpectedList);
482 return ExpectedList.takeError();
484 case StreamKind::MemoryList: {
485 auto ExpectedList = File.getMemoryList();
487 return ExpectedList.takeError();
488 std::vector<MemoryListStream::entry_type> Ranges;
490 auto ExpectedContent = File.getRawData(MD.Memory);
491 if (!ExpectedContent)
492 return ExpectedContent.takeError();
493 Ranges.push_back({MD, *ExpectedContent});
495 return std::make_unique<MemoryListStream>(
std::move(Ranges));
497 case StreamKind::ModuleList: {
498 auto ExpectedList = File.getModuleList();
500 return ExpectedList.takeError();
501 std::vector<ModuleListStream::entry_type> Modules;
502 for (
const Module &
M : *ExpectedList) {
503 auto ExpectedName = File.getString(
M.ModuleNameRVA);
505 return ExpectedName.takeError();
506 auto ExpectedCv = File.getRawData(
M.CvRecord);
508 return ExpectedCv.takeError();
509 auto ExpectedMisc = File.getRawData(
M.MiscRecord);
511 return ExpectedMisc.takeError();
513 {
M,
std::move(*ExpectedName), *ExpectedCv, *ExpectedMisc});
515 return std::make_unique<ModuleListStream>(
std::move(Modules));
517 case StreamKind::RawContent:
518 return std::make_unique<RawContentStream>(StreamDesc.
Type,
519 File.getRawStream(StreamDesc));
520 case StreamKind::SystemInfo: {
521 auto ExpectedInfo = File.getSystemInfo();
523 return ExpectedInfo.takeError();
524 auto ExpectedCSDVersion = File.getString(ExpectedInfo->CSDVersionRVA);
525 if (!ExpectedCSDVersion)
526 return ExpectedInfo.takeError();
527 return std::make_unique<SystemInfoStream>(*ExpectedInfo,
530 case StreamKind::TextContent:
531 return std::make_unique<TextContentStream>(
533 case StreamKind::ThreadList: {
534 auto ExpectedList = File.getThreadList();
536 return ExpectedList.takeError();
537 std::vector<ThreadListStream::entry_type> Threads;
538 for (
const Thread &
T : *ExpectedList) {
539 auto ExpectedStack = File.getRawData(
T.Stack.Memory);
541 return ExpectedStack.takeError();
542 auto ExpectedContext = File.getRawData(
T.Context);
543 if (!ExpectedContext)
544 return ExpectedContext.takeError();
545 Threads.push_back({
T, *ExpectedStack, *ExpectedContext});
547 return std::make_unique<ThreadListStream>(
std::move(Threads));
554 std::vector<std::unique_ptr<Stream>> Streams;
555 Streams.reserve(File.streams().size());
556 for (
const Directory &StreamDesc : File.streams()) {
559 return ExpectedStream.takeError();
560 Streams.push_back(
std::move(*ExpectedStream));