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