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