xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //==- SymbolCache.h - Cache of native symbols and ids ------------*- 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_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
10 #define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
11 
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/DebugInfo/CodeView/CVRecord.h"
14 #include "llvm/DebugInfo/CodeView/CodeView.h"
15 #include "llvm/DebugInfo/CodeView/Line.h"
16 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
17 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
18 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
19 #include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
20 #include "llvm/DebugInfo/PDB/PDBTypes.h"
21 #include "llvm/Support/Compiler.h"
22 
23 #include <memory>
24 #include <vector>
25 
26 namespace llvm {
27 namespace codeview {
28 class InlineSiteSym;
29 struct FileChecksumEntry;
30 } // namespace codeview
31 namespace pdb {
32 class IPDBSourceFile;
33 class NativeSession;
34 class PDBSymbol;
35 class PDBSymbolCompiland;
36 class DbiStream;
37 
38 class SymbolCache {
39   NativeSession &Session;
40   DbiStream *Dbi = nullptr;
41 
42   /// Cache of all stable symbols, indexed by SymIndexId.  Just because a
43   /// symbol has been parsed does not imply that it will be stable and have
44   /// an Id.  Id allocation is an implementation, with the only guarantee
45   /// being that once an Id is allocated, the symbol can be assumed to be
46   /// cached.
47   mutable std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
48 
49   /// For type records from the TPI stream which have been paresd and cached,
50   /// stores a mapping to SymIndexId of the cached symbol.
51   mutable DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
52 
53   /// For field list members which have been parsed and cached, stores a mapping
54   /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
55   /// cached symbol.
56   mutable DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
57       FieldListMembersToSymbolId;
58 
59   /// List of SymIndexIds for each compiland, indexed by compiland index as they
60   /// appear in the PDB file.
61   mutable std::vector<SymIndexId> Compilands;
62 
63   /// List of source files, indexed by unique source file index.
64   mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
65 
66   /// Map from string table offset to source file Id.
67   mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
68 
69   /// Map from global symbol offset to SymIndexId.
70   mutable DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
71 
72   /// Map from segment and code offset to function symbols.
73   mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
74   /// Map from segment and code offset to public symbols.
75   mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId>
76       AddressToPublicSymId;
77 
78   /// Map from module index and symbol table offset to SymIndexId.
79   mutable DenseMap<std::pair<uint16_t, uint32_t>, SymIndexId>
80       SymTabOffsetToSymbolId;
81 
82   struct LineTableEntry {
83     uint64_t Addr;
84     codeview::LineInfo Line;
85     uint32_t ColumnNumber;
86     uint32_t FileNameIndex;
87     bool IsTerminalEntry;
88   };
89 
90   std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
91   mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
92 
createSymbolPlaceholder()93   SymIndexId createSymbolPlaceholder() const {
94     SymIndexId Id = Cache.size();
95     Cache.push_back(nullptr);
96     return Id;
97   }
98 
99   template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
createSymbolForType(codeview::TypeIndex TI,codeview::CVType CVT,Args &&...ConstructorArgs)100   SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
101                                  Args &&...ConstructorArgs) const {
102     CVRecordT Record;
103     if (auto EC =
104             codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
105       consumeError(std::move(EC));
106       return 0;
107     }
108 
109     return createSymbol<ConcreteSymbolT>(
110         TI, std::move(Record), std::forward<Args>(ConstructorArgs)...);
111   }
112 
113   SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
114                                          codeview::CVType CVT) const;
115 
116   SymIndexId createSimpleType(codeview::TypeIndex TI,
117                               codeview::ModifierOptions Mods) const;
118 
119   std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
120                                                             uint32_t Offset);
121   std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect,
122                                                           uint32_t Offset);
123 
124 public:
125   LLVM_ABI SymbolCache(NativeSession &Session, DbiStream *Dbi);
126 
127   template <typename ConcreteSymbolT, typename... Args>
createSymbol(Args &&...ConstructorArgs)128   SymIndexId createSymbol(Args &&...ConstructorArgs) const {
129     SymIndexId Id = Cache.size();
130 
131     // Initial construction must not access the cache, since it must be done
132     // atomically.
133     auto Result = std::make_unique<ConcreteSymbolT>(
134         Session, Id, std::forward<Args>(ConstructorArgs)...);
135     Result->SymbolId = Id;
136 
137     NativeRawSymbol *NRS = static_cast<NativeRawSymbol *>(Result.get());
138     Cache.push_back(std::move(Result));
139 
140     // After the item is in the cache, we can do further initialization which
141     // is then allowed to access the cache.
142     NRS->initialize();
143     return Id;
144   }
145 
146   LLVM_ABI std::unique_ptr<IPDBEnumSymbols>
147   createTypeEnumerator(codeview::TypeLeafKind Kind);
148 
149   LLVM_ABI std::unique_ptr<IPDBEnumSymbols>
150   createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds);
151 
152   LLVM_ABI std::unique_ptr<IPDBEnumSymbols>
153   createGlobalsEnumerator(codeview::SymbolKind Kind);
154 
155   LLVM_ABI SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const;
156 
157   template <typename ConcreteSymbolT, typename... Args>
getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,uint32_t Index,Args &&...ConstructorArgs)158   SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
159                                         uint32_t Index,
160                                         Args &&... ConstructorArgs) {
161     SymIndexId SymId = Cache.size();
162     std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index};
163     auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId);
164     if (Result.second)
165       SymId =
166           createSymbol<ConcreteSymbolT>(std::forward<Args>(ConstructorArgs)...);
167     else
168       SymId = Result.first->second;
169     return SymId;
170   }
171 
172   LLVM_ABI SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
173   LLVM_ABI SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym,
174                                               uint64_t ParentAddr,
175                                               uint16_t Modi,
176                                               uint32_t RecordOffset) const;
177 
178   LLVM_ABI std::unique_ptr<PDBSymbol>
179   findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
180 
181   LLVM_ABI std::unique_ptr<IPDBEnumLineNumbers>
182   findLineNumbersByVA(uint64_t VA, uint32_t Length) const;
183 
184   LLVM_ABI std::unique_ptr<PDBSymbolCompiland>
185   getOrCreateCompiland(uint32_t Index);
186   LLVM_ABI uint32_t getNumCompilands() const;
187 
188   LLVM_ABI std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const;
189 
190   LLVM_ABI NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const;
191 
192   template <typename ConcreteT>
getNativeSymbolById(SymIndexId SymbolId)193   ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
194     return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
195   }
196 
197   LLVM_ABI std::unique_ptr<IPDBSourceFile>
198   getSourceFileById(SymIndexId FileId) const;
199   LLVM_ABI SymIndexId
200   getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
201 };
202 
203 } // namespace pdb
204 } // namespace llvm
205 
206 #endif
207