1 //===- DWARFLinkerUnit.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_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 10 #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 11 12 #include "DWARFLinkerGlobalData.h" 13 #include "OutputSections.h" 14 #include "llvm/CodeGen/DIE.h" 15 #include "llvm/DWARFLinker/IndexedValuesMap.h" 16 #include "llvm/DWARFLinker/Parallel/DWARFLinker.h" 17 #include "llvm/DWARFLinker/StringPool.h" 18 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 19 #include "llvm/Support/LEB128.h" 20 21 namespace llvm { 22 namespace dwarf_linker { 23 namespace parallel { 24 25 class DwarfUnit; 26 using MacroOffset2UnitMapTy = DenseMap<uint64_t, DwarfUnit *>; 27 28 /// Base class for all Dwarf units(Compile unit/Type table unit). 29 class DwarfUnit : public OutputSections { 30 public: 31 virtual ~DwarfUnit() {} 32 DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, 33 StringRef ClangModuleName) 34 : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName), 35 OutUnitDIE(nullptr) {} 36 37 /// Unique id of the unit. 38 unsigned getUniqueID() const { return ID; } 39 40 /// Returns size of this(newly generated) compile unit. 41 uint64_t getUnitSize() const { return UnitSize; } 42 43 /// Returns this unit name. 44 StringRef getUnitName() const { return UnitName; } 45 46 /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef. 47 StringRef getSysRoot() { return SysRoot; } 48 49 /// Return true if this compile unit is from Clang module. 50 bool isClangModule() const { return !ClangModuleName.empty(); } 51 52 /// Return Clang module name; 53 const std::string &getClangModuleName() const { return ClangModuleName; } 54 55 /// Return global data. 56 LinkingGlobalData &getGlobalData() { return GlobalData; } 57 58 /// Returns true if unit is inter-connected(it references/referenced by other 59 /// unit). 60 bool isInterconnectedCU() const { return IsInterconnectedCU; } 61 62 /// Mark this unit as inter-connected(it references/referenced by other unit). 63 void setInterconnectedCU() { IsInterconnectedCU = true; } 64 65 /// Adds \p Abbrev into unit`s abbreviation table. 66 void assignAbbrev(DIEAbbrev &Abbrev); 67 68 /// Returns abbreviations for this compile unit. 69 const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const { 70 return Abbreviations; 71 } 72 73 /// Returns output unit DIE. 74 DIE *getOutUnitDIE() { return OutUnitDIE; } 75 76 /// Set output unit DIE. 77 void setOutUnitDIE(DIE *UnitDie) { 78 OutUnitDIE = UnitDie; 79 80 if (OutUnitDIE != nullptr) { 81 UnitSize = getDebugInfoHeaderSize() + OutUnitDIE->getSize(); 82 UnitTag = OutUnitDIE->getTag(); 83 } 84 } 85 86 /// Returns unit DWARF tag. 87 dwarf::Tag getTag() const { return UnitTag; } 88 89 /// \defgroup Methods used to emit unit's debug info: 90 /// 91 /// @{ 92 /// Emit unit's abbreviations. 93 Error emitAbbreviations(); 94 95 /// Emit .debug_info section for unit DIEs. 96 Error emitDebugInfo(const Triple &TargetTriple); 97 98 /// Emit .debug_line section. 99 Error emitDebugLine(const Triple &TargetTriple, 100 const DWARFDebugLine::LineTable &OutLineTable); 101 102 /// Emit the .debug_str_offsets section for current unit. 103 Error emitDebugStringOffsetSection(); 104 /// @} 105 106 /// \defgroup Methods used for reporting warnings and errors: 107 /// 108 /// @{ 109 void warn(const Twine &Warning) { GlobalData.warn(Warning, getUnitName()); } 110 111 void error(const Twine &Err) { GlobalData.warn(Err, getUnitName()); } 112 /// @} 113 114 /// \defgroup Methods and data members used for building accelerator tables: 115 /// 116 /// @{ 117 118 enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type }; 119 120 /// This structure keeps fields which would be used for creating accelerator 121 /// table. 122 struct AccelInfo { 123 AccelInfo() { 124 AvoidForPubSections = false; 125 ObjcClassImplementation = false; 126 } 127 128 /// Name of the entry. 129 StringEntry *String = nullptr; 130 131 /// Output offset of the DIE this entry describes. 132 uint64_t OutOffset; 133 134 /// Hash of the fully qualified name. 135 uint32_t QualifiedNameHash = 0; 136 137 /// Tag of the DIE this entry describes. 138 dwarf::Tag Tag = dwarf::DW_TAG_null; 139 140 /// Type of this accelerator record. 141 AccelType Type = AccelType::None; 142 143 /// Avoid emitting this entry for pub sections. 144 bool AvoidForPubSections : 1; 145 146 /// Is this an ObjC class implementation? 147 bool ObjcClassImplementation : 1; 148 }; 149 150 /// Emit .debug_pubnames and .debug_pubtypes for \p Unit. 151 void emitPubAccelerators(); 152 153 /// Enumerates accelerator data. 154 virtual void 155 forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0; 156 157 /// @} 158 159 /// Returns index(inside .debug_str_offsets) of specified string. 160 virtual uint64_t getDebugStrIndex(const StringEntry *String) { 161 return DebugStringIndexMap.getValueIndex(String); 162 } 163 164 protected: 165 /// Emit single abbreviation entry. 166 void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev, 167 SectionDescriptor &AbbrevSection); 168 169 /// Emit single pubnames/pubtypes accelerator entry. 170 std::optional<uint64_t> 171 emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info, 172 std::optional<uint64_t> LengthOffset); 173 174 /// Unique ID for the unit. 175 unsigned ID = 0; 176 177 /// The name of this unit. 178 std::string UnitName; 179 180 /// The DW_AT_LLVM_sysroot of this unit. 181 std::string SysRoot; 182 183 /// If this is a Clang module, this holds the module's name. 184 std::string ClangModuleName; 185 186 uint64_t UnitSize = 0; 187 188 /// DWARF unit tag. 189 dwarf::Tag UnitTag = dwarf::DW_TAG_null; 190 191 /// true if current unit references_to/is_referenced by other unit. 192 std::atomic<bool> IsInterconnectedCU = {false}; 193 194 /// FoldingSet that uniques the abbreviations. 195 FoldingSet<DIEAbbrev> AbbreviationsSet; 196 197 /// Storage for the unique Abbreviations. 198 std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; 199 200 /// Output unit DIE. 201 DIE *OutUnitDIE = nullptr; 202 203 /// Cache for file names for this unit. 204 using FileNamesCache = 205 DenseMap<uint64_t, std::pair<std::string, std::string>>; 206 FileNamesCache FileNames; 207 208 /// Maps a string into the index inside .debug_str_offsets section. 209 IndexedValuesMap<const StringEntry *> DebugStringIndexMap; 210 }; 211 212 inline bool isODRLanguage(uint16_t Language) { 213 switch (Language) { 214 case dwarf::DW_LANG_C_plus_plus: 215 case dwarf::DW_LANG_C_plus_plus_03: 216 case dwarf::DW_LANG_C_plus_plus_11: 217 case dwarf::DW_LANG_C_plus_plus_14: 218 case dwarf::DW_LANG_ObjC_plus_plus: 219 return true; 220 default: 221 return false; 222 }; 223 224 return false; 225 } 226 227 } // end of namespace parallel 228 } // end of namespace dwarf_linker 229 } // end of namespace llvm 230 231 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 232