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