11db9f3b2SDimitry Andric //===- DWARFLinkerUnit.h ----------------------------------------*- C++ -*-===// 21db9f3b2SDimitry Andric // 31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61db9f3b2SDimitry Andric // 71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 81db9f3b2SDimitry Andric 91db9f3b2SDimitry Andric #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 101db9f3b2SDimitry Andric #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 111db9f3b2SDimitry Andric 121db9f3b2SDimitry Andric #include "DWARFLinkerGlobalData.h" 131db9f3b2SDimitry Andric #include "OutputSections.h" 141db9f3b2SDimitry Andric #include "llvm/CodeGen/DIE.h" 157a6dacacSDimitry Andric #include "llvm/DWARFLinker/IndexedValuesMap.h" 161db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Parallel/DWARFLinker.h" 171db9f3b2SDimitry Andric #include "llvm/DWARFLinker/StringPool.h" 181db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 191db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h" 201db9f3b2SDimitry Andric 211db9f3b2SDimitry Andric namespace llvm { 221db9f3b2SDimitry Andric namespace dwarf_linker { 231db9f3b2SDimitry Andric namespace parallel { 241db9f3b2SDimitry Andric 251db9f3b2SDimitry Andric class DwarfUnit; 261db9f3b2SDimitry Andric using MacroOffset2UnitMapTy = DenseMap<uint64_t, DwarfUnit *>; 271db9f3b2SDimitry Andric 281db9f3b2SDimitry Andric /// Base class for all Dwarf units(Compile unit/Type table unit). 291db9f3b2SDimitry Andric class DwarfUnit : public OutputSections { 301db9f3b2SDimitry Andric public: 311db9f3b2SDimitry Andric virtual ~DwarfUnit() {} 321db9f3b2SDimitry Andric DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, 331db9f3b2SDimitry Andric StringRef ClangModuleName) 341db9f3b2SDimitry Andric : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName), 351db9f3b2SDimitry Andric OutUnitDIE(nullptr) {} 361db9f3b2SDimitry Andric 371db9f3b2SDimitry Andric /// Unique id of the unit. 381db9f3b2SDimitry Andric unsigned getUniqueID() const { return ID; } 391db9f3b2SDimitry Andric 401db9f3b2SDimitry Andric /// Returns size of this(newly generated) compile unit. 411db9f3b2SDimitry Andric uint64_t getUnitSize() const { return UnitSize; } 421db9f3b2SDimitry Andric 431db9f3b2SDimitry Andric /// Returns this unit name. 441db9f3b2SDimitry Andric StringRef getUnitName() const { return UnitName; } 451db9f3b2SDimitry Andric 461db9f3b2SDimitry Andric /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef. 471db9f3b2SDimitry Andric StringRef getSysRoot() { return SysRoot; } 481db9f3b2SDimitry Andric 491db9f3b2SDimitry Andric /// Return true if this compile unit is from Clang module. 501db9f3b2SDimitry Andric bool isClangModule() const { return !ClangModuleName.empty(); } 511db9f3b2SDimitry Andric 521db9f3b2SDimitry Andric /// Return Clang module name; 531db9f3b2SDimitry Andric const std::string &getClangModuleName() const { return ClangModuleName; } 541db9f3b2SDimitry Andric 551db9f3b2SDimitry Andric /// Return global data. 561db9f3b2SDimitry Andric LinkingGlobalData &getGlobalData() { return GlobalData; } 571db9f3b2SDimitry Andric 581db9f3b2SDimitry Andric /// Returns true if unit is inter-connected(it references/referenced by other 591db9f3b2SDimitry Andric /// unit). 601db9f3b2SDimitry Andric bool isInterconnectedCU() const { return IsInterconnectedCU; } 611db9f3b2SDimitry Andric 621db9f3b2SDimitry Andric /// Mark this unit as inter-connected(it references/referenced by other unit). 631db9f3b2SDimitry Andric void setInterconnectedCU() { IsInterconnectedCU = true; } 641db9f3b2SDimitry Andric 651db9f3b2SDimitry Andric /// Adds \p Abbrev into unit`s abbreviation table. 661db9f3b2SDimitry Andric void assignAbbrev(DIEAbbrev &Abbrev); 671db9f3b2SDimitry Andric 681db9f3b2SDimitry Andric /// Returns abbreviations for this compile unit. 691db9f3b2SDimitry Andric const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const { 701db9f3b2SDimitry Andric return Abbreviations; 711db9f3b2SDimitry Andric } 721db9f3b2SDimitry Andric 731db9f3b2SDimitry Andric /// Returns output unit DIE. 741db9f3b2SDimitry Andric DIE *getOutUnitDIE() { return OutUnitDIE; } 751db9f3b2SDimitry Andric 761db9f3b2SDimitry Andric /// Set output unit DIE. 771db9f3b2SDimitry Andric void setOutUnitDIE(DIE *UnitDie) { 781db9f3b2SDimitry Andric OutUnitDIE = UnitDie; 791db9f3b2SDimitry Andric 80*0fca6ea1SDimitry Andric if (OutUnitDIE != nullptr) { 811db9f3b2SDimitry Andric UnitSize = getDebugInfoHeaderSize() + OutUnitDIE->getSize(); 82*0fca6ea1SDimitry Andric UnitTag = OutUnitDIE->getTag(); 831db9f3b2SDimitry Andric } 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric 86*0fca6ea1SDimitry Andric /// Returns unit DWARF tag. 87*0fca6ea1SDimitry Andric dwarf::Tag getTag() const { return UnitTag; } 881db9f3b2SDimitry Andric 891db9f3b2SDimitry Andric /// \defgroup Methods used to emit unit's debug info: 901db9f3b2SDimitry Andric /// 911db9f3b2SDimitry Andric /// @{ 921db9f3b2SDimitry Andric /// Emit unit's abbreviations. 931db9f3b2SDimitry Andric Error emitAbbreviations(); 941db9f3b2SDimitry Andric 951db9f3b2SDimitry Andric /// Emit .debug_info section for unit DIEs. 961db9f3b2SDimitry Andric Error emitDebugInfo(const Triple &TargetTriple); 971db9f3b2SDimitry Andric 981db9f3b2SDimitry Andric /// Emit .debug_line section. 991db9f3b2SDimitry Andric Error emitDebugLine(const Triple &TargetTriple, 1001db9f3b2SDimitry Andric const DWARFDebugLine::LineTable &OutLineTable); 1011db9f3b2SDimitry Andric 1021db9f3b2SDimitry Andric /// Emit the .debug_str_offsets section for current unit. 1031db9f3b2SDimitry Andric Error emitDebugStringOffsetSection(); 1041db9f3b2SDimitry Andric /// @} 1051db9f3b2SDimitry Andric 1061db9f3b2SDimitry Andric /// \defgroup Methods used for reporting warnings and errors: 1071db9f3b2SDimitry Andric /// 1081db9f3b2SDimitry Andric /// @{ 1091db9f3b2SDimitry Andric void warn(const Twine &Warning) { GlobalData.warn(Warning, getUnitName()); } 1101db9f3b2SDimitry Andric 1111db9f3b2SDimitry Andric void error(const Twine &Err) { GlobalData.warn(Err, getUnitName()); } 1121db9f3b2SDimitry Andric /// @} 1131db9f3b2SDimitry Andric 1141db9f3b2SDimitry Andric /// \defgroup Methods and data members used for building accelerator tables: 1151db9f3b2SDimitry Andric /// 1161db9f3b2SDimitry Andric /// @{ 1171db9f3b2SDimitry Andric 1181db9f3b2SDimitry Andric enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type }; 1191db9f3b2SDimitry Andric 1201db9f3b2SDimitry Andric /// This structure keeps fields which would be used for creating accelerator 1211db9f3b2SDimitry Andric /// table. 1221db9f3b2SDimitry Andric struct AccelInfo { 1231db9f3b2SDimitry Andric AccelInfo() { 1241db9f3b2SDimitry Andric AvoidForPubSections = false; 1251db9f3b2SDimitry Andric ObjcClassImplementation = false; 1261db9f3b2SDimitry Andric } 1271db9f3b2SDimitry Andric 1281db9f3b2SDimitry Andric /// Name of the entry. 1291db9f3b2SDimitry Andric StringEntry *String = nullptr; 1301db9f3b2SDimitry Andric 1311db9f3b2SDimitry Andric /// Output offset of the DIE this entry describes. 1321db9f3b2SDimitry Andric uint64_t OutOffset; 1331db9f3b2SDimitry Andric 1341db9f3b2SDimitry Andric /// Hash of the fully qualified name. 1351db9f3b2SDimitry Andric uint32_t QualifiedNameHash = 0; 1361db9f3b2SDimitry Andric 1371db9f3b2SDimitry Andric /// Tag of the DIE this entry describes. 1381db9f3b2SDimitry Andric dwarf::Tag Tag = dwarf::DW_TAG_null; 1391db9f3b2SDimitry Andric 1401db9f3b2SDimitry Andric /// Type of this accelerator record. 1411db9f3b2SDimitry Andric AccelType Type = AccelType::None; 1421db9f3b2SDimitry Andric 1431db9f3b2SDimitry Andric /// Avoid emitting this entry for pub sections. 1441db9f3b2SDimitry Andric bool AvoidForPubSections : 1; 1451db9f3b2SDimitry Andric 1461db9f3b2SDimitry Andric /// Is this an ObjC class implementation? 1471db9f3b2SDimitry Andric bool ObjcClassImplementation : 1; 1481db9f3b2SDimitry Andric }; 1491db9f3b2SDimitry Andric 1501db9f3b2SDimitry Andric /// Emit .debug_pubnames and .debug_pubtypes for \p Unit. 1511db9f3b2SDimitry Andric void emitPubAccelerators(); 1521db9f3b2SDimitry Andric 1531db9f3b2SDimitry Andric /// Enumerates accelerator data. 1541db9f3b2SDimitry Andric virtual void 1551db9f3b2SDimitry Andric forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0; 1561db9f3b2SDimitry Andric 1571db9f3b2SDimitry Andric /// @} 1581db9f3b2SDimitry Andric 1591db9f3b2SDimitry Andric /// Returns index(inside .debug_str_offsets) of specified string. 1601db9f3b2SDimitry Andric virtual uint64_t getDebugStrIndex(const StringEntry *String) { 1611db9f3b2SDimitry Andric return DebugStringIndexMap.getValueIndex(String); 1621db9f3b2SDimitry Andric } 1631db9f3b2SDimitry Andric 1641db9f3b2SDimitry Andric protected: 1651db9f3b2SDimitry Andric /// Emit single abbreviation entry. 1661db9f3b2SDimitry Andric void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev, 1671db9f3b2SDimitry Andric SectionDescriptor &AbbrevSection); 1681db9f3b2SDimitry Andric 1691db9f3b2SDimitry Andric /// Emit single pubnames/pubtypes accelerator entry. 1701db9f3b2SDimitry Andric std::optional<uint64_t> 1711db9f3b2SDimitry Andric emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info, 1721db9f3b2SDimitry Andric std::optional<uint64_t> LengthOffset); 1731db9f3b2SDimitry Andric 1741db9f3b2SDimitry Andric /// Unique ID for the unit. 1751db9f3b2SDimitry Andric unsigned ID = 0; 1761db9f3b2SDimitry Andric 1771db9f3b2SDimitry Andric /// The name of this unit. 1781db9f3b2SDimitry Andric std::string UnitName; 1791db9f3b2SDimitry Andric 1801db9f3b2SDimitry Andric /// The DW_AT_LLVM_sysroot of this unit. 1811db9f3b2SDimitry Andric std::string SysRoot; 1821db9f3b2SDimitry Andric 1831db9f3b2SDimitry Andric /// If this is a Clang module, this holds the module's name. 1841db9f3b2SDimitry Andric std::string ClangModuleName; 1851db9f3b2SDimitry Andric 1861db9f3b2SDimitry Andric uint64_t UnitSize = 0; 1871db9f3b2SDimitry Andric 188*0fca6ea1SDimitry Andric /// DWARF unit tag. 189*0fca6ea1SDimitry Andric dwarf::Tag UnitTag = dwarf::DW_TAG_null; 190*0fca6ea1SDimitry Andric 1911db9f3b2SDimitry Andric /// true if current unit references_to/is_referenced by other unit. 1921db9f3b2SDimitry Andric std::atomic<bool> IsInterconnectedCU = {false}; 1931db9f3b2SDimitry Andric 1941db9f3b2SDimitry Andric /// FoldingSet that uniques the abbreviations. 1951db9f3b2SDimitry Andric FoldingSet<DIEAbbrev> AbbreviationsSet; 1961db9f3b2SDimitry Andric 1971db9f3b2SDimitry Andric /// Storage for the unique Abbreviations. 1981db9f3b2SDimitry Andric std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; 1991db9f3b2SDimitry Andric 2001db9f3b2SDimitry Andric /// Output unit DIE. 2011db9f3b2SDimitry Andric DIE *OutUnitDIE = nullptr; 2021db9f3b2SDimitry Andric 2031db9f3b2SDimitry Andric /// Cache for file names for this unit. 2041db9f3b2SDimitry Andric using FileNamesCache = 2051db9f3b2SDimitry Andric DenseMap<uint64_t, std::pair<std::string, std::string>>; 2061db9f3b2SDimitry Andric FileNamesCache FileNames; 2071db9f3b2SDimitry Andric 2081db9f3b2SDimitry Andric /// Maps a string into the index inside .debug_str_offsets section. 2091db9f3b2SDimitry Andric IndexedValuesMap<const StringEntry *> DebugStringIndexMap; 2101db9f3b2SDimitry Andric }; 2111db9f3b2SDimitry Andric 2121db9f3b2SDimitry Andric inline bool isODRLanguage(uint16_t Language) { 2131db9f3b2SDimitry Andric switch (Language) { 2141db9f3b2SDimitry Andric case dwarf::DW_LANG_C_plus_plus: 2151db9f3b2SDimitry Andric case dwarf::DW_LANG_C_plus_plus_03: 2161db9f3b2SDimitry Andric case dwarf::DW_LANG_C_plus_plus_11: 2171db9f3b2SDimitry Andric case dwarf::DW_LANG_C_plus_plus_14: 2181db9f3b2SDimitry Andric case dwarf::DW_LANG_ObjC_plus_plus: 2191db9f3b2SDimitry Andric return true; 2201db9f3b2SDimitry Andric default: 2211db9f3b2SDimitry Andric return false; 2221db9f3b2SDimitry Andric }; 2231db9f3b2SDimitry Andric 2241db9f3b2SDimitry Andric return false; 2251db9f3b2SDimitry Andric } 2261db9f3b2SDimitry Andric 2271db9f3b2SDimitry Andric } // end of namespace parallel 2281db9f3b2SDimitry Andric } // end of namespace dwarf_linker 2291db9f3b2SDimitry Andric } // end of namespace llvm 2301db9f3b2SDimitry Andric 2311db9f3b2SDimitry Andric #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H 232