1 //===- DWARFLinker.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_DWARFLINKERPARALLEL_DWARFLINKER_H
10 #define LLVM_DWARFLINKERPARALLEL_DWARFLINKER_H
11 
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/DWARFLinkerParallel/DWARFFile.h"
14 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
16 #include "llvm/MC/MCDwarf.h"
17 #include "llvm/TargetParser/Triple.h"
18 
19 /// ------------------------------------------------------------------
20 /// The core of the Dwarf linking logic.
21 ///
22 /// The generation of the dwarf information from the object files will be
23 /// driven by the selection of 'root DIEs', which are DIEs that
24 /// describe variables or functions that resolves to the corresponding
25 /// code section(and thus have entries in the Addresses map). All the debug
26 /// information that will be generated(the DIEs, but also the line
27 /// tables, ranges, ...) is derived from that set of root DIEs.
28 ///
29 /// The root DIEs are identified because they contain relocations that
30 /// points to code section(the low_pc for a function, the location for
31 /// a variable). These relocations are gathered as a very first step
32 /// when we start processing a object file by AddressesMap.
33 ///
34 /// The overall linking process looks like this:
35 ///
36 /// parrallel_for_each(ObjectFile) {
37 ///   for_each (Compile Unit) {
38 ///     1. Load Clang modules.
39 ///   }
40 ///
41 ///   parrallel_for_each(Compile Unit) {
42 ///     1. Load input DWARF for Compile Unit.
43 ///     2. Report warnings for Clang modules.
44 ///     3. Analyze live DIEs and type names(if ODR deduplication is requested).
45 ///     4. Clone DIEs(Generate output DIEs and resulting DWARF tables).
46 ///        The result is in an OutDebugInfoBytes, which is an ELF file
47 ///        containing DWARF tables corresponding to the current compile unit.
48 ///     5. Cleanup Input and Output DIEs.
49 ///   }
50 ///
51 ///   Deallocate loaded Object file.
52 /// }
53 ///
54 /// if (ODR deduplication is requested)
55 ///   Generate an artificial compilation unit ("Type Table": used to partially
56 ///   generate DIEs at the clone stage).
57 ///
58 /// for_each (ObjectFile) {
59 ///   for_each (Compile Unit) {
60 ///     1. Set offsets to Compile Units DWARF tables.
61 ///     2. Sort offsets/attributes/patches to have a predictable result.
62 ///     3. Patch size/offsets fields.
63 ///     4. Generate index tables.
64 ///     5. Move DWARF tables of compile units into the resulting file.
65 ///   }
66 /// }
67 ///
68 /// Every compile unit is processed separately, visited only once
69 /// (except case inter-CU references exist), and used data is freed
70 /// after the compile unit is processed. The resulting file is glued together
71 /// from the generated debug tables which correspond to separate compile units.
72 ///
73 /// Handling inter-CU references: inter-CU references are hard to process
74 /// using only one pass. f.e. if CU1 references CU100 and CU100 references
75 /// CU1, we could not finish handling of CU1 until we finished CU100.
76 /// Thus we either need to load all CUs into the memory, either load CUs several
77 /// times. This implementation loads inter-connected CU into memory at the first
78 /// pass and processes them at the second pass.
79 ///
80 /// ODR deduplication: Artificial compilation unit will be constructed to keep
81 /// type dies. All types are moved into that compilation unit. Type's references
82 /// are patched so that they point to the corresponding types from artificial
83 /// compilation unit. All partial type definitions would be merged into single
84 /// type definition.
85 ///
86 
87 namespace llvm {
88 namespace dwarflinker_parallel {
89 
90 /// ExtraDwarfEmitter allows adding extra data to the DWARFLinker output.
91 /// The finish() method should be called after all extra data are emitted.
92 class ExtraDwarfEmitter {
93 public:
94   virtual ~ExtraDwarfEmitter() = default;
95 
96   /// Dump the file to the disk.
97   virtual void finish() = 0;
98 
99   /// Emit section named SecName with data SecData.
100   virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0;
101 
102   /// Emit the swift_ast section stored in \p Buffer.
103   virtual void emitSwiftAST(StringRef Buffer) = 0;
104 
105   /// Emit the swift reflection section stored in \p Buffer.
106   virtual void emitSwiftReflectionSection(
107       llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
108       StringRef Buffer, uint32_t Alignment, uint32_t Size) = 0;
109 
110   /// Returns underlying AsmPrinter.
111   virtual AsmPrinter &getAsmPrinter() const = 0;
112 };
113 
114 class DWARFLinker {
115 public:
116   /// Type of output file.
117   enum class OutputFileType {
118     Object,
119     Assembly,
120   };
121 
122   /// The kind of accelerator tables we should emit.
123   enum class AccelTableKind : uint8_t {
124     Apple,     ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
125     Pub,       ///< .debug_pubnames, .debug_pubtypes
126     DebugNames ///< .debug_names.
127   };
128 
129   using MessageHandlerTy = std::function<void(
130       const Twine &Warning, StringRef Context, const DWARFDie *DIE)>;
131   using ObjFileLoaderTy = std::function<ErrorOr<DWARFFile &>(
132       StringRef ContainerName, StringRef Path)>;
133   using InputVerificationHandlerTy = std::function<void(const DWARFFile &File, llvm::StringRef Output)>;
134   using ObjectPrefixMapTy = std::map<std::string, std::string>;
135   using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>;
136   using TranslatorFuncTy = std::function<StringRef(StringRef)>;
137   using SwiftInterfacesMapTy = std::map<std::string, std::string>;
138 
139   virtual ~DWARFLinker() = default;
140 
141   /// Creates dwarf linker instance.
142   static std::unique_ptr<DWARFLinker>
143   createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
144                TranslatorFuncTy StringsTranslator = nullptr);
145 
146   /// Creates emitter for output dwarf.
147   virtual Error createEmitter(const Triple &TheTriple, OutputFileType FileType,
148                               raw_pwrite_stream &OutFile) = 0;
149 
150   /// Returns previously created dwarf emitter. May be nullptr.
151   virtual ExtraDwarfEmitter *getEmitter() = 0;
152 
153   /// Add object file to be linked. Pre-load compile unit die. Call
154   /// \p OnCUDieLoaded for each compile unit die. If specified \p File
155   /// has reference to the Clang module then such module would be
156   /// pre-loaded by \p Loader for !Update case.
157   ///
158   /// \pre NoODR, Update options should be set before call to addObjectFile.
159   virtual void addObjectFile(
160       DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
161       CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) = 0;
162 
163   /// Link debug info for added files.
164   virtual Error link() = 0;
165 
166   /// \defgroup Methods setting various linking options:
167   ///
168   /// @{
169 
170   /// Allows to generate log of linking process to the standard output.
171   virtual void setVerbosity(bool Verbose) = 0;
172 
173   /// Print statistics to standard output.
174   virtual void setStatistics(bool Statistics) = 0;
175 
176   /// Verify the input DWARF.
177   virtual void setVerifyInputDWARF(bool Verify) = 0;
178 
179   /// Do not unique types according to ODR.
180   virtual void setNoODR(bool NoODR) = 0;
181 
182   /// Update index tables only(do not modify rest of DWARF).
183   virtual void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) = 0;
184 
185   /// Allow generating valid, but non-deterministic output.
186   virtual void
187   setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) = 0;
188 
189   /// Set to keep the enclosing function for a static variable.
190   virtual void setKeepFunctionForStatic(bool KeepFunctionForStatic) = 0;
191 
192   /// Use specified number of threads for parallel files linking.
193   virtual void setNumThreads(unsigned NumThreads) = 0;
194 
195   /// Add kind of accelerator tables to be generated.
196   virtual void addAccelTableKind(AccelTableKind Kind) = 0;
197 
198   /// Set prepend path for clang modules.
199   virtual void setPrependPath(const std::string &Ppath) = 0;
200 
201   /// Set estimated objects files amount, for preliminary data allocation.
202   virtual void setEstimatedObjfilesAmount(unsigned ObjFilesNum) = 0;
203 
204   /// Set verification handler which would be used to report verification
205   /// errors.
206   virtual void
207   setInputVerificationHandler(InputVerificationHandlerTy Handler) = 0;
208 
209   /// Set map for Swift interfaces.
210   virtual void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) = 0;
211 
212   /// Set prefix map for objects.
213   virtual void setObjectPrefixMap(ObjectPrefixMapTy *Map) = 0;
214 
215   /// Set target DWARF version.
216   virtual Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) = 0;
217   /// @}
218 };
219 
220 } // end namespace dwarflinker_parallel
221 } // end namespace llvm
222 
223 #endif // LLVM_DWARFLINKERPARALLEL_DWARFLINKER_H
224