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