forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			300 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 | 
						|
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.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/NativeTypeArray.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/SymbolStream.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::codeview;
 | 
						|
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::None, PDB_BuiltinType::None, 0},
 | 
						|
    {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
 | 
						|
    {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
 | 
						|
    {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
 | 
						|
    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
 | 
						|
    {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
 | 
						|
    {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
 | 
						|
    {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
 | 
						|
    {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
 | 
						|
    {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
 | 
						|
    {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
 | 
						|
    {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
 | 
						|
    {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
 | 
						|
    {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
 | 
						|
    {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
 | 
						|
    {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
 | 
						|
    {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
 | 
						|
    {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
 | 
						|
    {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
 | 
						|
    {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
 | 
						|
    {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<IPDBEnumSymbols>
 | 
						|
SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
 | 
						|
  return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
 | 
						|
}
 | 
						|
 | 
						|
std::unique_ptr<IPDBEnumSymbols>
 | 
						|
SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
 | 
						|
  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, std::move(Kinds)));
 | 
						|
}
 | 
						|
 | 
						|
std::unique_ptr<IPDBEnumSymbols>
 | 
						|
SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
 | 
						|
  return std::unique_ptr<IPDBEnumSymbols>(
 | 
						|
      new NativeEnumGlobals(Session, {Kind}));
 | 
						|
}
 | 
						|
 | 
						|
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
 | 
						|
                                         ModifierOptions Mods) {
 | 
						|
  if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
 | 
						|
    return createSymbol<NativeTypePointer>(Index);
 | 
						|
 | 
						|
  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;
 | 
						|
  return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
 | 
						|
}
 | 
						|
 | 
						|
SymIndexId
 | 
						|
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
 | 
						|
                                         codeview::CVType CVT) {
 | 
						|
  ModifierRecord Record;
 | 
						|
  if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
 | 
						|
    consumeError(std::move(EC));
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Record.ModifiedType.isSimple())
 | 
						|
    return createSimpleType(Record.ModifiedType, Record.Modifiers);
 | 
						|
 | 
						|
  // Make sure we create and cache a record for the unmodified type.
 | 
						|
  SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
 | 
						|
  NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
 | 
						|
 | 
						|
  switch (UnmodifiedNRS.getSymTag()) {
 | 
						|
  case PDB_SymType::Enum:
 | 
						|
    return createSymbol<NativeTypeEnum>(
 | 
						|
        static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
 | 
						|
  case PDB_SymType::UDT:
 | 
						|
    return createSymbol<NativeTypeUDT>(
 | 
						|
        static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
 | 
						|
  default:
 | 
						|
    // No other types can be modified.  (LF_POINTER, for example, records
 | 
						|
    // its modifiers a different way.
 | 
						|
    assert(false && "Invalid LF_MODIFIER record");
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
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()) {
 | 
						|
    SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
 | 
						|
    assert(TypeIndexToSymbolId.count(Index) == 0);
 | 
						|
    TypeIndexToSymbolId[Index] = Result;
 | 
						|
    return Result;
 | 
						|
  }
 | 
						|
 | 
						|
  // 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();
 | 
						|
  codeview::CVType CVT = Types.getType(Index);
 | 
						|
 | 
						|
  if (isUdtForwardRef(CVT)) {
 | 
						|
    Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
 | 
						|
 | 
						|
    if (!EFD)
 | 
						|
      consumeError(EFD.takeError());
 | 
						|
    else if (*EFD != Index) {
 | 
						|
      assert(!isUdtForwardRef(Types.getType(*EFD)));
 | 
						|
      SymIndexId Result = findSymbolByTypeIndex(*EFD);
 | 
						|
      // Record a mapping from ForwardRef -> SymIndex of complete type so that
 | 
						|
      // we'll take the fast path next time.
 | 
						|
      assert(TypeIndexToSymbolId.count(Index) == 0);
 | 
						|
      TypeIndexToSymbolId[Index] = Result;
 | 
						|
      return Result;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // At this point if we still have a forward ref udt it means the full decl was
 | 
						|
  // not in the PDB.  We just have to deal with it and use the forward ref.
 | 
						|
  SymIndexId Id = 0;
 | 
						|
  switch (CVT.kind()) {
 | 
						|
  case codeview::LF_ENUM:
 | 
						|
    Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_ARRAY:
 | 
						|
    Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
 | 
						|
                                                           std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_CLASS:
 | 
						|
  case codeview::LF_STRUCTURE:
 | 
						|
  case codeview::LF_INTERFACE:
 | 
						|
    Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_UNION:
 | 
						|
    Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_POINTER:
 | 
						|
    Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
 | 
						|
                                                               std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_MODIFIER:
 | 
						|
    Id = createSymbolForModifiedType(Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_PROCEDURE:
 | 
						|
    Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
 | 
						|
        Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_MFUNCTION:
 | 
						|
    Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
 | 
						|
        Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  case codeview::LF_VTSHAPE:
 | 
						|
    Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
 | 
						|
        Index, std::move(CVT));
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    Id = createSymbolPlaceholder();
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  if (Id != 0) {
 | 
						|
    assert(TypeIndexToSymbolId.count(Index) == 0);
 | 
						|
    TypeIndexToSymbolId[Index] = Id;
 | 
						|
  }
 | 
						|
  return Id;
 | 
						|
}
 | 
						|
 | 
						|
std::unique_ptr<PDBSymbol>
 | 
						|
SymbolCache::getSymbolById(SymIndexId SymbolId) const {
 | 
						|
  assert(SymbolId < Cache.size());
 | 
						|
 | 
						|
  // Id 0 is reserved.
 | 
						|
  if (SymbolId == 0 || SymbolId >= Cache.size())
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  // Make sure to handle the case where we've inserted a placeholder symbol
 | 
						|
  // for types we don't yet suppport.
 | 
						|
  NativeRawSymbol *NRS = Cache[SymbolId].get();
 | 
						|
  if (!NRS)
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  return PDBSymbol::create(Session, *NRS);
 | 
						|
}
 | 
						|
 | 
						|
NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
 | 
						|
  return *Cache[SymbolId];
 | 
						|
}
 | 
						|
 | 
						|
uint32_t SymbolCache::getNumCompilands() const {
 | 
						|
  if (!Dbi)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  return Dbi->modules().getModuleCount();
 | 
						|
}
 | 
						|
 | 
						|
SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
 | 
						|
  auto Iter = GlobalOffsetToSymbolId.find(Offset);
 | 
						|
  if (Iter != GlobalOffsetToSymbolId.end())
 | 
						|
    return Iter->second;
 | 
						|
 | 
						|
  SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
 | 
						|
  CVSymbol CVS = SS.readRecord(Offset);
 | 
						|
  SymIndexId Id = 0;
 | 
						|
  switch (CVS.kind()) {
 | 
						|
  case SymbolKind::S_UDT: {
 | 
						|
    UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
 | 
						|
    Id = createSymbol<NativeTypeTypedef>(std::move(US));
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  default:
 | 
						|
    Id = createSymbolPlaceholder();
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  if (Id != 0) {
 | 
						|
    assert(GlobalOffsetToSymbolId.count(Offset) == 0);
 | 
						|
    GlobalOffsetToSymbolId[Offset] = Id;
 | 
						|
  }
 | 
						|
 | 
						|
  return Id;
 | 
						|
}
 | 
						|
 | 
						|
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]);
 | 
						|
}
 |