1 | //===- DwarfStreamer.h ------------------------------------------*- C++ -*-===// |
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 | #ifndef LLVM_DWARFLINKER_CLASSIC_DWARFSTREAMER_H |
10 | #define LLVM_DWARFLINKER_CLASSIC_DWARFSTREAMER_H |
11 | |
12 | #include "DWARFLinker.h" |
13 | #include "llvm/BinaryFormat/Swift.h" |
14 | #include "llvm/CodeGen/AsmPrinter.h" |
15 | #include "llvm/MC/MCAsmInfo.h" |
16 | #include "llvm/MC/MCContext.h" |
17 | #include "llvm/MC/MCInstrInfo.h" |
18 | #include "llvm/MC/MCObjectFileInfo.h" |
19 | #include "llvm/MC/MCRegisterInfo.h" |
20 | #include "llvm/MC/MCSubtargetInfo.h" |
21 | #include "llvm/Target/TargetMachine.h" |
22 | |
23 | namespace llvm { |
24 | template <typename DataT> class AccelTable; |
25 | |
26 | class MCCodeEmitter; |
27 | class DWARFDebugMacro; |
28 | |
29 | namespace dwarf_linker { |
30 | namespace classic { |
31 | |
32 | /// User of DwarfStreamer should call initialization code |
33 | /// for AsmPrinter: |
34 | /// |
35 | /// InitializeAllTargetInfos(); |
36 | /// InitializeAllTargetMCs(); |
37 | /// InitializeAllTargets(); |
38 | /// InitializeAllAsmPrinters(); |
39 | |
40 | /// The Dwarf streaming logic. |
41 | /// |
42 | /// All interactions with the MC layer that is used to build the debug |
43 | /// information binary representation are handled in this class. |
44 | class DwarfStreamer : public DwarfEmitter { |
45 | public: |
46 | DwarfStreamer(DWARFLinkerBase::OutputFileType OutFileType, |
47 | raw_pwrite_stream &OutFile, |
48 | DWARFLinkerBase::MessageHandlerTy Warning) |
49 | : OutFile(OutFile), OutFileType(OutFileType), WarningHandler(Warning) {} |
50 | virtual ~DwarfStreamer() = default; |
51 | |
52 | static Expected<std::unique_ptr<DwarfStreamer>> createStreamer( |
53 | const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, |
54 | raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning); |
55 | |
56 | Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName); |
57 | |
58 | /// Dump the file to the disk. |
59 | void finish() override; |
60 | |
61 | AsmPrinter &getAsmPrinter() const { return *Asm; } |
62 | |
63 | /// Set the current output section to debug_info and change |
64 | /// the MC Dwarf version to \p DwarfVersion. |
65 | void switchToDebugInfoSection(unsigned DwarfVersion); |
66 | |
67 | /// Emit the compilation unit header for \p Unit in the |
68 | /// debug_info section. |
69 | /// |
70 | /// As a side effect, this also switches the current Dwarf version |
71 | /// of the MC layer to the one of U.getOrigUnit(). |
72 | void (CompileUnit &Unit, unsigned DwarfVersion) override; |
73 | |
74 | /// Recursively emit the DIE tree rooted at \p Die. |
75 | void emitDIE(DIE &Die) override; |
76 | |
77 | /// Emit the abbreviation table \p Abbrevs to the debug_abbrev section. |
78 | void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs, |
79 | unsigned DwarfVersion) override; |
80 | |
81 | /// Emit contents of section SecName From Obj. |
82 | void emitSectionContents(StringRef SecData, |
83 | DebugSectionKind SecKind) override; |
84 | |
85 | /// Emit the string table described by \p Pool into .debug_str table. |
86 | void emitStrings(const NonRelocatableStringpool &Pool) override; |
87 | |
88 | /// Emit the debug string offset table described by \p StringOffsets into the |
89 | /// .debug_str_offsets table. |
90 | void emitStringOffsets(const SmallVector<uint64_t> &StringOffset, |
91 | uint16_t TargetDWARFVersion) override; |
92 | |
93 | /// Emit the string table described by \p Pool into .debug_line_str table. |
94 | void emitLineStrings(const NonRelocatableStringpool &Pool) override; |
95 | |
96 | /// Emit the swift_ast section stored in \p Buffer. |
97 | void emitSwiftAST(StringRef Buffer); |
98 | |
99 | /// Emit the swift reflection section stored in \p Buffer. |
100 | void emitSwiftReflectionSection( |
101 | llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, |
102 | StringRef Buffer, uint32_t Alignment, uint32_t Size); |
103 | |
104 | /// Emit debug ranges(.debug_ranges, .debug_rnglists) header. |
105 | MCSymbol *(const CompileUnit &Unit) override; |
106 | |
107 | /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment. |
108 | void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, |
109 | const AddressRanges &LinkedRanges, |
110 | PatchLocation Patch, |
111 | DebugDieValuePool &AddrPool) override; |
112 | |
113 | /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer. |
114 | void (const CompileUnit &Unit, |
115 | MCSymbol *EndLabel) override; |
116 | |
117 | /// Emit debug locations(.debug_loc, .debug_loclists) header. |
118 | MCSymbol *(const CompileUnit &Unit) override; |
119 | |
120 | /// Emit .debug_addr header. |
121 | MCSymbol *(const CompileUnit &Unit) override; |
122 | |
123 | /// Emit the addresses described by \p Addrs into .debug_addr table. |
124 | void emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs, |
125 | uint8_t AddrSize) override; |
126 | |
127 | /// Emit .debug_addr footer. |
128 | void (const CompileUnit &Unit, |
129 | MCSymbol *EndLabel) override; |
130 | |
131 | /// Emit debug ranges(.debug_loc, .debug_loclists) fragment. |
132 | void emitDwarfDebugLocListFragment( |
133 | const CompileUnit &Unit, |
134 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
135 | PatchLocation Patch, DebugDieValuePool &AddrPool) override; |
136 | |
137 | /// Emit debug ranges(.debug_loc, .debug_loclists) footer. |
138 | void (const CompileUnit &Unit, |
139 | MCSymbol *EndLabel) override; |
140 | |
141 | /// Emit .debug_aranges entries for \p Unit |
142 | void emitDwarfDebugArangesTable(const CompileUnit &Unit, |
143 | const AddressRanges &LinkedRanges) override; |
144 | |
145 | uint64_t getRangesSectionSize() const override { return RangesSectionSize; } |
146 | |
147 | uint64_t getRngListsSectionSize() const override { |
148 | return RngListsSectionSize; |
149 | } |
150 | |
151 | /// Emit .debug_line table entry for specified \p LineTable |
152 | void emitLineTableForUnit(const DWARFDebugLine::LineTable &LineTable, |
153 | const CompileUnit &Unit, |
154 | OffsetsStringPool &DebugStrPool, |
155 | OffsetsStringPool &DebugLineStrPool) override; |
156 | |
157 | uint64_t getLineSectionSize() const override { return LineSectionSize; } |
158 | |
159 | /// Emit the .debug_pubnames contribution for \p Unit. |
160 | void emitPubNamesForUnit(const CompileUnit &Unit) override; |
161 | |
162 | /// Emit the .debug_pubtypes contribution for \p Unit. |
163 | void emitPubTypesForUnit(const CompileUnit &Unit) override; |
164 | |
165 | /// Emit a CIE. |
166 | void emitCIE(StringRef CIEBytes) override; |
167 | |
168 | /// Emit an FDE with data \p Bytes. |
169 | void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, |
170 | StringRef Bytes) override; |
171 | |
172 | /// Emit DWARF debug names. |
173 | void emitDebugNames(DWARF5AccelTable &Table) override; |
174 | |
175 | /// Emit Apple namespaces accelerator table. |
176 | void emitAppleNamespaces( |
177 | AccelTable<AppleAccelTableStaticOffsetData> &Table) override; |
178 | |
179 | /// Emit Apple names accelerator table. |
180 | void |
181 | emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) override; |
182 | |
183 | /// Emit Apple Objective-C accelerator table. |
184 | void |
185 | emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) override; |
186 | |
187 | /// Emit Apple type accelerator table. |
188 | void |
189 | emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) override; |
190 | |
191 | uint64_t getFrameSectionSize() const override { return FrameSectionSize; } |
192 | |
193 | uint64_t getDebugInfoSectionSize() const override { |
194 | return DebugInfoSectionSize; |
195 | } |
196 | |
197 | uint64_t getDebugMacInfoSectionSize() const override { |
198 | return MacInfoSectionSize; |
199 | } |
200 | |
201 | uint64_t getDebugMacroSectionSize() const override { |
202 | return MacroSectionSize; |
203 | } |
204 | |
205 | uint64_t getLocListsSectionSize() const override { |
206 | return LocListsSectionSize; |
207 | } |
208 | |
209 | uint64_t getDebugAddrSectionSize() const override { return AddrSectionSize; } |
210 | |
211 | void emitMacroTables(DWARFContext *Context, |
212 | const Offset2UnitMap &UnitMacroMap, |
213 | OffsetsStringPool &StringPool) override; |
214 | |
215 | private: |
216 | inline void warn(const Twine &Warning, StringRef Context = "" ) { |
217 | if (WarningHandler) |
218 | WarningHandler(Warning, Context, nullptr); |
219 | } |
220 | |
221 | MCSection *getMCSection(DebugSectionKind SecKind); |
222 | |
223 | void emitMacroTableImpl(const DWARFDebugMacro *MacroTable, |
224 | const Offset2UnitMap &UnitMacroMap, |
225 | OffsetsStringPool &StringPool, uint64_t &OutOffset); |
226 | |
227 | /// Emit piece of .debug_ranges for \p LinkedRanges. |
228 | void emitDwarfDebugRangesTableFragment(const CompileUnit &Unit, |
229 | const AddressRanges &LinkedRanges, |
230 | PatchLocation Patch); |
231 | |
232 | /// Emit piece of .debug_rnglists for \p LinkedRanges. |
233 | void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit, |
234 | const AddressRanges &LinkedRanges, |
235 | PatchLocation Patch, |
236 | DebugDieValuePool &AddrPool); |
237 | |
238 | /// Emit piece of .debug_loc for \p LinkedRanges. |
239 | void emitDwarfDebugLocTableFragment( |
240 | const CompileUnit &Unit, |
241 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
242 | PatchLocation Patch); |
243 | |
244 | /// Emit piece of .debug_loclists for \p LinkedRanges. |
245 | void emitDwarfDebugLocListsTableFragment( |
246 | const CompileUnit &Unit, |
247 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
248 | PatchLocation Patch, DebugDieValuePool &AddrPool); |
249 | |
250 | /// \defgroup Line table emission |
251 | /// @{ |
252 | void emitLineTablePrologue(const DWARFDebugLine::Prologue &P, |
253 | OffsetsStringPool &DebugStrPool, |
254 | OffsetsStringPool &DebugLineStrPool); |
255 | void emitLineTableString(const DWARFDebugLine::Prologue &P, |
256 | const DWARFFormValue &String, |
257 | OffsetsStringPool &DebugStrPool, |
258 | OffsetsStringPool &DebugLineStrPool); |
259 | void emitLineTableProloguePayload(const DWARFDebugLine::Prologue &P, |
260 | OffsetsStringPool &DebugStrPool, |
261 | OffsetsStringPool &DebugLineStrPool); |
262 | void emitLineTablePrologueV2IncludeAndFileTable( |
263 | const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, |
264 | OffsetsStringPool &DebugLineStrPool); |
265 | void emitLineTablePrologueV5IncludeAndFileTable( |
266 | const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, |
267 | OffsetsStringPool &DebugLineStrPool); |
268 | void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable, |
269 | MCSymbol *LineEndSym, unsigned AddressByteSize); |
270 | void emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format, |
271 | uint64_t &SectionSize); |
272 | void emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, |
273 | dwarf::DwarfFormat Format, uint64_t &SectionSize); |
274 | /// @} |
275 | |
276 | /// \defgroup MCObjects MC layer objects constructed by the streamer |
277 | /// @{ |
278 | std::unique_ptr<MCRegisterInfo> MRI; |
279 | std::unique_ptr<MCAsmInfo> MAI; |
280 | std::unique_ptr<MCObjectFileInfo> MOFI; |
281 | std::unique_ptr<MCContext> MC; |
282 | MCAsmBackend *MAB; // Owned by MCStreamer |
283 | std::unique_ptr<MCInstrInfo> MII; |
284 | std::unique_ptr<MCSubtargetInfo> MSTI; |
285 | MCInstPrinter *MIP; // Owned by AsmPrinter |
286 | MCCodeEmitter *MCE; // Owned by MCStreamer |
287 | MCStreamer *MS; // Owned by AsmPrinter |
288 | std::unique_ptr<TargetMachine> TM; |
289 | std::unique_ptr<AsmPrinter> Asm; |
290 | /// @} |
291 | |
292 | /// The output file we stream the linked Dwarf to. |
293 | raw_pwrite_stream &OutFile; |
294 | DWARFLinker::OutputFileType OutFileType = DWARFLinker::OutputFileType::Object; |
295 | |
296 | uint64_t RangesSectionSize = 0; |
297 | uint64_t RngListsSectionSize = 0; |
298 | uint64_t LocSectionSize = 0; |
299 | uint64_t LocListsSectionSize = 0; |
300 | uint64_t LineSectionSize = 0; |
301 | uint64_t FrameSectionSize = 0; |
302 | uint64_t DebugInfoSectionSize = 0; |
303 | uint64_t MacInfoSectionSize = 0; |
304 | uint64_t MacroSectionSize = 0; |
305 | uint64_t AddrSectionSize = 0; |
306 | uint64_t StrOffsetSectionSize = 0; |
307 | |
308 | /// Keep track of emitted CUs and their Unique ID. |
309 | struct EmittedUnit { |
310 | unsigned ID; |
311 | MCSymbol *LabelBegin; |
312 | }; |
313 | std::vector<EmittedUnit> EmittedUnits; |
314 | |
315 | /// Emit the pubnames or pubtypes section contribution for \p |
316 | /// Unit into \p Sec. The data is provided in \p Names. |
317 | void emitPubSectionForUnit(MCSection *Sec, StringRef Name, |
318 | const CompileUnit &Unit, |
319 | const std::vector<CompileUnit::AccelInfo> &Names); |
320 | |
321 | DWARFLinkerBase::MessageHandlerTy WarningHandler = nullptr; |
322 | }; |
323 | |
324 | } // end of namespace classic |
325 | } // end of namespace dwarf_linker |
326 | } // end of namespace llvm |
327 | |
328 | #endif // LLVM_DWARFLINKER_CLASSIC_DWARFSTREAMER_H |
329 | |