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

source code of llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h