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_DWARFLINKER_PARALLEL_DWARFLINKER_H 10 #define LLVM_DWARFLINKER_PARALLEL_DWARFLINKER_H 11 12 #include "llvm/CodeGen/AsmPrinter.h" 13 #include "llvm/DWARFLinker/DWARFFile.h" 14 #include "llvm/DWARFLinker/DWARFLinkerBase.h" 15 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 16 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 17 #include "llvm/MC/MCDwarf.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/TargetParser/Triple.h" 20 21 /// ------------------------------------------------------------------ 22 /// The core of the Dwarf linking logic. 23 /// 24 /// The generation of the dwarf information from the object files will be 25 /// driven by the selection of 'root DIEs', which are DIEs that 26 /// describe variables or functions that resolves to the corresponding 27 /// code section(and thus have entries in the Addresses map). All the debug 28 /// information that will be generated(the DIEs, but also the line 29 /// tables, ranges, ...) is derived from that set of root DIEs. 30 /// 31 /// The root DIEs are identified because they contain relocations that 32 /// points to code section(the low_pc for a function, the location for 33 /// a variable). These relocations are gathered as a very first step 34 /// when we start processing a object file by AddressesMap. 35 /// 36 /// The overall linking process looks like this: 37 /// 38 /// parrallel_for_each(ObjectFile) { 39 /// for_each (Compile Unit) { 40 /// 1. Load Clang modules. 41 /// } 42 /// 43 /// parrallel_for_each(Compile Unit) { 44 /// 1. Load input DWARF for Compile Unit. 45 /// 2. Report warnings for Clang modules. 46 /// 3. Analyze live DIEs and type names(if ODR deduplication is requested). 47 /// 4. Clone DIEs(Generate output DIEs and resulting DWARF tables). 48 /// The result is in an OutDebugInfoBytes, which is an ELF file 49 /// containing DWARF tables corresponding to the current compile unit. 50 /// 5. Cleanup Input and Output DIEs. 51 /// } 52 /// 53 /// Deallocate loaded Object file. 54 /// } 55 /// 56 /// if (ODR deduplication is requested) 57 /// Generate an artificial compilation unit ("Type Table": used to partially 58 /// generate DIEs at the clone stage). 59 /// 60 /// for_each (ObjectFile) { 61 /// for_each (Compile Unit) { 62 /// 1. Set offsets to Compile Units DWARF tables. 63 /// 2. Sort offsets/attributes/patches to have a predictable result. 64 /// 3. Patch size/offsets fields. 65 /// 4. Generate index tables. 66 /// 5. Move DWARF tables of compile units into the resulting file. 67 /// } 68 /// } 69 /// 70 /// Every compile unit is processed separately, visited only once 71 /// (except case inter-CU references exist), and used data is freed 72 /// after the compile unit is processed. The resulting file is glued together 73 /// from the generated debug tables which correspond to separate compile units. 74 /// 75 /// Handling inter-CU references: inter-CU references are hard to process 76 /// using only one pass. f.e. if CU1 references CU100 and CU100 references 77 /// CU1, we could not finish handling of CU1 until we finished CU100. 78 /// Thus we either need to load all CUs into the memory, either load CUs several 79 /// times. This implementation loads inter-connected CU into memory at the first 80 /// pass and processes them at the second pass. 81 /// 82 /// ODR deduplication: Artificial compilation unit will be constructed to keep 83 /// type dies. All types are moved into that compilation unit. Type's references 84 /// are patched so that they point to the corresponding types from artificial 85 /// compilation unit. All partial type definitions would be merged into single 86 /// type definition. 87 /// 88 89 namespace llvm { 90 namespace dwarf_linker { 91 namespace parallel { 92 93 /// This structure keeps data of the concrete section. 94 struct SectionDescriptorBase { SectionDescriptorBaseSectionDescriptorBase95 SectionDescriptorBase(DebugSectionKind SectionKind, dwarf::FormParams Format, 96 llvm::endianness Endianess) 97 : SectionKind(SectionKind), Format(Format), Endianess(Endianess) {} 98 virtual ~SectionDescriptorBase() = default; 99 /// Returns section content. 100 virtual StringRef getContents() = 0; 101 /// Returns section kind. getKindSectionDescriptorBase102 DebugSectionKind getKind() { return SectionKind; } 103 /// Returns section name. getNameSectionDescriptorBase104 const StringLiteral &getName() const { return getSectionName(SectionKind); } 105 /// Returns endianess used by section. getEndianessSectionDescriptorBase106 llvm::endianness getEndianess() const { return Endianess; } 107 /// Returns FormParams used by section. getFormParamsSectionDescriptorBase108 dwarf::FormParams getFormParams() const { return Format; } 109 110 protected: 111 /// The section kind. 112 DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries; 113 /// Output format. 114 dwarf::FormParams Format = {4, 4, dwarf::DWARF32}; 115 llvm::endianness Endianess = llvm::endianness::little; 116 }; 117 118 using SectionHandlerTy = 119 std::function<void(std::shared_ptr<SectionDescriptorBase> Section)>; 120 121 class DWARFLinker : public DWARFLinkerBase { 122 public: 123 virtual ~DWARFLinker() = default; 124 125 /// Creates dwarf linker instance. 126 LLVM_ABI static std::unique_ptr<DWARFLinker> 127 createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler); 128 129 /// Set output DWARF handler. Result of linking DWARF is set of sections 130 /// containing final debug info. DWARFLinkerBase::link() pass generated 131 /// sections using specified \p SectionHandler. 132 virtual void setOutputDWARFHandler(const Triple &TargetTriple, 133 SectionHandlerTy SectionHandler) = 0; 134 }; 135 136 } // end of namespace parallel 137 } // end of namespace dwarf_linker 138 } // end of namespace llvm 139 140 #endif // LLVM_DWARFLINKER_PARALLEL_DWARFLINKER_H 141