@@ -510,6 +510,117 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
510
510
dl_iterate_phdr (dl_iterate_phdr_cb, &data);
511
511
return true ;
512
512
}
513
+
514
+ class DSOMarkupPrinter {
515
+ llvm::raw_ostream &OS;
516
+ const char *MainExecutableName;
517
+ size_t ModuleCount = 0 ;
518
+ bool IsFirst = true ;
519
+
520
+ public:
521
+ DSOMarkupPrinter (llvm::raw_ostream &OS, const char *MainExecutableName)
522
+ : OS(OS), MainExecutableName(MainExecutableName) {}
523
+
524
+ // / Print llvm-symbolizer markup describing the layout of the given DSO.
525
+ void printDSOMarkup (dl_phdr_info *Info) {
526
+ ArrayRef<uint8_t > BuildID = findBuildID (Info);
527
+ if (BuildID.empty ())
528
+ return ;
529
+ OS << format (" {{{module:%d:%s:elf:" , ModuleCount,
530
+ IsFirst ? MainExecutableName : Info->dlpi_name );
531
+ for (uint8_t X : BuildID)
532
+ OS << format (" %02x" , X);
533
+ OS << " }}}\n " ;
534
+
535
+ for (int I = 0 ; I < Info->dlpi_phnum ; I++) {
536
+ const auto *Phdr = &Info->dlpi_phdr [I];
537
+ if (Phdr->p_type != PT_LOAD)
538
+ continue ;
539
+ uintptr_t StartAddress = Info->dlpi_addr + Phdr->p_vaddr ;
540
+ uintptr_t ModuleRelativeAddress = Phdr->p_vaddr ;
541
+ std::array<char , 4 > ModeStr = modeStrFromFlags (Phdr->p_flags );
542
+ OS << format (" {{{mmap:%#016x:%#x:load:%d:%s:%#016x}}}\n " , StartAddress,
543
+ Phdr->p_memsz , ModuleCount, &ModeStr[0 ],
544
+ ModuleRelativeAddress);
545
+ }
546
+ IsFirst = false ;
547
+ ModuleCount++;
548
+ }
549
+
550
+ // / Callback for use with dl_iterate_phdr. The last dl_iterate_phdr argument
551
+ // / must be a pointer to an instance of this class.
552
+ static int printDSOMarkup (dl_phdr_info *Info, size_t Size, void *Arg) {
553
+ static_cast <DSOMarkupPrinter *>(Arg)->printDSOMarkup (Info);
554
+ return 0 ;
555
+ }
556
+
557
+ // Returns the build ID for the given DSO as an array of bytes. Returns an
558
+ // empty array if none could be found.
559
+ ArrayRef<uint8_t > findBuildID (dl_phdr_info *Info) {
560
+ for (int I = 0 ; I < Info->dlpi_phnum ; I++) {
561
+ const auto *Phdr = &Info->dlpi_phdr [I];
562
+ if (Phdr->p_type != PT_NOTE)
563
+ continue ;
564
+
565
+ ArrayRef<uint8_t > Notes (
566
+ reinterpret_cast <const uint8_t *>(Info->dlpi_addr + Phdr->p_vaddr ),
567
+ Phdr->p_memsz );
568
+ while (Notes.size () > 12 ) {
569
+ uint32_t NameSize = *reinterpret_cast <const uint32_t *>(Notes.data ());
570
+ Notes = Notes.drop_front (4 );
571
+ uint32_t DescSize = *reinterpret_cast <const uint32_t *>(Notes.data ());
572
+ Notes = Notes.drop_front (4 );
573
+ uint32_t Type = *reinterpret_cast <const uint32_t *>(Notes.data ());
574
+ Notes = Notes.drop_front (4 );
575
+
576
+ ArrayRef<uint8_t > Name = Notes.take_front (NameSize);
577
+ auto CurPos = reinterpret_cast <uintptr_t >(Notes.data ());
578
+ uint32_t BytesUntilDesc =
579
+ alignToPowerOf2 (CurPos + NameSize, 4 ) - CurPos;
580
+ if (BytesUntilDesc >= Notes.size ())
581
+ break ;
582
+ Notes = Notes.drop_front (BytesUntilDesc);
583
+
584
+ ArrayRef<uint8_t > Desc = Notes.take_front (DescSize);
585
+ CurPos = reinterpret_cast <uintptr_t >(Notes.data ());
586
+ uint32_t BytesUntilNextNote =
587
+ alignToPowerOf2 (CurPos + DescSize, 4 ) - CurPos;
588
+ if (BytesUntilNextNote > Notes.size ())
589
+ break ;
590
+ Notes = Notes.drop_front (BytesUntilNextNote);
591
+
592
+ if (Type == 3 /* NT_GNU_BUILD_ID*/ && Name.size () >= 3 &&
593
+ Name[0 ] == ' G' && Name[1 ] == ' N' && Name[2 ] == ' U' )
594
+ return Desc;
595
+ }
596
+ }
597
+ return {};
598
+ }
599
+
600
+ // Returns a symbolizer markup string describing the permissions on a DSO
601
+ // with the given p_flags.
602
+ std::array<char , 4 > modeStrFromFlags (uint32_t Flags) {
603
+ std::array<char , 4 > Mode;
604
+ char *Cur = &Mode[0 ];
605
+ if (Flags & PF_R)
606
+ *Cur++ = ' r' ;
607
+ if (Flags & PF_W)
608
+ *Cur++ = ' w' ;
609
+ if (Flags & PF_X)
610
+ *Cur++ = ' x' ;
611
+ *Cur = ' \0 ' ;
612
+ return Mode;
613
+ }
614
+ };
615
+
616
+ static bool printMarkupContext (llvm::raw_ostream &OS,
617
+ const char *MainExecutableName) {
618
+ OS << " {{{reset}}}\n " ;
619
+ DSOMarkupPrinter MP (OS, MainExecutableName);
620
+ dl_iterate_phdr (DSOMarkupPrinter::printDSOMarkup, &MP);
621
+ return true ;
622
+ }
623
+
513
624
#elif ENABLE_BACKTRACES && defined(__APPLE__) && defined(__LP64__)
514
625
static bool findModulesAndOffsets (void **StackTrace, int Depth,
515
626
const char **Modules, intptr_t *Offsets,
@@ -544,6 +655,7 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
544
655
}
545
656
return true ;
546
657
}
658
+
547
659
#else
548
660
// / Backtraces are not enabled or we don't yet know how to find all loaded DSOs
549
661
// / on this platform.
@@ -553,6 +665,11 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
553
665
StringSaver &StrPool) {
554
666
return false ;
555
667
}
668
+
669
+ static bool printMarkupContext (llvm::raw_ostream &OS,
670
+ const char *MainExecutableName) {
671
+ return false ;
672
+ }
556
673
#endif // ENABLE_BACKTRACES && ... (findModulesAndOffsets variants)
557
674
558
675
#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
@@ -613,6 +730,8 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
613
730
// backtrace() for printing a symbolized stack trace.
614
731
if (!Depth)
615
732
Depth = depth;
733
+ if (printMarkupStackTrace (Argv0, StackTrace, Depth, OS))
734
+ return ;
616
735
if (printSymbolizedStackTrace (Argv0, StackTrace, Depth, OS))
617
736
return ;
618
737
OS << " Stack dump without symbol names (ensure you have llvm-symbolizer in "
0 commit comments