@@ -691,6 +691,194 @@ Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
691
691
return Error::success ();
692
692
}
693
693
694
+ namespace {
695
+ // / Emits the header for a DebugNames section.
696
+ void emitDebugNamesHeader (raw_ostream &OS, bool IsLittleEndian,
697
+ uint32_t NameCount, uint32_t AbbrevSize,
698
+ uint32_t CombinedSizeOtherParts) {
699
+ // Use the same AugmentationString as AsmPrinter.
700
+ StringRef AugmentationString = " LLVM0700" ;
701
+ size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof (uint32_t ) +
702
+ 2 * sizeof (uint16_t ) + sizeof (NameCount) +
703
+ sizeof (AbbrevSize) + AugmentationString.size ();
704
+ writeInteger (uint32_t (TotalSize), OS, IsLittleEndian); // Unit length
705
+
706
+ // Everything below is included in total size.
707
+ writeInteger (uint16_t (5 ), OS, IsLittleEndian); // Version
708
+ writeInteger (uint16_t (0 ), OS, IsLittleEndian); // Padding
709
+ writeInteger (uint32_t (1 ), OS, IsLittleEndian); // Compilation Unit count
710
+ writeInteger (uint32_t (0 ), OS, IsLittleEndian); // Local Type Unit count
711
+ writeInteger (uint32_t (0 ), OS, IsLittleEndian); // Foreign Type Unit count
712
+ writeInteger (uint32_t (0 ), OS, IsLittleEndian); // Bucket count
713
+ writeInteger (NameCount, OS, IsLittleEndian);
714
+ writeInteger (AbbrevSize, OS, IsLittleEndian);
715
+ writeInteger (uint32_t (AugmentationString.size ()), OS, IsLittleEndian);
716
+ OS.write (AugmentationString.data (), AugmentationString.size ());
717
+ return ;
718
+ }
719
+
720
+ // / Emits the abbreviations for a DebugNames section.
721
+ std::string
722
+ emitDebugNamesAbbrev (ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
723
+ std::string Data;
724
+ raw_string_ostream OS (Data);
725
+ for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
726
+ encodeULEB128 (Abbrev.Code , OS);
727
+ encodeULEB128 (Abbrev.Tag , OS);
728
+ for (auto [Idx, Form] : Abbrev.Indices ) {
729
+ encodeULEB128 (Idx, OS);
730
+ encodeULEB128 (Form, OS);
731
+ }
732
+ encodeULEB128 (0 , OS);
733
+ encodeULEB128 (0 , OS);
734
+ }
735
+ encodeULEB128 (0 , OS);
736
+ return Data;
737
+ }
738
+
739
+ // / Emits a simple CU offsets list for a DebugNames section containing a single
740
+ // / CU at offset 0.
741
+ std::string emitDebugNamesCUOffsets (bool IsLittleEndian) {
742
+ std::string Data;
743
+ raw_string_ostream OS (Data);
744
+ writeInteger (uint32_t (0 ), OS, IsLittleEndian);
745
+ return Data;
746
+ }
747
+
748
+ // / Emits the "NameTable" for a DebugNames section; according to the spec, it
749
+ // / consists of two arrays: an array of string offsets, followed immediately by
750
+ // / an array of entry offsets. The string offsets are emitted in the order
751
+ // / provided in `Entries`.
752
+ std::string emitDebugNamesNameTable (
753
+ bool IsLittleEndian,
754
+ const DenseMap<uint32_t , std::vector<DWARFYAML::DebugNameEntry>> &Entries,
755
+ ArrayRef<uint32_t > EntryPoolOffsets) {
756
+ assert (Entries.size () == EntryPoolOffsets.size ());
757
+
758
+ std::string Data;
759
+ raw_string_ostream OS (Data);
760
+
761
+ for (uint32_t Strp : make_first_range (Entries))
762
+ writeInteger (Strp, OS, IsLittleEndian);
763
+ for (uint32_t PoolOffset : EntryPoolOffsets)
764
+ writeInteger (PoolOffset, OS, IsLittleEndian);
765
+ return Data;
766
+ }
767
+
768
+ // / Groups entries based on their name (strp) code and returns a map.
769
+ DenseMap<uint32_t , std::vector<DWARFYAML::DebugNameEntry>>
770
+ groupEntries (ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
771
+ DenseMap<uint32_t , std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
772
+ for (const DWARFYAML::DebugNameEntry &Entry : Entries)
773
+ StrpToEntries[Entry.NameStrp ].push_back (Entry);
774
+ return StrpToEntries;
775
+ }
776
+
777
+ // / Finds the abbreviation whose code is AbbrevCode and returns a list
778
+ // / containing the expected size of all non-zero-length forms.
779
+ Expected<SmallVector<uint8_t >>
780
+ getNonZeroDataSizesFor (uint32_t AbbrevCode,
781
+ ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
782
+ const auto *AbbrevIt = find_if (Abbrevs, [&](const auto &Abbrev) {
783
+ return Abbrev.Code .value == AbbrevCode;
784
+ });
785
+ if (AbbrevIt == Abbrevs.end ())
786
+ return createStringError (inconvertibleErrorCode (),
787
+ " did not find an Abbreviation for this code" );
788
+
789
+ SmallVector<uint8_t > DataSizes;
790
+ dwarf::FormParams Params{/* Version=*/ 5 , /* AddrSize=*/ 4 , dwarf::DWARF32};
791
+ for (auto [Idx, Form] : AbbrevIt->Indices ) {
792
+ std::optional<uint8_t > FormSize = dwarf::getFixedFormByteSize (Form, Params);
793
+ if (!FormSize)
794
+ return createStringError (inconvertibleErrorCode (),
795
+ " unsupported Form for YAML debug_names emitter" );
796
+ if (FormSize == 0 )
797
+ continue ;
798
+ DataSizes.push_back (*FormSize);
799
+ }
800
+ return DataSizes;
801
+ }
802
+
803
+ struct PoolOffsetsAndData {
804
+ std::string PoolData;
805
+ std::vector<uint32_t > PoolOffsets;
806
+ };
807
+
808
+ // / Emits the entry pool and returns an array of offsets containing the start
809
+ // / offset for the entries of each unique name.
810
+ // / Verifies that the provided number of data values match those expected by
811
+ // / the abbreviation table.
812
+ Expected<PoolOffsetsAndData> emitDebugNamesEntryPool (
813
+ bool IsLittleEndian,
814
+ const DenseMap<uint32_t , std::vector<DWARFYAML::DebugNameEntry>>
815
+ &StrpToEntries,
816
+ ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
817
+ PoolOffsetsAndData Result;
818
+ raw_string_ostream OS (Result.PoolData );
819
+
820
+ for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
821
+ make_second_range (StrpToEntries)) {
822
+ Result.PoolOffsets .push_back (Result.PoolData .size ());
823
+
824
+ for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
825
+ encodeULEB128 (Entry.Code , OS);
826
+
827
+ Expected<SmallVector<uint8_t >> DataSizes =
828
+ getNonZeroDataSizesFor (Entry.Code , Abbrevs);
829
+ if (!DataSizes)
830
+ return DataSizes.takeError ();
831
+ if (DataSizes->size () != Entry.Values .size ())
832
+ return createStringError (
833
+ inconvertibleErrorCode (),
834
+ " mismatch between provided and required number of values" );
835
+
836
+ for (auto [Value, ValueSize] : zip_equal (Entry.Values , *DataSizes))
837
+ if (Error E =
838
+ writeVariableSizedInteger (Value, ValueSize, OS, IsLittleEndian))
839
+ return std::move (E);
840
+ }
841
+ encodeULEB128 (0 , OS);
842
+ }
843
+
844
+ return Result;
845
+ }
846
+ } // namespace
847
+
848
+ Error DWARFYAML::emitDebugNames (raw_ostream &OS, const Data &DI) {
849
+ assert (DI.DebugNames && " unexpected emitDebugNames() call" );
850
+ const DebugNamesSection DebugNames = DI.DebugNames .value ();
851
+
852
+ DenseMap<uint32_t , std::vector<DebugNameEntry>> StrpToEntries =
853
+ groupEntries (DebugNames.Entries );
854
+
855
+ // Emit all sub-sections into individual strings so that we may compute
856
+ // relative offsets and sizes.
857
+ Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool (
858
+ DI.IsLittleEndian , StrpToEntries, DebugNames.Abbrevs );
859
+ if (!PoolInfo)
860
+ return PoolInfo.takeError ();
861
+ std::string NamesTableData = emitDebugNamesNameTable (
862
+ DI.IsLittleEndian , StrpToEntries, PoolInfo->PoolOffsets );
863
+
864
+ std::string AbbrevData = emitDebugNamesAbbrev (DebugNames.Abbrevs );
865
+ std::string CUOffsetsData = emitDebugNamesCUOffsets (DI.IsLittleEndian );
866
+
867
+ size_t TotalSize = PoolInfo->PoolData .size () + NamesTableData.size () +
868
+ AbbrevData.size () + CUOffsetsData.size ();
869
+
870
+ // Start real emission by combining all individual strings.
871
+ emitDebugNamesHeader (OS, DI.IsLittleEndian , StrpToEntries.size (),
872
+ AbbrevData.size (), TotalSize);
873
+ OS.write (CUOffsetsData.data (), CUOffsetsData.size ());
874
+ // No local TUs, no foreign TUs, no hash lookups table.
875
+ OS.write (NamesTableData.data (), NamesTableData.size ());
876
+ OS.write (AbbrevData.data (), AbbrevData.size ());
877
+ OS.write (PoolInfo->PoolData .data (), PoolInfo->PoolData .size ());
878
+
879
+ return Error::success ();
880
+ }
881
+
694
882
static Error checkOperandCount (StringRef EncodingString,
695
883
ArrayRef<yaml::Hex64> Values,
696
884
uint64_t ExpectedOperands) {
@@ -1024,6 +1212,7 @@ DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
1024
1212
.Case (" debug_rnglists" , DWARFYAML::emitDebugRnglists)
1025
1213
.Case (" debug_str" , DWARFYAML::emitDebugStr)
1026
1214
.Case (" debug_str_offsets" , DWARFYAML::emitDebugStrOffsets)
1215
+ .Case (" debug_names" , DWARFYAML::emitDebugNames)
1027
1216
.Default ([&](raw_ostream &, const DWARFYAML::Data &) {
1028
1217
return createStringError (errc::not_supported,
1029
1218
SecName + " is not supported" );
0 commit comments