mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2026-01-31 01:35:20 +01:00
Part of the responsibility of the native PDB reader is to cache symbols the first time they are accessed, so they can then be looked up by an ID. Furthermore, we need to resolve type indices to records that we vend to the user, and other things. Previously this code was all thrown together a bit haphazardly in the native session class, but it makes sense to collect all of this into a single class whose sole responsibility is to manage the collection of known symbols. llvm-svn: 341608
148 lines
5.1 KiB
C++
148 lines
5.1 KiB
C++
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
|
|
|
|
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
|
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
|
|
#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
|
|
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
|
|
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
|
|
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
|
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
|
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
|
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
|
|
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::pdb;
|
|
|
|
// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
|
|
// to instantiate a NativeBuiltinSymbol for that type.
|
|
static const struct BuiltinTypeEntry {
|
|
codeview::SimpleTypeKind Kind;
|
|
PDB_BuiltinType Type;
|
|
uint32_t Size;
|
|
} BuiltinTypes[] = {
|
|
{codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
|
|
{codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
|
|
{codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
|
|
{codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
|
|
{codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
|
|
{codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
|
|
{codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
|
|
{codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
|
|
{codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
|
|
// This table can be grown as necessary, but these are the only types we've
|
|
// needed so far.
|
|
};
|
|
|
|
SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
|
|
: Session(Session), Dbi(Dbi) {
|
|
// Id 0 is reserved for the invalid symbol.
|
|
Cache.push_back(nullptr);
|
|
|
|
if (Dbi)
|
|
Compilands.resize(Dbi->modules().getModuleCount());
|
|
}
|
|
|
|
std::unique_ptr<PDBSymbolTypeEnum>
|
|
SymbolCache::createEnumSymbol(codeview::TypeIndex Index) {
|
|
const auto Id = findSymbolByTypeIndex(Index);
|
|
return PDBSymbol::createAs<PDBSymbolTypeEnum>(Session, *Cache[Id]);
|
|
}
|
|
|
|
std::unique_ptr<IPDBEnumSymbols>
|
|
SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
|
|
auto Tpi = Session.getPDBFile().getPDBTpiStream();
|
|
if (!Tpi) {
|
|
consumeError(Tpi.takeError());
|
|
return nullptr;
|
|
}
|
|
auto &Types = Tpi->typeCollection();
|
|
return std::unique_ptr<IPDBEnumSymbols>(
|
|
new NativeEnumTypes(Session, Types, codeview::LF_ENUM));
|
|
}
|
|
|
|
SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
|
// First see if it's already in our cache.
|
|
const auto Entry = TypeIndexToSymbolId.find(Index);
|
|
if (Entry != TypeIndexToSymbolId.end())
|
|
return Entry->second;
|
|
|
|
// Symbols for built-in types are created on the fly.
|
|
if (Index.isSimple()) {
|
|
// FIXME: We will eventually need to handle pointers to other simple types,
|
|
// which are still simple types in the world of CodeView TypeIndexes.
|
|
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
|
|
return 0;
|
|
const auto Kind = Index.getSimpleKind();
|
|
const auto It =
|
|
std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
|
|
[Kind](const BuiltinTypeEntry &Builtin) {
|
|
return Builtin.Kind == Kind;
|
|
});
|
|
if (It == std::end(BuiltinTypes))
|
|
return 0;
|
|
SymIndexId Id = Cache.size();
|
|
Cache.emplace_back(llvm::make_unique<NativeBuiltinSymbol>(
|
|
Session, Id, It->Type, It->Size));
|
|
TypeIndexToSymbolId[Index] = Id;
|
|
return Id;
|
|
}
|
|
|
|
// We need to instantiate and cache the desired type symbol.
|
|
auto Tpi = Session.getPDBFile().getPDBTpiStream();
|
|
if (!Tpi) {
|
|
consumeError(Tpi.takeError());
|
|
return 0;
|
|
}
|
|
codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
|
|
const codeview::CVType &CVT = Types.getType(Index);
|
|
// TODO(amccarth): Make this handle all types, not just LF_ENUMs.
|
|
SymIndexId Id = 0;
|
|
switch (CVT.kind()) {
|
|
case codeview::LF_ENUM:
|
|
Id = createSymbol<NativeEnumSymbol>(CVT);
|
|
break;
|
|
default:
|
|
assert(false && "Unsupported native symbol type!");
|
|
return 0;
|
|
}
|
|
TypeIndexToSymbolId[Index] = Id;
|
|
return Id;
|
|
}
|
|
|
|
std::unique_ptr<PDBSymbol>
|
|
SymbolCache::getSymbolById(SymIndexId SymbolId) const {
|
|
// If the caller has a SymbolId, it'd better be in our SymbolCache.
|
|
return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId])
|
|
: nullptr;
|
|
}
|
|
|
|
NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
|
|
return *Cache[SymbolId];
|
|
}
|
|
|
|
uint32_t SymbolCache::getNumCompilands() const {
|
|
if (!Dbi)
|
|
return 0;
|
|
|
|
return Dbi->modules().getModuleCount();
|
|
}
|
|
|
|
std::unique_ptr<PDBSymbolCompiland>
|
|
SymbolCache::getOrCreateCompiland(uint32_t Index) {
|
|
if (!Dbi)
|
|
return nullptr;
|
|
|
|
if (Index >= Compilands.size())
|
|
return nullptr;
|
|
|
|
if (Compilands[Index] == 0) {
|
|
const DbiModuleList &Modules = Dbi->modules();
|
|
Compilands[Index] =
|
|
createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
|
|
}
|
|
|
|
return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
|
|
}
|