1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
| //==- SymbolCache.h - Cache of native symbols and ids ------------*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/Support/Allocator.h"
#include <memory>
#include <vector>
namespace llvm {
namespace pdb {
class DbiStream;
class PDBFile;
class SymbolCache {
NativeSession &Session;
DbiStream *Dbi = nullptr;
/// Cache of all stable symbols, indexed by SymIndexId. Just because a
/// symbol has been parsed does not imply that it will be stable and have
/// an Id. Id allocation is an implementation, with the only guarantee
/// being that once an Id is allocated, the symbol can be assumed to be
/// cached.
std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
/// For type records from the TPI stream which have been paresd and cached,
/// stores a mapping to SymIndexId of the cached symbol.
DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
/// For field list members which have been parsed and cached, stores a mapping
/// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
/// cached symbol.
DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
FieldListMembersToSymbolId;
/// List of SymIndexIds for each compiland, indexed by compiland index as they
/// appear in the PDB file.
std::vector<SymIndexId> Compilands;
/// Map from global symbol offset to SymIndexId.
DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
SymIndexId createSymbolPlaceholder() {
SymIndexId Id = Cache.size();
Cache.push_back(nullptr);
return Id;
}
template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
Args &&... ConstructorArgs) {
CVRecordT Record;
if (auto EC =
codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
consumeError(std::move(EC));
return 0;
}
return createSymbol<ConcreteSymbolT>(
TI, std::move(Record), std::forward<Args>(ConstructorArgs)...);
}
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
codeview::CVType CVT);
SymIndexId createSimpleType(codeview::TypeIndex TI,
codeview::ModifierOptions Mods);
public:
SymbolCache(NativeSession &Session, DbiStream *Dbi);
template <typename ConcreteSymbolT, typename... Args>
SymIndexId createSymbol(Args &&... ConstructorArgs) {
SymIndexId Id = Cache.size();
// Initial construction must not access the cache, since it must be done
// atomically.
auto Result = std::make_unique<ConcreteSymbolT>(
Session, Id, std::forward<Args>(ConstructorArgs)...);
Result->SymbolId = Id;
NativeRawSymbol *NRS = static_cast<NativeRawSymbol *>(Result.get());
Cache.push_back(std::move(Result));
// After the item is in the cache, we can do further initialization which
// is then allowed to access the cache.
NRS->initialize();
return Id;
}
std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(codeview::TypeLeafKind Kind);
std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds);
std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind);
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
template <typename ConcreteSymbolT, typename... Args>
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
uint32_t Index,
Args &&... ConstructorArgs) {
SymIndexId SymId = Cache.size();
std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index};
auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId);
if (Result.second)
SymId =
createSymbol<ConcreteSymbolT>(std::forward<Args>(ConstructorArgs)...);
else
SymId = Result.first->second;
return SymId;
}
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
uint32_t getNumCompilands() const;
std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const;
NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const;
template <typename ConcreteT>
ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
}
};
} // namespace pdb
} // namespace llvm
#endif
|