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_DWARFSTREAMER_H
10 #define LLVM_DWARFLINKER_DWARFSTREAMER_H
11 
12 #include "llvm/BinaryFormat/Swift.h"
13 #include "llvm/CodeGen/AsmPrinter.h"
14 #include "llvm/DWARFLinker/DWARFLinker.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 enum class OutputFileType {
27   Object,
28   Assembly,
29 };
30 
31 ///   User of DwarfStreamer should call initialization code
32 ///   for AsmPrinter:
33 ///
34 ///   InitializeAllTargetInfos();
35 ///   InitializeAllTargetMCs();
36 ///   InitializeAllTargets();
37 ///   InitializeAllAsmPrinters();
38 
39 class MCCodeEmitter;
40 class DWARFDebugMacro;
41 
42 /// The Dwarf streaming logic.
43 ///
44 /// All interactions with the MC layer that is used to build the debug
45 /// information binary representation are handled in this class.
46 class DwarfStreamer : public DwarfEmitter {
47 public:
DwarfStreamer(OutputFileType OutFileType,raw_pwrite_stream & OutFile,std::function<StringRef (StringRef Input)> Translator,messageHandler Error,messageHandler Warning)48   DwarfStreamer(OutputFileType OutFileType, raw_pwrite_stream &OutFile,
49                 std::function<StringRef(StringRef Input)> Translator,
50                 messageHandler Error, messageHandler Warning)
51       : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator),
52         ErrorHandler(Error), WarningHandler(Warning) {}
53 
54   bool init(Triple TheTriple, StringRef Swift5ReflectionSegmentName);
55 
56   /// Dump the file to the disk.
57   void finish();
58 
getAsmPrinter()59   AsmPrinter &getAsmPrinter() const { return *Asm; }
60 
61   /// Set the current output section to debug_info and change
62   /// the MC Dwarf version to \p DwarfVersion.
63   void switchToDebugInfoSection(unsigned DwarfVersion);
64 
65   /// Emit the compilation unit header for \p Unit in the
66   /// debug_info section.
67   ///
68   /// As a side effect, this also switches the current Dwarf version
69   /// of the MC layer to the one of U.getOrigUnit().
70   void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion) override;
71 
72   /// Recursively emit the DIE tree rooted at \p Die.
73   void emitDIE(DIE &Die) override;
74 
75   /// Emit the abbreviation table \p Abbrevs to the debug_abbrev section.
76   void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
77                    unsigned DwarfVersion) override;
78 
79   /// Emit DIE containing warnings.
80   void emitPaperTrailWarningsDie(DIE &Die) override;
81 
82   /// Emit contents of section SecName From Obj.
83   void emitSectionContents(StringRef SecData, StringRef SecName) override;
84 
85   /// Emit the string table described by \p Pool.
86   void emitStrings(const NonRelocatableStringpool &Pool) override;
87 
88   /// Emit the swift_ast section stored in \p Buffer.
89   void emitSwiftAST(StringRef Buffer);
90 
91   /// Emit the swift reflection section stored in \p Buffer.
92   void emitSwiftReflectionSection(
93       llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
94       StringRef Buffer, uint32_t Alignment, uint32_t Size);
95 
96   /// Emit piece of .debug_ranges for \p Ranges.
97   virtual void
98   emitDwarfDebugRangesTableFragment(const CompileUnit &Unit,
99                                     const AddressRanges &LinkedRanges) override;
100 
101   /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
102   /// also emit the debug_ranges entries for the DW_TAG_compile_unit's
103   /// DW_AT_ranges attribute.
104   void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection) override;
105 
getRangesSectionSize()106   uint64_t getRangesSectionSize() const override { return RangesSectionSize; }
107 
108   /// Emit the debug_loc contribution for \p Unit by copying the entries from
109   /// \p Dwarf and offsetting them. Update the location attributes to point to
110   /// the new entries.
111   void emitLocationsForUnit(
112       const CompileUnit &Unit, DWARFContext &Dwarf,
113       std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr)
114       override;
115 
116   /// Emit the line table described in \p Rows into the debug_line section.
117   void emitLineTableForUnit(MCDwarfLineTableParams Params,
118                             StringRef PrologueBytes, unsigned MinInstLength,
119                             std::vector<DWARFDebugLine::Row> &Rows,
120                             unsigned AdddressSize) override;
121 
122   /// Copy the debug_line over to the updated binary while unobfuscating the
123   /// file names and directories.
124   void translateLineTable(DataExtractor LineData, uint64_t Offset) override;
125 
getLineSectionSize()126   uint64_t getLineSectionSize() const override { return LineSectionSize; }
127 
128   /// Emit the .debug_pubnames contribution for \p Unit.
129   void emitPubNamesForUnit(const CompileUnit &Unit) override;
130 
131   /// Emit the .debug_pubtypes contribution for \p Unit.
132   void emitPubTypesForUnit(const CompileUnit &Unit) override;
133 
134   /// Emit a CIE.
135   void emitCIE(StringRef CIEBytes) override;
136 
137   /// Emit an FDE with data \p Bytes.
138   void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address,
139                StringRef Bytes) override;
140 
141   /// Emit DWARF debug names.
142   void emitDebugNames(AccelTable<DWARF5AccelTableStaticData> &Table) override;
143 
144   /// Emit Apple namespaces accelerator table.
145   void emitAppleNamespaces(
146       AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
147 
148   /// Emit Apple names accelerator table.
149   void
150   emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
151 
152   /// Emit Apple Objective-C accelerator table.
153   void
154   emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
155 
156   /// Emit Apple type accelerator table.
157   void
158   emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) override;
159 
getFrameSectionSize()160   uint64_t getFrameSectionSize() const override { return FrameSectionSize; }
161 
getDebugInfoSectionSize()162   uint64_t getDebugInfoSectionSize() const override {
163     return DebugInfoSectionSize;
164   }
165 
getDebugMacInfoSectionSize()166   uint64_t getDebugMacInfoSectionSize() const override {
167     return MacInfoSectionSize;
168   }
169 
getDebugMacroSectionSize()170   uint64_t getDebugMacroSectionSize() const override {
171     return MacroSectionSize;
172   }
173 
174   void emitMacroTables(DWARFContext *Context,
175                        const Offset2UnitMap &UnitMacroMap,
176                        OffsetsStringPool &StringPool) override;
177 
178 private:
179   inline void error(const Twine &Error, StringRef Context = "") {
180     if (ErrorHandler)
181       ErrorHandler(Error, Context, nullptr);
182   }
183 
184   inline void warn(const Twine &Warning, StringRef Context = "") {
185     if (WarningHandler)
186       WarningHandler(Warning, Context, nullptr);
187   }
188 
189   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
190                           const Offset2UnitMap &UnitMacroMap,
191                           OffsetsStringPool &StringPool, uint64_t &OutOffset);
192   void emitDwarfDebugArangesTable(const CompileUnit &Unit,
193                                   const AddressRanges &LinkedRanges);
194 
195   /// \defgroup MCObjects MC layer objects constructed by the streamer
196   /// @{
197   std::unique_ptr<MCRegisterInfo> MRI;
198   std::unique_ptr<MCAsmInfo> MAI;
199   std::unique_ptr<MCObjectFileInfo> MOFI;
200   std::unique_ptr<MCContext> MC;
201   MCAsmBackend *MAB; // Owned by MCStreamer
202   std::unique_ptr<MCInstrInfo> MII;
203   std::unique_ptr<MCSubtargetInfo> MSTI;
204   MCInstPrinter *MIP; // Owned by AsmPrinter
205   MCCodeEmitter *MCE; // Owned by MCStreamer
206   MCStreamer *MS;     // Owned by AsmPrinter
207   std::unique_ptr<TargetMachine> TM;
208   std::unique_ptr<AsmPrinter> Asm;
209   /// @}
210 
211   /// The output file we stream the linked Dwarf to.
212   raw_pwrite_stream &OutFile;
213   OutputFileType OutFileType = OutputFileType::Object;
214   std::function<StringRef(StringRef Input)> Translator;
215 
216   uint64_t RangesSectionSize = 0;
217   uint64_t LocSectionSize = 0;
218   uint64_t LineSectionSize = 0;
219   uint64_t FrameSectionSize = 0;
220   uint64_t DebugInfoSectionSize = 0;
221   uint64_t MacInfoSectionSize = 0;
222   uint64_t MacroSectionSize = 0;
223 
224   /// Keep track of emitted CUs and their Unique ID.
225   struct EmittedUnit {
226     unsigned ID;
227     MCSymbol *LabelBegin;
228   };
229   std::vector<EmittedUnit> EmittedUnits;
230 
231   /// Emit the pubnames or pubtypes section contribution for \p
232   /// Unit into \p Sec. The data is provided in \p Names.
233   void emitPubSectionForUnit(MCSection *Sec, StringRef Name,
234                              const CompileUnit &Unit,
235                              const std::vector<CompileUnit::AccelInfo> &Names);
236 
237   messageHandler ErrorHandler = nullptr;
238   messageHandler WarningHandler = nullptr;
239 };
240 
241 } // end namespace llvm
242 
243 #endif // LLVM_DWARFLINKER_DWARFSTREAMER_H
244