@@ -180,6 +180,8 @@ Stream::StreamKind Stream::getKind(StreamType Type) {
180
180
case StreamType::LinuxProcStat:
181
181
case StreamType::LinuxProcUptime:
182
182
return StreamKind::TextContent;
183
+ case StreamType::ThreadList:
184
+ return StreamKind::ThreadList;
183
185
default :
184
186
return StreamKind::RawContent;
185
187
}
@@ -196,6 +198,8 @@ std::unique_ptr<Stream> Stream::create(StreamType Type) {
196
198
return llvm::make_unique<SystemInfoStream>();
197
199
case StreamKind::TextContent:
198
200
return llvm::make_unique<TextContentStream>(Type);
201
+ case StreamKind::ThreadList:
202
+ return llvm::make_unique<ThreadListStream>();
199
203
}
200
204
llvm_unreachable (" Unhandled stream kind!" );
201
205
}
@@ -323,19 +327,19 @@ void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO,
323
327
mapOptionalHex (IO, " File Date Low" , Info.FileDateLow , 0 );
324
328
}
325
329
326
- void yaml::MappingTraits<ModuleListStream::ParsedModule >::mapping(
327
- IO &IO, ModuleListStream::ParsedModule &M) {
328
- mapRequiredHex (IO, " Base of Image" , M.Module .BaseOfImage );
329
- mapRequiredHex (IO, " Size of Image" , M.Module .SizeOfImage );
330
- mapOptionalHex (IO, " Checksum" , M.Module .Checksum , 0 );
331
- IO.mapOptional (" Time Date Stamp" , M.Module .TimeDateStamp ,
330
+ void yaml::MappingTraits<ModuleListStream::entry_type >::mapping(
331
+ IO &IO, ModuleListStream::entry_type &M) {
332
+ mapRequiredHex (IO, " Base of Image" , M.Entry .BaseOfImage );
333
+ mapRequiredHex (IO, " Size of Image" , M.Entry .SizeOfImage );
334
+ mapOptionalHex (IO, " Checksum" , M.Entry .Checksum , 0 );
335
+ IO.mapOptional (" Time Date Stamp" , M.Entry .TimeDateStamp ,
332
336
support::ulittle32_t (0 ));
333
337
IO.mapRequired (" Module Name" , M.Name );
334
- IO.mapOptional (" Version Info" , M.Module .VersionInfo , VSFixedFileInfo ());
338
+ IO.mapOptional (" Version Info" , M.Entry .VersionInfo , VSFixedFileInfo ());
335
339
IO.mapRequired (" CodeView Record" , M.CvRecord );
336
340
IO.mapOptional (" Misc Record" , M.MiscRecord , yaml::BinaryRef ());
337
- mapOptionalHex (IO, " Reserved0" , M.Module .Reserved0 , 0 );
338
- mapOptionalHex (IO, " Reserved1" , M.Module .Reserved1 , 0 );
341
+ mapOptionalHex (IO, " Reserved0" , M.Entry .Reserved0 , 0 );
342
+ mapOptionalHex (IO, " Reserved1" , M.Entry .Reserved1 , 0 );
339
343
}
340
344
341
345
static void streamMapping (yaml::IO &IO, RawContentStream &Stream) {
@@ -350,7 +354,7 @@ static StringRef streamValidate(RawContentStream &Stream) {
350
354
}
351
355
352
356
static void streamMapping (yaml::IO &IO, ModuleListStream &Stream) {
353
- IO.mapRequired (" Modules" , Stream.Modules );
357
+ IO.mapRequired (" Modules" , Stream.Entries );
354
358
}
355
359
356
360
static void streamMapping (yaml::IO &IO, SystemInfoStream &Stream) {
@@ -386,6 +390,27 @@ static void streamMapping(yaml::IO &IO, TextContentStream &Stream) {
386
390
IO.mapOptional (" Text" , Stream.Text );
387
391
}
388
392
393
+ void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
394
+ IO &IO, MemoryDescriptor &Memory, BinaryRef &Content) {
395
+ mapRequiredHex (IO, " Start of Memory Range" , Memory.StartOfMemoryRange );
396
+ IO.mapRequired (" Content" , Content);
397
+ }
398
+
399
+ void yaml::MappingTraits<ThreadListStream::entry_type>::mapping(
400
+ IO &IO, ThreadListStream::entry_type &T) {
401
+ mapRequiredHex (IO, " Thread Id" , T.Entry .ThreadId );
402
+ mapOptionalHex (IO, " Suspend Count" , T.Entry .SuspendCount , 0 );
403
+ mapOptionalHex (IO, " Priority Class" , T.Entry .PriorityClass , 0 );
404
+ mapOptionalHex (IO, " Priority" , T.Entry .Priority , 0 );
405
+ mapOptionalHex (IO, " Environment Block" , T.Entry .EnvironmentBlock , 0 );
406
+ IO.mapRequired (" Context" , T.Context );
407
+ IO.mapRequired (" Stack" , T.Entry .Stack , T.Stack );
408
+ }
409
+
410
+ static void streamMapping (yaml::IO &IO, ThreadListStream &Stream) {
411
+ IO.mapRequired (" Threads" , Stream.Entries );
412
+ }
413
+
389
414
void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
390
415
yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
391
416
StreamType Type;
@@ -408,6 +433,9 @@ void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
408
433
case MinidumpYAML::Stream::StreamKind::TextContent:
409
434
streamMapping (IO, llvm::cast<TextContentStream>(*S));
410
435
break ;
436
+ case MinidumpYAML::Stream::StreamKind::ThreadList:
437
+ streamMapping (IO, llvm::cast<ThreadListStream>(*S));
438
+ break ;
411
439
}
412
440
}
413
441
@@ -419,6 +447,7 @@ StringRef yaml::MappingTraits<std::unique_ptr<Stream>>::validate(
419
447
case MinidumpYAML::Stream::StreamKind::ModuleList:
420
448
case MinidumpYAML::Stream::StreamKind::SystemInfo:
421
449
case MinidumpYAML::Stream::StreamKind::TextContent:
450
+ case MinidumpYAML::Stream::StreamKind::ThreadList:
422
451
return " " ;
423
452
}
424
453
llvm_unreachable (" Fully covered switch above!" );
@@ -432,32 +461,50 @@ void yaml::MappingTraits<Object>::mapping(IO &IO, Object &O) {
432
461
IO.mapRequired (" Streams" , O.Streams );
433
462
}
434
463
464
+ static LocationDescriptor layout (BlobAllocator &File, yaml::BinaryRef Data) {
465
+ return {support::ulittle32_t (Data.binary_size ()),
466
+ support::ulittle32_t (File.allocateBytes (Data))};
467
+ }
468
+
469
+ static void layout (BlobAllocator &File, ModuleListStream::entry_type &M) {
470
+ M.Entry .ModuleNameRVA = File.allocateString (M.Name );
471
+
472
+ M.Entry .CvRecord = layout (File, M.CvRecord );
473
+ M.Entry .MiscRecord = layout (File, M.MiscRecord );
474
+ }
475
+
476
+ static void layout (BlobAllocator &File, ThreadListStream::entry_type &T) {
477
+ T.Entry .Stack .Memory = layout (File, T.Stack );
478
+ T.Entry .Context = layout (File, T.Context );
479
+ }
480
+
481
+ template <typename EntryT>
482
+ static size_t layout (BlobAllocator &File,
483
+ MinidumpYAML::detail::ListStream<EntryT> &S) {
484
+
485
+ File.allocateNewObject <support::ulittle32_t >(S.Entries .size ());
486
+ for (auto &E : S.Entries )
487
+ File.allocateObject (E.Entry );
488
+
489
+ size_t DataEnd = File.tell ();
490
+
491
+ // Lay out the auxiliary data, (which is not a part of the stream).
492
+ DataEnd = File.tell ();
493
+ for (auto &E : S.Entries )
494
+ layout (File, E);
495
+
496
+ return DataEnd;
497
+ }
498
+
435
499
static Directory layout (BlobAllocator &File, Stream &S) {
436
500
Directory Result;
437
501
Result.Type = S.Type ;
438
502
Result.Location .RVA = File.tell ();
439
503
Optional<size_t > DataEnd;
440
504
switch (S.Kind ) {
441
- case Stream::StreamKind::ModuleList: {
442
- ModuleListStream &List = cast<ModuleListStream>(S);
443
-
444
- File.allocateNewObject <support::ulittle32_t >(List.Modules .size ());
445
- for (ModuleListStream::ParsedModule &M : List.Modules )
446
- File.allocateObject (M.Module );
447
-
448
- // Module names and CodeView/Misc records are not a part of the stream.
449
- DataEnd = File.tell ();
450
- for (ModuleListStream::ParsedModule &M : List.Modules ) {
451
- M.Module .ModuleNameRVA = File.allocateString (M.Name );
452
-
453
- M.Module .CvRecord .RVA = File.allocateBytes (M.CvRecord );
454
- M.Module .CvRecord .DataSize = M.CvRecord .binary_size ();
455
-
456
- M.Module .MiscRecord .RVA = File.allocateBytes (M.MiscRecord );
457
- M.Module .MiscRecord .DataSize = M.MiscRecord .binary_size ();
458
- }
505
+ case Stream::StreamKind::ModuleList:
506
+ DataEnd = layout (File, cast<ModuleListStream>(S));
459
507
break ;
460
- }
461
508
case Stream::StreamKind::RawContent: {
462
509
RawContentStream &Raw = cast<RawContentStream>(S);
463
510
File.allocateCallback (Raw.Size , [&Raw](raw_ostream &OS) {
@@ -478,6 +525,9 @@ static Directory layout(BlobAllocator &File, Stream &S) {
478
525
case Stream::StreamKind::TextContent:
479
526
File.allocateArray (arrayRefFromStringRef (cast<TextContentStream>(S).Text ));
480
527
break ;
528
+ case Stream::StreamKind::ThreadList:
529
+ DataEnd = layout (File, cast<ThreadListStream>(S));
530
+ break ;
481
531
}
482
532
// If DataEnd is not set, we assume everything we generated is a part of the
483
533
// stream.
@@ -520,7 +570,7 @@ Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
520
570
auto ExpectedList = File.getModuleList ();
521
571
if (!ExpectedList)
522
572
return ExpectedList.takeError ();
523
- std::vector<ModuleListStream::ParsedModule > Modules;
573
+ std::vector<ModuleListStream::entry_type > Modules;
524
574
for (const Module &M : *ExpectedList) {
525
575
auto ExpectedName = File.getString (M.ModuleNameRVA );
526
576
if (!ExpectedName)
@@ -552,6 +602,22 @@ Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
552
602
case StreamKind::TextContent:
553
603
return llvm::make_unique<TextContentStream>(
554
604
StreamDesc.Type , toStringRef (File.getRawStream (StreamDesc)));
605
+ case StreamKind::ThreadList: {
606
+ auto ExpectedList = File.getThreadList ();
607
+ if (!ExpectedList)
608
+ return ExpectedList.takeError ();
609
+ std::vector<ThreadListStream::entry_type> Threads;
610
+ for (const Thread &T : *ExpectedList) {
611
+ auto ExpectedStack = File.getRawData (T.Stack .Memory );
612
+ if (!ExpectedStack)
613
+ return ExpectedStack.takeError ();
614
+ auto ExpectedContext = File.getRawData (T.Context );
615
+ if (!ExpectedContext)
616
+ return ExpectedContext.takeError ();
617
+ Threads.push_back ({T, *ExpectedStack, *ExpectedContext});
618
+ }
619
+ return llvm::make_unique<ThreadListStream>(std::move (Threads));
620
+ }
555
621
}
556
622
llvm_unreachable (" Unhandled stream kind!" );
557
623
}
0 commit comments