1 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
2 
3 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
4 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
5 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
6 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
7 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
8 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
9 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
10 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
11 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
12 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
13 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
17 
18 using namespace llvm;
19 using namespace llvm::codeview;
20 using namespace llvm::pdb;
21 
22 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
23 // to instantiate a NativeBuiltinSymbol for that type.
24 static const struct BuiltinTypeEntry {
25   codeview::SimpleTypeKind Kind;
26   PDB_BuiltinType Type;
27   uint32_t Size;
28 } BuiltinTypes[] = {
29     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
30     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
31     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
32     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
33     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
34     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
35     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
36     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
37     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
38     // This table can be grown as necessary, but these are the only types we've
39     // needed so far.
40 };
41 
42 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
43     : Session(Session), Dbi(Dbi) {
44   // Id 0 is reserved for the invalid symbol.
45   Cache.push_back(nullptr);
46 
47   if (Dbi)
48     Compilands.resize(Dbi->modules().getModuleCount());
49 }
50 
51 std::unique_ptr<IPDBEnumSymbols>
52 SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
53   auto Tpi = Session.getPDBFile().getPDBTpiStream();
54   if (!Tpi) {
55     consumeError(Tpi.takeError());
56     return nullptr;
57   }
58   auto &Types = Tpi->typeCollection();
59   return std::unique_ptr<IPDBEnumSymbols>(
60       new NativeEnumTypes(Session, Types, Kind));
61 }
62 
63 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
64   // First see if it's already in our cache.
65   const auto Entry = TypeIndexToSymbolId.find(Index);
66   if (Entry != TypeIndexToSymbolId.end())
67     return Entry->second;
68 
69   // Symbols for built-in types are created on the fly.
70   if (Index.isSimple()) {
71     // FIXME:  We will eventually need to handle pointers to other simple types,
72     // which are still simple types in the world of CodeView TypeIndexes.
73     if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
74       return 0;
75     const auto Kind = Index.getSimpleKind();
76     const auto It =
77         std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
78                      [Kind](const BuiltinTypeEntry &Builtin) {
79                        return Builtin.Kind == Kind;
80                      });
81     if (It == std::end(BuiltinTypes))
82       return 0;
83     SymIndexId Id = Cache.size();
84     Cache.emplace_back(
85         llvm::make_unique<NativeTypeBuiltin>(Session, Id, It->Type, It->Size));
86     TypeIndexToSymbolId[Index] = Id;
87     return Id;
88   }
89 
90   // We need to instantiate and cache the desired type symbol.
91   auto Tpi = Session.getPDBFile().getPDBTpiStream();
92   if (!Tpi) {
93     consumeError(Tpi.takeError());
94     return 0;
95   }
96   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
97   codeview::CVType CVT = Types.getType(Index);
98   // TODO(amccarth):  Make this handle all types.
99   SymIndexId Id = 0;
100   switch (CVT.kind()) {
101   case codeview::LF_ENUM:
102     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
103     break;
104   case codeview::LF_POINTER:
105     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
106                                                                std::move(CVT));
107     break;
108   default:
109     Id = createSymbolPlaceholder();
110     break;
111   }
112   if (Id != 0)
113     TypeIndexToSymbolId[Index] = Id;
114   return Id;
115 }
116 
117 std::unique_ptr<PDBSymbol>
118 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
119   // Id 0 is reserved.
120   if (SymbolId == 0)
121     return nullptr;
122 
123   // If the caller has a SymbolId, it'd better be in our SymbolCache.
124   return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId])
125                                  : nullptr;
126 }
127 
128 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
129   return *Cache[SymbolId];
130 }
131 
132 uint32_t SymbolCache::getNumCompilands() const {
133   if (!Dbi)
134     return 0;
135 
136   return Dbi->modules().getModuleCount();
137 }
138 
139 std::unique_ptr<PDBSymbolCompiland>
140 SymbolCache::getOrCreateCompiland(uint32_t Index) {
141   if (!Dbi)
142     return nullptr;
143 
144   if (Index >= Compilands.size())
145     return nullptr;
146 
147   if (Compilands[Index] == 0) {
148     const DbiModuleList &Modules = Dbi->modules();
149     Compilands[Index] =
150         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
151   }
152 
153   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
154 }
155