xref: /llvm-project/bolt/include/bolt/Core/DebugNames.h (revision 4b825c7417f72ee88ee3e4316d0c01ed463f1241)
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