Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ObjectYAML/MinidumpYAML.cpp
35233 views
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
9
#include "llvm/ObjectYAML/MinidumpYAML.h"
10
#include "llvm/Support/Allocator.h"
11
12
using namespace llvm;
13
using namespace llvm::MinidumpYAML;
14
using namespace llvm::minidump;
15
16
/// Perform an optional yaml-mapping of an endian-aware type EndianType. The
17
/// only purpose of this function is to avoid casting the Default value to the
18
/// endian type;
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));
23
}
24
25
/// Yaml-map an endian-aware type EndianType as some other type MapType.
26
template <typename MapType, typename EndianType>
27
static inline void mapRequiredAs(yaml::IO &IO, const char *Key,
28
EndianType &Val) {
29
MapType Mapped = static_cast<typename EndianType::value_type>(Val);
30
IO.mapRequired(Key, Mapped);
31
Val = static_cast<typename EndianType::value_type>(Mapped);
32
}
33
34
/// Perform an optional yaml-mapping of an endian-aware type EndianType as some
35
/// other type MapType.
36
template <typename MapType, typename EndianType>
37
static inline void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val,
38
MapType Default) {
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);
42
}
43
44
namespace {
45
/// Return the appropriate yaml Hex type for a given endian-aware type.
46
template <typename EndianType> struct HexType;
47
template <> struct HexType<support::ulittle16_t> { using type = yaml::Hex16; };
48
template <> struct HexType<support::ulittle32_t> { using type = yaml::Hex32; };
49
template <> struct HexType<support::ulittle64_t> { using type = yaml::Hex64; };
50
} // namespace
51
52
/// Yaml-map an endian-aware type as an appropriately-sized hex value.
53
template <typename EndianType>
54
static inline void mapRequiredHex(yaml::IO &IO, const char *Key,
55
EndianType &Val) {
56
mapRequiredAs<typename HexType<EndianType>::type>(IO, Key, Val);
57
}
58
59
/// Perform an optional yaml-mapping of an endian-aware type as an
60
/// appropriately-sized hex value.
61
template <typename EndianType>
62
static inline void mapOptionalHex(yaml::IO &IO, const char *Key,
63
EndianType &Val,
64
typename EndianType::value_type Default) {
65
mapOptionalAs<typename HexType<EndianType>::type>(IO, Key, Val, Default);
66
}
67
68
Stream::~Stream() = default;
69
70
Stream::StreamKind Stream::getKind(StreamType Type) {
71
switch (Type) {
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;
92
default:
93
return StreamKind::RawContent;
94
}
95
}
96
97
std::unique_ptr<Stream> Stream::create(StreamType Type) {
98
StreamKind Kind = getKind(Type);
99
switch (Kind) {
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>();
116
}
117
llvm_unreachable("Unhandled stream kind!");
118
}
119
120
void yaml::ScalarBitSetTraits<MemoryProtection>::bitset(
121
IO &IO, MemoryProtection &Protect) {
122
#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) \
123
IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);
124
#include "llvm/BinaryFormat/MinidumpConstants.def"
125
}
126
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"
131
}
132
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"
137
}
138
139
void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
140
IO &IO, ProcessorArchitecture &Arch) {
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);
145
}
146
147
void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO,
148
OSPlatform &Plat) {
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);
153
}
154
155
void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO,
156
StreamType &Type) {
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);
161
}
162
163
void yaml::MappingTraits<CPUInfo::ArmInfo>::mapping(IO &IO,
164
CPUInfo::ArmInfo &Info) {
165
mapRequiredHex(IO, "CPUID", Info.CPUID);
166
mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0);
167
}
168
169
namespace {
170
template <std::size_t N> struct FixedSizeHex {
171
FixedSizeHex(uint8_t (&Storage)[N]) : Storage(Storage) {}
172
173
uint8_t (&Storage)[N];
174
};
175
} // namespace
176
177
namespace llvm {
178
namespace yaml {
179
template <std::size_t N> struct ScalarTraits<FixedSizeHex<N>> {
180
static void output(const FixedSizeHex<N> &Fixed, void *, raw_ostream &OS) {
181
OS << toHex(ArrayRef(Fixed.Storage));
182
}
183
184
static StringRef input(StringRef Scalar, void *, FixedSizeHex<N> &Fixed) {
185
if (!all_of(Scalar, isHexDigit))
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";
191
copy(fromHex(Scalar), Fixed.Storage);
192
return "";
193
}
194
195
static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
196
};
197
} // namespace yaml
198
} // namespace llvm
199
void yaml::MappingTraits<CPUInfo::OtherInfo>::mapping(
200
IO &IO, CPUInfo::OtherInfo &Info) {
201
FixedSizeHex<sizeof(Info.ProcessorFeatures)> Features(Info.ProcessorFeatures);
202
IO.mapRequired("Features", Features);
203
}
204
205
namespace {
206
/// A type which only accepts strings of a fixed size for yaml conversion.
207
template <std::size_t N> struct FixedSizeString {
208
FixedSizeString(char (&Storage)[N]) : Storage(Storage) {}
209
210
char (&Storage)[N];
211
};
212
} // namespace
213
214
namespace llvm {
215
namespace yaml {
216
template <std::size_t N> struct ScalarTraits<FixedSizeString<N>> {
217
static void output(const FixedSizeString<N> &Fixed, void *, raw_ostream &OS) {
218
OS << StringRef(Fixed.Storage, N);
219
}
220
221
static StringRef input(StringRef Scalar, void *, FixedSizeString<N> &Fixed) {
222
if (Scalar.size() < N)
223
return "String too short";
224
if (Scalar.size() > N)
225
return "String too long";
226
copy(Scalar, Fixed.Storage);
227
return "";
228
}
229
230
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
231
};
232
} // namespace yaml
233
} // namespace llvm
234
235
void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO,
236
CPUInfo::X86Info &Info) {
237
FixedSizeString<sizeof(Info.VendorID)> VendorID(Info.VendorID);
238
IO.mapRequired("Vendor ID", VendorID);
239
240
mapRequiredHex(IO, "Version Info", Info.VersionInfo);
241
mapRequiredHex(IO, "Feature Info", Info.FeatureInfo);
242
mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);
243
}
244
245
void yaml::MappingTraits<MemoryInfo>::mapping(IO &IO, MemoryInfo &Info) {
246
mapRequiredHex(IO, "Base Address", Info.BaseAddress);
247
mapOptionalHex(IO, "Allocation Base", Info.AllocationBase, Info.BaseAddress);
248
mapRequiredAs<MemoryProtection>(IO, "Allocation Protect",
249
Info.AllocationProtect);
250
mapOptionalHex(IO, "Reserved0", Info.Reserved0, 0);
251
mapRequiredHex(IO, "Region Size", Info.RegionSize);
252
mapRequiredAs<MemoryState>(IO, "State", Info.State);
253
mapOptionalAs<MemoryProtection>(IO, "Protect", Info.Protect,
254
Info.AllocationProtect);
255
mapRequiredAs<MemoryType>(IO, "Type", Info.Type);
256
mapOptionalHex(IO, "Reserved1", Info.Reserved1, 0);
257
}
258
259
void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO,
260
VSFixedFileInfo &Info) {
261
mapOptionalHex(IO, "Signature", Info.Signature, 0);
262
mapOptionalHex(IO, "Struct Version", Info.StructVersion, 0);
263
mapOptionalHex(IO, "File Version High", Info.FileVersionHigh, 0);
264
mapOptionalHex(IO, "File Version Low", Info.FileVersionLow, 0);
265
mapOptionalHex(IO, "Product Version High", Info.ProductVersionHigh, 0);
266
mapOptionalHex(IO, "Product Version Low", Info.ProductVersionLow, 0);
267
mapOptionalHex(IO, "File Flags Mask", Info.FileFlagsMask, 0);
268
mapOptionalHex(IO, "File Flags", Info.FileFlags, 0);
269
mapOptionalHex(IO, "File OS", Info.FileOS, 0);
270
mapOptionalHex(IO, "File Type", Info.FileType, 0);
271
mapOptionalHex(IO, "File Subtype", Info.FileSubtype, 0);
272
mapOptionalHex(IO, "File Date High", Info.FileDateHigh, 0);
273
mapOptionalHex(IO, "File Date Low", Info.FileDateLow, 0);
274
}
275
276
void yaml::MappingTraits<ModuleListStream::entry_type>::mapping(
277
IO &IO, ModuleListStream::entry_type &M) {
278
mapRequiredHex(IO, "Base of Image", M.Entry.BaseOfImage);
279
mapRequiredHex(IO, "Size of Image", M.Entry.SizeOfImage);
280
mapOptionalHex(IO, "Checksum", M.Entry.Checksum, 0);
281
mapOptional(IO, "Time Date Stamp", M.Entry.TimeDateStamp, 0);
282
IO.mapRequired("Module Name", M.Name);
283
IO.mapOptional("Version Info", M.Entry.VersionInfo, VSFixedFileInfo());
284
IO.mapRequired("CodeView Record", M.CvRecord);
285
IO.mapOptional("Misc Record", M.MiscRecord, yaml::BinaryRef());
286
mapOptionalHex(IO, "Reserved0", M.Entry.Reserved0, 0);
287
mapOptionalHex(IO, "Reserved1", M.Entry.Reserved1, 0);
288
}
289
290
static void streamMapping(yaml::IO &IO, RawContentStream &Stream) {
291
IO.mapOptional("Content", Stream.Content);
292
IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size());
293
}
294
295
static std::string streamValidate(RawContentStream &Stream) {
296
if (Stream.Size.value < Stream.Content.binary_size())
297
return "Stream size must be greater or equal to the content size";
298
return "";
299
}
300
301
void yaml::MappingTraits<MemoryListStream::entry_type>::mapping(
302
IO &IO, MemoryListStream::entry_type &Range) {
303
MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
304
IO, Range.Entry, Range.Content);
305
}
306
307
static void streamMapping(yaml::IO &IO, MemoryInfoListStream &Stream) {
308
IO.mapRequired("Memory Ranges", Stream.Infos);
309
}
310
311
static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {
312
IO.mapRequired("Memory Ranges", Stream.Entries);
313
}
314
315
static void streamMapping(yaml::IO &IO, ModuleListStream &Stream) {
316
IO.mapRequired("Modules", Stream.Entries);
317
}
318
319
static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) {
320
SystemInfo &Info = Stream.Info;
321
IO.mapRequired("Processor Arch", Info.ProcessorArch);
322
mapOptional(IO, "Processor Level", Info.ProcessorLevel, 0);
323
mapOptional(IO, "Processor Revision", Info.ProcessorRevision, 0);
324
IO.mapOptional("Number of Processors", Info.NumberOfProcessors, 0);
325
IO.mapOptional("Product type", Info.ProductType, 0);
326
mapOptional(IO, "Major Version", Info.MajorVersion, 0);
327
mapOptional(IO, "Minor Version", Info.MinorVersion, 0);
328
mapOptional(IO, "Build Number", Info.BuildNumber, 0);
329
IO.mapRequired("Platform ID", Info.PlatformId);
330
IO.mapOptional("CSD Version", Stream.CSDVersion, "");
331
mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);
332
mapOptionalHex(IO, "Reserved", Info.Reserved, 0);
333
switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {
334
case ProcessorArchitecture::X86:
335
case ProcessorArchitecture::AMD64:
336
IO.mapOptional("CPU", Info.CPU.X86);
337
break;
338
case ProcessorArchitecture::ARM:
339
case ProcessorArchitecture::ARM64:
340
case ProcessorArchitecture::BP_ARM64:
341
IO.mapOptional("CPU", Info.CPU.Arm);
342
break;
343
default:
344
IO.mapOptional("CPU", Info.CPU.Other);
345
break;
346
}
347
}
348
349
static void streamMapping(yaml::IO &IO, TextContentStream &Stream) {
350
IO.mapOptional("Text", Stream.Text);
351
}
352
353
void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
354
IO &IO, MemoryDescriptor &Memory, BinaryRef &Content) {
355
mapRequiredHex(IO, "Start of Memory Range", Memory.StartOfMemoryRange);
356
IO.mapRequired("Content", Content);
357
}
358
359
void yaml::MappingTraits<ThreadListStream::entry_type>::mapping(
360
IO &IO, ThreadListStream::entry_type &T) {
361
mapRequiredHex(IO, "Thread Id", T.Entry.ThreadId);
362
mapOptionalHex(IO, "Suspend Count", T.Entry.SuspendCount, 0);
363
mapOptionalHex(IO, "Priority Class", T.Entry.PriorityClass, 0);
364
mapOptionalHex(IO, "Priority", T.Entry.Priority, 0);
365
mapOptionalHex(IO, "Environment Block", T.Entry.EnvironmentBlock, 0);
366
IO.mapRequired("Context", T.Context);
367
IO.mapRequired("Stack", T.Entry.Stack, T.Stack);
368
}
369
370
static void streamMapping(yaml::IO &IO, ThreadListStream &Stream) {
371
IO.mapRequired("Threads", Stream.Entries);
372
}
373
374
static void streamMapping(yaml::IO &IO, MinidumpYAML::ExceptionStream &Stream) {
375
mapRequiredHex(IO, "Thread ID", Stream.MDExceptionStream.ThreadId);
376
IO.mapRequired("Exception Record", Stream.MDExceptionStream.ExceptionRecord);
377
IO.mapRequired("Thread Context", Stream.ThreadContext);
378
}
379
380
void yaml::MappingTraits<minidump::Exception>::mapping(
381
yaml::IO &IO, minidump::Exception &Exception) {
382
mapRequiredHex(IO, "Exception Code", Exception.ExceptionCode);
383
mapOptionalHex(IO, "Exception Flags", Exception.ExceptionFlags, 0);
384
mapOptionalHex(IO, "Exception Record", Exception.ExceptionRecord, 0);
385
mapOptionalHex(IO, "Exception Address", Exception.ExceptionAddress, 0);
386
mapOptional(IO, "Number of Parameters", Exception.NumberParameters, 0);
387
388
for (size_t Index = 0; Index < Exception.MaxParameters; ++Index) {
389
SmallString<16> Name("Parameter ");
390
Twine(Index).toVector(Name);
391
support::ulittle64_t &Field = Exception.ExceptionInformation[Index];
392
393
if (Index < Exception.NumberParameters)
394
mapRequiredHex(IO, Name.c_str(), Field);
395
else
396
mapOptionalHex(IO, Name.c_str(), Field, 0);
397
}
398
}
399
400
void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
401
yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
402
StreamType Type;
403
if (IO.outputting())
404
Type = S->Type;
405
IO.mapRequired("Type", Type);
406
407
if (!IO.outputting())
408
S = MinidumpYAML::Stream::create(Type);
409
switch (S->Kind) {
410
case MinidumpYAML::Stream::StreamKind::Exception:
411
streamMapping(IO, llvm::cast<MinidumpYAML::ExceptionStream>(*S));
412
break;
413
case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
414
streamMapping(IO, llvm::cast<MemoryInfoListStream>(*S));
415
break;
416
case MinidumpYAML::Stream::StreamKind::MemoryList:
417
streamMapping(IO, llvm::cast<MemoryListStream>(*S));
418
break;
419
case MinidumpYAML::Stream::StreamKind::ModuleList:
420
streamMapping(IO, llvm::cast<ModuleListStream>(*S));
421
break;
422
case MinidumpYAML::Stream::StreamKind::RawContent:
423
streamMapping(IO, llvm::cast<RawContentStream>(*S));
424
break;
425
case MinidumpYAML::Stream::StreamKind::SystemInfo:
426
streamMapping(IO, llvm::cast<SystemInfoStream>(*S));
427
break;
428
case MinidumpYAML::Stream::StreamKind::TextContent:
429
streamMapping(IO, llvm::cast<TextContentStream>(*S));
430
break;
431
case MinidumpYAML::Stream::StreamKind::ThreadList:
432
streamMapping(IO, llvm::cast<ThreadListStream>(*S));
433
break;
434
}
435
}
436
437
std::string yaml::MappingTraits<std::unique_ptr<Stream>>::validate(
438
yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
439
switch (S->Kind) {
440
case MinidumpYAML::Stream::StreamKind::RawContent:
441
return streamValidate(cast<RawContentStream>(*S));
442
case MinidumpYAML::Stream::StreamKind::Exception:
443
case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
444
case MinidumpYAML::Stream::StreamKind::MemoryList:
445
case MinidumpYAML::Stream::StreamKind::ModuleList:
446
case MinidumpYAML::Stream::StreamKind::SystemInfo:
447
case MinidumpYAML::Stream::StreamKind::TextContent:
448
case MinidumpYAML::Stream::StreamKind::ThreadList:
449
return "";
450
}
451
llvm_unreachable("Fully covered switch above!");
452
}
453
454
void yaml::MappingTraits<Object>::mapping(IO &IO, Object &O) {
455
IO.mapTag("!minidump", true);
456
mapOptionalHex(IO, "Signature", O.Header.Signature, Header::MagicSignature);
457
mapOptionalHex(IO, "Version", O.Header.Version, Header::MagicVersion);
458
mapOptionalHex(IO, "Flags", O.Header.Flags, 0);
459
IO.mapRequired("Streams", O.Streams);
460
}
461
462
Expected<std::unique_ptr<Stream>>
463
Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
464
StreamKind Kind = getKind(StreamDesc.Type);
465
switch (Kind) {
466
case StreamKind::Exception: {
467
Expected<const minidump::ExceptionStream &> ExpectedExceptionStream =
468
File.getExceptionStream();
469
if (!ExpectedExceptionStream)
470
return ExpectedExceptionStream.takeError();
471
Expected<ArrayRef<uint8_t>> ExpectedThreadContext =
472
File.getRawData(ExpectedExceptionStream->ThreadContext);
473
if (!ExpectedThreadContext)
474
return ExpectedThreadContext.takeError();
475
return std::make_unique<ExceptionStream>(*ExpectedExceptionStream,
476
*ExpectedThreadContext);
477
}
478
case StreamKind::MemoryInfoList: {
479
if (auto ExpectedList = File.getMemoryInfoList())
480
return std::make_unique<MemoryInfoListStream>(*ExpectedList);
481
else
482
return ExpectedList.takeError();
483
}
484
case StreamKind::MemoryList: {
485
auto ExpectedList = File.getMemoryList();
486
if (!ExpectedList)
487
return ExpectedList.takeError();
488
std::vector<MemoryListStream::entry_type> Ranges;
489
for (const MemoryDescriptor &MD : *ExpectedList) {
490
auto ExpectedContent = File.getRawData(MD.Memory);
491
if (!ExpectedContent)
492
return ExpectedContent.takeError();
493
Ranges.push_back({MD, *ExpectedContent});
494
}
495
return std::make_unique<MemoryListStream>(std::move(Ranges));
496
}
497
case StreamKind::ModuleList: {
498
auto ExpectedList = File.getModuleList();
499
if (!ExpectedList)
500
return ExpectedList.takeError();
501
std::vector<ModuleListStream::entry_type> Modules;
502
for (const Module &M : *ExpectedList) {
503
auto ExpectedName = File.getString(M.ModuleNameRVA);
504
if (!ExpectedName)
505
return ExpectedName.takeError();
506
auto ExpectedCv = File.getRawData(M.CvRecord);
507
if (!ExpectedCv)
508
return ExpectedCv.takeError();
509
auto ExpectedMisc = File.getRawData(M.MiscRecord);
510
if (!ExpectedMisc)
511
return ExpectedMisc.takeError();
512
Modules.push_back(
513
{M, std::move(*ExpectedName), *ExpectedCv, *ExpectedMisc});
514
}
515
return std::make_unique<ModuleListStream>(std::move(Modules));
516
}
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();
522
if (!ExpectedInfo)
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,
528
std::move(*ExpectedCSDVersion));
529
}
530
case StreamKind::TextContent:
531
return std::make_unique<TextContentStream>(
532
StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc)));
533
case StreamKind::ThreadList: {
534
auto ExpectedList = File.getThreadList();
535
if (!ExpectedList)
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);
540
if (!ExpectedStack)
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});
546
}
547
return std::make_unique<ThreadListStream>(std::move(Threads));
548
}
549
}
550
llvm_unreachable("Unhandled stream kind!");
551
}
552
553
Expected<Object> Object::create(const object::MinidumpFile &File) {
554
std::vector<std::unique_ptr<Stream>> Streams;
555
Streams.reserve(File.streams().size());
556
for (const Directory &StreamDesc : File.streams()) {
557
auto ExpectedStream = Stream::create(StreamDesc, File);
558
if (!ExpectedStream)
559
return ExpectedStream.takeError();
560
Streams.push_back(std::move(*ExpectedStream));
561
}
562
return Object(File.header(), std::move(Streams));
563
}
564
565