1 //===- bolt/Core/DebugNames.h - Debug names support ---*- 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 // This file contains declaration of classes required for generation of 10 // .debug_names section. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef BOLT_CORE_DEBUG_NAMES_H 15 #define BOLT_CORE_DEBUG_NAMES_H 16 17 #include "bolt/Core/DebugData.h" 18 #include "llvm/CodeGen/AccelTable.h" 19 20 namespace llvm { 21 namespace bolt { 22 class BOLTDWARF5AccelTableData : public DWARF5AccelTableData { 23 public: 24 BOLTDWARF5AccelTableData(const uint64_t DieOffset, 25 const std::optional<uint64_t> DefiningParentOffset, 26 const unsigned DieTag, const unsigned UnitID, 27 const bool IsParentRoot, const bool IsTU, 28 const std::optional<unsigned> SecondUnitID) 29 : DWARF5AccelTableData(DieOffset, DefiningParentOffset, DieTag, UnitID, 30 IsTU), 31 SecondUnitID(SecondUnitID), IsParentRoot(IsParentRoot) {} 32 33 uint64_t getDieOffset() const { return DWARF5AccelTableData::getDieOffset(); } 34 unsigned getDieTag() const { return DWARF5AccelTableData::getDieTag(); } 35 unsigned getUnitID() const { return DWARF5AccelTableData::getUnitID(); } 36 bool isTU() const { return DWARF5AccelTableData::isTU(); } 37 bool isParentRoot() const { return IsParentRoot; } 38 std::optional<unsigned> getSecondUnitID() const { return SecondUnitID; } 39 40 void setPatchOffset(uint64_t PatchOffset) { OffsetVal = PatchOffset; } 41 uint64_t getPatchOffset() const { return std::get<uint64_t>(OffsetVal); } 42 43 private: 44 std::optional<unsigned> SecondUnitID; 45 bool IsParentRoot; 46 }; 47 48 class DWARF5AcceleratorTable { 49 public: 50 DWARF5AcceleratorTable(const bool CreateDebugNames, BinaryContext &BC, 51 DebugStrWriter &MainBinaryStrWriter); 52 ~DWARF5AcceleratorTable() { 53 for (DebugNamesAbbrev *Abbrev : AbbreviationsVector) 54 Abbrev->~DebugNamesAbbrev(); 55 } 56 /// Add DWARF5 Accelerator table entry. 57 /// Input is DWARFUnit being processed, DIE that belongs to it, potential 58 /// DWOID if the Unit comes from a DWO section, and potential parent entry. 59 std::optional<BOLTDWARF5AccelTableData *> 60 addAccelTableEntry(DWARFUnit &Unit, const DIE &Die, 61 const std::optional<uint64_t> &DWOID, 62 const uint32_t NumberParentsInChain, 63 std::optional<BOLTDWARF5AccelTableData *> &Parent); 64 /// Set current unit being processed. 65 void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset); 66 /// Emit Accelerator table. 67 void emitAccelTable(); 68 /// Returns true if the table was crated. 69 bool isCreated() const { return NeedToCreate; } 70 /// Returns buffer containing the accelerator table. 71 std::unique_ptr<DebugBufferVector> releaseBuffer() { 72 return std::move(FullTableBuffer); 73 } 74 /// Adds a DIE that is referenced across CUs. 75 void addCrossCUDie(DWARFUnit *Unit, const DIE *Die) { 76 CrossCUDies.insert({Die->getOffset(), {Unit, Die}}); 77 } 78 /// Returns true if the DIE can generate an entry for a cross cu reference. 79 /// This only checks TAGs of a DIE because when this is invoked DIE might not 80 /// be fully constructed. 81 bool canGenerateEntryWithCrossCUReference( 82 const DWARFUnit &Unit, const DIE &Die, 83 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec); 84 85 private: 86 BinaryContext &BC; 87 bool NeedToCreate = false; 88 BumpPtrAllocator Allocator; 89 DebugStrWriter &MainBinaryStrWriter; 90 StringRef StrSection; 91 uint64_t CurrentUnitOffset = 0; 92 const DWARFUnit *CurrentUnit = nullptr; 93 std::unordered_map<uint32_t, uint32_t> AbbrevTagToIndexMap; 94 /// Contains a map of TU hashes to a Foreign TU indecies. 95 /// This is used to reduce the size of Foreign TU list since there could be 96 /// multiple TUs with the same hash. 97 DenseMap<uint64_t, uint32_t> TUHashToIndexMap; 98 99 /// Represents a group of entries with identical name (and hence, hash value). 100 struct HashData { 101 uint64_t StrOffset; 102 uint32_t HashValue; 103 uint32_t EntryOffset; 104 std::vector<BOLTDWARF5AccelTableData *> Values; 105 }; 106 using HashList = std::vector<HashData *>; 107 using BucketList = std::vector<HashList>; 108 /// Contains all the offsets of CUs. 109 SmallVector<uint32_t, 1> CUList; 110 /// Contains all the offsets of local TUs. 111 SmallVector<uint32_t, 1> LocalTUList; 112 /// Contains all the type hashes for split dwarf TUs. 113 SmallVector<uint64_t, 1> ForeignTUList; 114 using StringEntries = 115 MapVector<std::string, HashData, llvm::StringMap<unsigned>>; 116 StringEntries Entries; 117 /// FoldingSet that uniques the abbreviations. 118 FoldingSet<DebugNamesAbbrev> AbbreviationsSet; 119 /// Vector containing DebugNames abbreviations for iteration in order. 120 SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector; 121 /// The bump allocator to use when creating DIEAbbrev objects in the uniqued 122 /// storage container. 123 BumpPtrAllocator Alloc; 124 uint32_t BucketCount = 0; 125 uint32_t UniqueHashCount = 0; 126 uint32_t AbbrevTableSize = 0; 127 uint32_t CUIndexEncodingSize = 4; 128 uint32_t TUIndexEncodingSize = 4; 129 uint32_t AugmentationStringSize = 0; 130 dwarf::Form CUIndexForm = dwarf::DW_FORM_data4; 131 dwarf::Form TUIndexForm = dwarf::DW_FORM_data4; 132 133 BucketList Buckets; 134 135 std::unique_ptr<DebugBufferVector> FullTableBuffer; 136 std::unique_ptr<raw_svector_ostream> FullTableStream; 137 std::unique_ptr<DebugBufferVector> StrBuffer; 138 std::unique_ptr<raw_svector_ostream> StrStream; 139 std::unique_ptr<DebugBufferVector> EntriesBuffer; 140 std::unique_ptr<raw_svector_ostream> Entriestream; 141 std::unique_ptr<DebugBufferVector> AugStringBuffer; 142 std::unique_ptr<raw_svector_ostream> AugStringtream; 143 llvm::DenseMap<llvm::hash_code, uint64_t> StrCacheToOffsetMap; 144 // Contains DWO ID to CUList Index. 145 llvm::DenseMap<uint64_t, uint32_t> CUOffsetsToPatch; 146 // Contains a map of Entry ID to Entry relative offset. 147 llvm::DenseMap<uint64_t, uint32_t> EntryRelativeOffsets; 148 llvm::DenseMap<uint64_t, std::pair<DWARFUnit *, const DIE *>> CrossCUDies; 149 /// Adds Unit to either CUList, LocalTUList or ForeignTUList. 150 /// Input Unit being processed, and DWO ID if Unit is being processed comes 151 /// from a DWO section. 152 void addUnit(DWARFUnit &Unit, const std::optional<uint64_t> &DWOID); 153 /// Returns number of buckets in .debug_name table. 154 ArrayRef<HashList> getBuckets() const { return Buckets; } 155 /// Get encoding for a given attribute. 156 std::optional<DWARF5AccelTable::UnitIndexAndEncoding> 157 getIndexForEntry(const BOLTDWARF5AccelTableData &Value) const; 158 /// Get encoding for a given attribute for second index. 159 /// Returns nullopt if there is no second index. 160 std::optional<DWARF5AccelTable::UnitIndexAndEncoding> 161 getSecondIndexForEntry(const BOLTDWARF5AccelTableData &Value) const; 162 /// Uniquify Entries. 163 void finalize(); 164 /// Computes bucket count. 165 void computeBucketCount(); 166 /// Populate Abbreviations Map. 167 void populateAbbrevsMap(); 168 /// Write Entries. 169 void writeEntries(); 170 /// Write an Entry. 171 void writeEntry(BOLTDWARF5AccelTableData &Entry); 172 /// Write augmentation_string for BOLT. 173 void writeAugmentationString(); 174 /// Emit out Header for DWARF5 Accelerator table. 175 void emitHeader() const; 176 /// Emit out CU list. 177 void emitCUList() const; 178 /// Emit out TU List. Combination of LocalTUList and ForeignTUList. 179 void emitTUList() const; 180 /// Emit buckets. 181 void emitBuckets() const; 182 /// Emit hashes for hash table. 183 void emitHashes() const; 184 /// Emit string offsets for hash table. 185 void emitStringOffsets() const; 186 /// Emit Entry Offsets for hash table. 187 void emitOffsets() const; 188 /// Emit abbreviation table. 189 void emitAbbrevs(); 190 /// Emit entries. 191 void emitData(); 192 /// Emit augmentation string. 193 void emitAugmentationString() const; 194 /// Creates a new entry for a given DIE. 195 std::optional<BOLTDWARF5AccelTableData *> 196 addEntry(DWARFUnit &DU, const DIE &CurrDie, 197 const std::optional<uint64_t> &DWOID, 198 const std::optional<BOLTDWARF5AccelTableData *> &Parent, 199 const std::optional<std::string> &Name, 200 const uint32_t NumberParentsInChain); 201 /// Returns UnitID for a given DWARFUnit. 202 uint32_t getUnitID(const DWARFUnit &Unit, 203 const std::optional<uint64_t> &DWOID, bool &IsTU); 204 std::optional<std::string> getName(DWARFUnit &DU, 205 const std::optional<uint64_t> &DWOID, 206 const std::string &NameToUse, 207 DIEValue ValName); 208 /// Processes a DIE with references to other DIEs for DW_AT_name and 209 /// DW_AT_linkage_name resolution. 210 /// If DW_AT_name exists method creates a new entry for this DIE and returns 211 /// it. 212 std::optional<BOLTDWARF5AccelTableData *> processReferencedDie( 213 DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID, 214 const std::optional<BOLTDWARF5AccelTableData *> &Parent, 215 const std::string &NameToUse, const uint32_t NumberParentsInChain, 216 const dwarf::Attribute &Attr); 217 }; 218 } // namespace bolt 219 } // namespace llvm 220 #endif 221