xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- DWARFLinkerUnit.cpp ------------------------------------------------===//
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 "DWARFLinkerUnit.h"
10 #include "DWARFEmitterImpl.h"
11 #include "DebugLineSectionEmitter.h"
12 
13 using namespace llvm;
14 using namespace dwarf_linker;
15 using namespace dwarf_linker::parallel;
16 
assignAbbrev(DIEAbbrev & Abbrev)17 void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
18   // Check the set for priors.
19   FoldingSetNodeID ID;
20   Abbrev.Profile(ID);
21   void *InsertToken;
22 
23   DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
24   // If it's newly added.
25   if (InSet) {
26     // Assign existing abbreviation number.
27     Abbrev.setNumber(InSet->getNumber());
28   } else {
29     // Add to abbreviation list.
30     Abbreviations.push_back(
31         std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
32     for (const auto &Attr : Abbrev.getData())
33       Abbreviations.back()->AddAttribute(Attr);
34     AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
35     // Assign the unique abbreviation number.
36     Abbrev.setNumber(Abbreviations.size());
37     Abbreviations.back()->setNumber(Abbreviations.size());
38   }
39 }
40 
emitAbbreviations()41 Error DwarfUnit::emitAbbreviations() {
42   const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
43   if (Abbrevs.empty())
44     return Error::success();
45 
46   SectionDescriptor &AbbrevSection =
47       getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);
48 
49   // For each abbreviation.
50   for (const auto &Abbrev : Abbrevs)
51     emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);
52 
53   // Mark end of abbreviations.
54   encodeULEB128(0, AbbrevSection.OS);
55 
56   return Error::success();
57 }
58 
emitDwarfAbbrevEntry(const DIEAbbrev & Abbrev,SectionDescriptor & AbbrevSection)59 void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
60                                      SectionDescriptor &AbbrevSection) {
61   // Emit the abbreviations code (base 1 index.)
62   encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);
63 
64   // Emit the abbreviations data.
65   // Emit its Dwarf tag type.
66   encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);
67 
68   // Emit whether it has children DIEs.
69   encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);
70 
71   // For each attribute description.
72   const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
73   for (const DIEAbbrevData &AttrData : Data) {
74     // Emit attribute type.
75     encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);
76 
77     // Emit form type.
78     encodeULEB128(AttrData.getForm(), AbbrevSection.OS);
79 
80     // Emit value for DW_FORM_implicit_const.
81     if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
82       encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);
83   }
84 
85   // Mark end of abbreviation.
86   encodeULEB128(0, AbbrevSection.OS);
87   encodeULEB128(0, AbbrevSection.OS);
88 }
89 
emitDebugInfo(const Triple & TargetTriple)90 Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
91   DIE *OutUnitDIE = getOutUnitDIE();
92   if (OutUnitDIE == nullptr)
93     return Error::success();
94 
95   // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs
96   // directly.
97 
98   SectionDescriptor &OutSection =
99       getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
100   DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);
101   if (Error Err = Emitter.init(TargetTriple, "__DWARF"))
102     return Err;
103 
104   // Emit compile unit header.
105   Emitter.emitCompileUnitHeader(*this);
106   size_t OffsetToAbbreviationTableOffset =
107       (getFormParams().Version >= 5) ? 8 : 6;
108   OutSection.notePatch(DebugOffsetPatch{
109       OffsetToAbbreviationTableOffset,
110       &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});
111 
112   // Emit DIEs.
113   Emitter.emitDIE(*OutUnitDIE);
114   Emitter.finish();
115 
116   // Set start offset ans size for .debug_info section.
117   OutSection.setSizesForSectionCreatedByAsmPrinter();
118   return Error::success();
119 }
120 
emitDebugLine(const Triple & TargetTriple,const DWARFDebugLine::LineTable & OutLineTable)121 Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,
122                                const DWARFDebugLine::LineTable &OutLineTable) {
123   DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
124 
125   return DebugLineEmitter.emit(OutLineTable);
126 }
127 
emitDebugStringOffsetSection()128 Error DwarfUnit::emitDebugStringOffsetSection() {
129   if (getVersion() < 5)
130     return Error::success();
131 
132   if (DebugStringIndexMap.empty())
133     return Error::success();
134 
135   SectionDescriptor &OutDebugStrOffsetsSection =
136       getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
137 
138   // Emit section header.
139 
140   //   Emit length.
141   OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);
142   uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
143 
144   //   Emit version.
145   OutDebugStrOffsetsSection.emitIntVal(5, 2);
146 
147   //   Emit padding.
148   OutDebugStrOffsetsSection.emitIntVal(0, 2);
149 
150   //   Emit index to offset map.
151   for (const StringEntry *String : DebugStringIndexMap.getValues()) {
152     // Note patch for string offset value.
153     OutDebugStrOffsetsSection.notePatch(
154         DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});
155 
156     // Emit placeholder for offset value.
157     OutDebugStrOffsetsSection.emitOffset(0xBADDEF);
158   }
159 
160   // Patch section length.
161   OutDebugStrOffsetsSection.apply(
162       OffsetAfterSectionLength -
163           OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
164       dwarf::DW_FORM_sec_offset,
165       OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
166 
167   return Error::success();
168 }
169 
170 /// Emit the pubnames or pubtypes section contribution for \p
171 /// Unit into \p Sec. The data is provided in \p Info.
172 std::optional<uint64_t>
emitPubAcceleratorEntry(SectionDescriptor & OutSection,const DwarfUnit::AccelInfo & Info,std::optional<uint64_t> LengthOffset)173 DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
174                                    const DwarfUnit::AccelInfo &Info,
175                                    std::optional<uint64_t> LengthOffset) {
176   if (!LengthOffset) {
177     // Emit the header.
178     OutSection.emitIntVal(0xBADDEF,
179                           getFormParams().getDwarfOffsetByteSize()); // Length
180     LengthOffset = OutSection.OS.tell();
181 
182     OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version
183 
184     OutSection.notePatch(DebugOffsetPatch{
185         OutSection.OS.tell(),
186         &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});
187     OutSection.emitOffset(0xBADDEF); // Unit offset
188 
189     OutSection.emitIntVal(getUnitSize(), 4); // Size
190   }
191   OutSection.emitOffset(Info.OutOffset);
192 
193   // Emit the string itself.
194   OutSection.emitInplaceString(Info.String->first());
195 
196   return LengthOffset;
197 }
198 
199 /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
emitPubAccelerators()200 void DwarfUnit::emitPubAccelerators() {
201   std::optional<uint64_t> NamesLengthOffset;
202   std::optional<uint64_t> TypesLengthOffset;
203 
204   forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
205     if (Info.AvoidForPubSections)
206       return;
207 
208     switch (Info.Type) {
209     case DwarfUnit::AccelType::Name: {
210       NamesLengthOffset = emitPubAcceleratorEntry(
211           getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,
212           NamesLengthOffset);
213     } break;
214     case DwarfUnit::AccelType::Type: {
215       TypesLengthOffset = emitPubAcceleratorEntry(
216           getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,
217           TypesLengthOffset);
218     } break;
219     default: {
220       // Nothing to do.
221     } break;
222     }
223   });
224 
225   if (NamesLengthOffset) {
226     SectionDescriptor &OutSection =
227         getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);
228     OutSection.emitIntVal(0, 4); // End marker.
229 
230     OutSection.apply(*NamesLengthOffset -
231                          OutSection.getFormParams().getDwarfOffsetByteSize(),
232                      dwarf::DW_FORM_sec_offset,
233                      OutSection.OS.tell() - *NamesLengthOffset);
234   }
235 
236   if (TypesLengthOffset) {
237     SectionDescriptor &OutSection =
238         getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);
239     OutSection.emitIntVal(0, 4); // End marker.
240 
241     OutSection.apply(*TypesLengthOffset -
242                          OutSection.getFormParams().getDwarfOffsetByteSize(),
243                      dwarf::DW_FORM_sec_offset,
244                      OutSection.OS.tell() - *TypesLengthOffset);
245   }
246 }
247