summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/CompileUnit.h5
-rw-r--r--lldb/lit/SymbolFile/NativePDB/typedefs.cpp71
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp186
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp17
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp115
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h3
8 files changed, 349 insertions, 61 deletions
diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index ea7292912b1..a4d19cd3d8a 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -409,6 +409,11 @@ public:
//------------------------------------------------------------------
bool GetIsOptimized();
+ //------------------------------------------------------------------
+ /// Returns the number of functions in this compile unit
+ //------------------------------------------------------------------
+ size_t GetNumFunctions() const { return m_functions_by_uid.size(); }
+
protected:
void *m_user_data; ///< User data for the SymbolFile parser to store
///information into.
diff --git a/lldb/lit/SymbolFile/NativePDB/typedefs.cpp b/lldb/lit/SymbolFile/NativePDB/typedefs.cpp
new file mode 100644
index 00000000000..738fbe615d9
--- /dev/null
+++ b/lldb/lit/SymbolFile/NativePDB/typedefs.cpp
@@ -0,0 +1,71 @@
+// clang-format off
+
+// REQUIRES: system-windows
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols -dump-ast %t.exe | FileCheck %s
+
+namespace A {
+ namespace B {
+ using NamespaceTypedef = double;
+ }
+ template<typename T>
+ class C {
+ public:
+ using ClassTypedef = T;
+ };
+ using ClassTypedef = C<char>::ClassTypedef;
+ using ClassTypedef2 = C<wchar_t>::ClassTypedef;
+
+ template<typename T>
+ using AliasTemplate = typename C<T>::ClassTypedef;
+}
+
+namespace {
+ using AnonNamespaceTypedef = bool;
+}
+
+using IntTypedef = int;
+
+using ULongArrayTypedef = unsigned long[10];
+
+using RefTypedef = long double*&;
+
+using FuncPtrTypedef = long long(*)(int&, unsigned char**, short[], const double, volatile bool);
+
+using VarArgsFuncTypedef = char(*)(void*, long, unsigned short, unsigned int, ...);
+
+using VarArgsFuncTypedefA = float(*)(...);
+
+int main(int argc, char **argv) {
+ long double *Ptr;
+
+ A::B::NamespaceTypedef *X0;
+ A::C<char>::ClassTypedef *X1;
+ A::C<wchar_t>::ClassTypedef *X2;
+ AnonNamespaceTypedef *X3;
+ IntTypedef *X4;
+ ULongArrayTypedef *X5;
+ RefTypedef X6 = Ptr;
+ FuncPtrTypedef X7;
+ VarArgsFuncTypedef X8;
+ VarArgsFuncTypedefA X9;
+ A::AliasTemplate<float> X10;
+ return 0;
+}
+
+
+// CHECK: namespace `anonymous namespace' {
+// CHECK-NEXT: typedef bool AnonNamespaceTypedef;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef unsigned long ULongArrayTypedef[10];
+// CHECK-NEXT: typedef double *&RefTypedef;
+// CHECK-NEXT: namespace A {
+// CHECK-NEXT: namespace B {
+// CHECK-NEXT: typedef double NamespaceTypedef;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef float AliasTemplate<float>;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef long long (*FuncPtrTypedef)(int &, unsigned char **, short *, const double, volatile bool);
+// CHECK-NEXT: typedef char (*VarArgsFuncTypedef)(void *, long, unsigned short, unsigned int, ...);
+// CHECK-NEXT: typedef float (*VarArgsFuncTypedefA)(...);
+// CHECK-NEXT: typedef int IntTypedef;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index e340c3d4d44..8917fd09238 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -2,6 +2,7 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
@@ -13,6 +14,7 @@
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Demangle/MicrosoftDemangle.h"
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
@@ -215,10 +217,15 @@ clang::DeclContext &PdbAstBuilder::GetTranslationUnitDecl() {
std::pair<clang::DeclContext *, std::string>
PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
// FIXME: Move this to GetDeclContextContainingUID.
+ if (!record.hasUniqueName())
+ return CreateDeclInfoForUndecoratedName(record.Name);
llvm::ms_demangle::Demangler demangler;
StringView sv(record.UniqueName.begin(), record.UniqueName.size());
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+ if (demangler.Error)
+ return {m_clang.GetTranslationUnitDecl(), record.UniqueName};
+
llvm::ms_demangle::IdentifierNode *idn =
ttn->QualifiedName->getUnqualifiedIdentifier();
std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);
@@ -491,6 +498,82 @@ clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
return clang::Decl::castToDeclContext(decl);
}
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ clang::DeclContext *context = &GetTranslationUnitDecl();
+
+ llvm::StringRef uname = specs.back().GetBaseName();
+ specs = specs.drop_back();
+ if (specs.empty())
+ return {context, name};
+
+ llvm::StringRef scope_name = specs.back().GetFullName();
+
+ // It might be a class name, try that first.
+ std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name);
+ while (!types.empty()) {
+ clang::QualType qt = GetOrCreateType(types.back());
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (tag)
+ return {clang::TagDecl::castToDeclContext(tag), uname};
+ types.pop_back();
+ }
+
+ // If that fails, treat it as a series of namespaces.
+ for (const MSVCUndecoratedNameSpecifier &spec : specs) {
+ std::string ns_name = spec.GetBaseName().str();
+ context = m_clang.GetUniqueNamespaceDeclaration(ns_name.c_str(), context);
+ }
+ return {context, uname};
+}
+
+clang::DeclContext *
+PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) {
+ if (!SymbolHasAddress(sym))
+ return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+ SegmentOffset addr = GetSegmentAndOffset(sym);
+ llvm::Optional<PublicSym32> pub =
+ FindPublicSym(addr, m_index.symrecords(), m_index.publics());
+ if (!pub)
+ return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+
+ llvm::ms_demangle::Demangler demangler;
+ StringView name{pub->Name.begin(), pub->Name.size()};
+ llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+ if (!node)
+ return &GetTranslationUnitDecl();
+ llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
+ node->Name->Components->Nodes, node->Name->Components->Count - 1};
+
+ if (!name_components.empty()) {
+ // Render the current list of scope nodes as a fully qualified name, and
+ // look it up in the debug info as a type name. If we find something,
+ // this is a type (which may itself be prefixed by a namespace). If we
+ // don't, this is a list of namespaces.
+ std::string qname = RenderScopeList(name_components);
+ std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
+ while (!matches.empty()) {
+ clang::QualType qt = GetOrCreateType(matches.back());
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (tag)
+ return clang::TagDecl::castToDeclContext(tag);
+ matches.pop_back();
+ }
+ }
+
+ // It's not a type. It must be a series of namespaces.
+ clang::DeclContext *context = &GetTranslationUnitDecl();
+ while (!name_components.empty()) {
+ std::string ns = name_components.front()->toString();
+ context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
+ name_components = name_components.drop_front();
+ }
+ return context;
+}
+
clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
// We must do this *without* calling GetOrCreate on the current uid, as
// that would be an infinite recursion.
@@ -502,46 +585,7 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
return GetOrCreateDeclContextForUid(*scope);
CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
- if (!SymbolHasAddress(sym))
- return &GetTranslationUnitDecl();
- SegmentOffset addr = GetSegmentAndOffset(sym);
- llvm::Optional<PublicSym32> pub =
- FindPublicSym(addr, m_index.symrecords(), m_index.publics());
- if (!pub)
- return &GetTranslationUnitDecl();
-
- llvm::ms_demangle::Demangler demangler;
- StringView name{pub->Name.begin(), pub->Name.size()};
- llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
- if (!node)
- return &GetTranslationUnitDecl();
- llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
- node->Name->Components->Nodes, node->Name->Components->Count - 1};
-
- if (!name_components.empty()) {
- // Render the current list of scope nodes as a fully qualified name, and
- // look it up in the debug info as a type name. If we find something,
- // this is a type (which may itself be prefixed by a namespace). If we
- // don't, this is a list of namespaces.
- std::string qname = RenderScopeList(name_components);
- std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
- while (!matches.empty()) {
- clang::QualType qt = GetOrCreateType(matches.back());
- clang::TagDecl *tag = qt->getAsTagDecl();
- if (tag)
- return clang::TagDecl::castToDeclContext(tag);
- matches.pop_back();
- }
- }
-
- // It's not a type. It must be a series of namespaces.
- clang::DeclContext *context = &GetTranslationUnitDecl();
- while (!name_components.empty()) {
- std::string ns = name_components.front()->toString();
- context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
- name_components = name_components.drop_front();
- }
- return context;
+ return GetParentDeclContextForSymbol(sym);
}
case PdbSymUidKind::Type: {
// It could be a namespace, class, or global. We don't support nested
@@ -556,6 +600,34 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
// In this case the parent DeclContext is the one for the class that this
// member is inside of.
break;
+ case PdbSymUidKind::GlobalSym: {
+ // If this refers to a compiland symbol, just recurse in with that symbol.
+ // The only other possibilities are S_CONSTANT and S_UDT, in which case we
+ // need to parse the undecorated name to figure out the scope, then look
+ // that up in the TPI stream. If it's found, it's a type, othewrise it's
+ // a series of namespaces.
+ // FIXME: do this.
+ CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym());
+ switch (global.kind()) {
+ case SymbolKind::S_GDATA32:
+ case SymbolKind::S_LDATA32:
+ return GetParentDeclContextForSymbol(global);
+ case SymbolKind::S_PROCREF:
+ case SymbolKind::S_LPROCREF: {
+ ProcRefSym ref{global.kind()};
+ llvm::cantFail(
+ SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));
+ PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};
+ return GetParentDeclContext(cu_sym_id);
+ }
+ case SymbolKind::S_CONSTANT:
+ case SymbolKind::S_UDT:
+ return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;
+ default:
+ break;
+ }
+ break;
+ }
default:
break;
}
@@ -645,6 +717,11 @@ clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType);
+ // This can happen for pointers to LF_VTSHAPE records, which we shouldn't
+ // create in the AST.
+ if (pointee_type.isNull())
+ return {};
+
if (pointer.isPointerToMember()) {
MemberPointerInfo mpi = pointer.getMemberInfo();
clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
@@ -677,8 +754,9 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
clang::QualType
PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {
-
clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType);
+ if (unmodified_type.isNull())
+ return {};
if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
unmodified_type.addConst();
@@ -786,6 +864,32 @@ clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl());
}
+clang::TypedefNameDecl *
+PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
+ if (clang::Decl *decl = TryGetDecl(id))
+ return llvm::dyn_cast<clang::TypedefNameDecl>(decl);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(id);
+ lldbassert(sym.kind() == S_UDT);
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+ clang::DeclContext *scope = GetParentDeclContext(id);
+
+ PdbTypeSymId real_type_id{udt.Type, false};
+ clang::QualType qt = GetOrCreateType(real_type_id);
+
+ std::string uname = DropNameScope(udt.Name);
+
+ CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(),
+ ToCompilerDeclContext(*scope));
+ clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(id);
+ m_decl_to_status.insert({tnd, status});
+ return tnd;
+}
+
clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) {
CompilerType ct = m_clang.GetBasicType(type);
return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
index 9538d675171..e3c0346f935 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -69,6 +69,7 @@ public:
clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id);
clang::VarDecl *GetOrCreateVariableDecl(PdbGlobalSymId var_id);
+ clang::TypedefNameDecl *GetOrCreateTypedefDecl(PdbGlobalSymId id);
void ParseDeclsForContext(clang::DeclContext &context);
clang::QualType GetBasicType(lldb::BasicType type);
@@ -112,6 +113,8 @@ private:
clang::VarDecl *CreateVariableDecl(PdbSymUid uid,
llvm::codeview::CVSymbol sym,
clang::DeclContext &scope);
+ clang::DeclContext *
+ GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym);
void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent);
void ParseDeclsForSimpleContext(clang::DeclContext &context);
@@ -120,6 +123,8 @@ private:
void BuildParentMap();
std::pair<clang::DeclContext *, std::string>
CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);
+ std::pair<clang::DeclContext *, std::string>
+ CreateDeclInfoForUndecoratedName(llvm::StringRef uname);
clang::QualType CreateSimpleType(TypeIndex ti);
PdbIndex &m_index;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
index 72ed3a7329e..317725dd250 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -17,8 +17,8 @@
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "lldb/Utility/LLDBAssert.h"
-
#include "lldb/lldb-enumerations.h"
using namespace lldb_private;
@@ -449,16 +449,7 @@ TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
}
llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
- // Not all PDB names can be parsed with CPlusPlusNameParser.
- // E.g. it fails on names containing `anonymous namespace'.
- // So we simply drop everything before '::'
-
- auto offset = name.rfind("::");
- if (offset == llvm::StringRef::npos)
- return name;
- assert(offset + 2 <= name.size());
-
- return name.substr(offset + 2);
+ return MSVCUndecoratedNameParser::DropScope(name);
}
VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
@@ -558,10 +549,6 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
} else {
// FIXME: Handle other kinds
- llvm::APSInt value;
- value = 42;
- result.location = MakeConstantLocationExpression(
- TypeIndex::Int32(), index.tpi(), value, module);
}
return result;
}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
index 863f999a70f..570c300b6a2 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -66,6 +66,14 @@ struct CVTagRecord {
return cvunion;
}
+ llvm::StringRef name() const {
+ if (m_kind == Struct || m_kind == Union)
+ return cvclass.Name;
+ if (m_kind == Enum)
+ return cvenum.Name;
+ return cvunion.Name;
+ }
+
private:
CVTagRecord(llvm::codeview::ClassRecord &&c);
CVTagRecord(llvm::codeview::UnionRecord &&u);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 9868a3283e0..2ac0b985a6a 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamBuffer.h"
@@ -394,7 +395,11 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+ if (proc.FunctionType == TypeIndex::None())
+ return nullptr;
TypeSP func_type = GetOrCreateType(proc.FunctionType);
+ if (!func_type)
+ return nullptr;
PdbTypeSymId sig_id(proc.FunctionType, false);
Mangled mangled(proc.Name);
@@ -515,9 +520,19 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
}
static std::string GetUnqualifiedTypeName(const TagRecord &record) {
+ if (!record.hasUniqueName()) {
+ MSVCUndecoratedNameParser parser(record.Name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ return specs.back().GetBaseName();
+ }
+
llvm::ms_demangle::Demangler demangler;
StringView sv(record.UniqueName.begin(), record.UniqueName.size());
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+ if (demangler.Error)
+ return record.Name;
+
llvm::ms_demangle::IdentifierNode *idn =
ttn->QualifiedName->getUnqualifiedIdentifier();
return idn->toString();
@@ -696,7 +711,10 @@ TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
if (iter != m_types.end())
return iter->second;
- return CreateAndCacheType(type_id);
+ TypeSP type = CreateAndCacheType(type_id);
+ if (type)
+ m_obj_file->GetModule()->GetTypeList()->Insert(type);
+ return type;
}
VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
@@ -821,7 +839,6 @@ FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
if (emplace_result.second)
emplace_result.first->second = CreateFunction(func_id, comp_unit);
- lldbassert(emplace_result.first->second);
return emplace_result.first->second;
}
@@ -887,7 +904,26 @@ void SymbolFileNativePDB::AddSymbols(Symtab &symtab) { return; }
size_t SymbolFileNativePDB::ParseCompileUnitFunctions(const SymbolContext &sc) {
lldbassert(sc.comp_unit);
- return false;
+
+ PdbSymUid uid{sc.comp_unit->GetID()};
+ lldbassert(uid.kind() == PdbSymUidKind::Compiland);
+ uint16_t modi = uid.asCompiland().modi;
+ CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
+
+ size_t count = sc.comp_unit->GetNumFunctions();
+ const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+ for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
+ if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
+ continue;
+
+ PdbCompilandSymId sym_id{modi, iter.offset()};
+
+ FunctionSP func = GetOrCreateFunction(sym_id, *sc.comp_unit);
+ }
+
+ size_t new_count = sc.comp_unit->GetNumFunctions();
+ lldbassert(new_count >= count);
+ return new_count - count;
}
static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
@@ -1238,7 +1274,47 @@ size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
return match_count;
}
-size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { return 0; }
+size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) {
+ // Only do the full type scan the first time.
+ if (m_done_full_type_scan)
+ return 0;
+
+ size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+ LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
+
+ // First process the entire TPI stream.
+ for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+ TypeSP type = GetOrCreateType(*ti);
+ if (type)
+ (void)type->GetFullCompilerType();
+ }
+
+ // Next look for S_UDT records in the globals stream.
+ for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
+ PdbGlobalSymId global{gid, false};
+ CVSymbol sym = m_index->ReadSymbolRecord(global);
+ if (sym.kind() != S_UDT)
+ continue;
+
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+ bool is_typedef = true;
+ if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
+ CVType cvt = m_index->tpi().getType(udt.Type);
+ llvm::StringRef name = CVTagRecord::create(cvt).name();
+ if (name == udt.Name)
+ is_typedef = false;
+ }
+
+ if (is_typedef)
+ GetOrCreateTypedef(global);
+ }
+
+ size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+
+ m_done_full_type_scan = true;
+
+ return new_count - old_count;
+}
size_t
SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
@@ -1253,6 +1329,8 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
bool is_param) {
ModuleSP module = GetObjectFile()->GetModule();
VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
+ if (!var_info.location || !var_info.ranges)
+ return nullptr;
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
@@ -1285,6 +1363,32 @@ VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
return CreateLocalVariable(scope_id, var_id, is_param);
}
+TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
+ CVSymbol sym = m_index->ReadSymbolRecord(id);
+ lldbassert(sym.kind() == SymbolKind::S_UDT);
+
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+ TypeSP target_type = GetOrCreateType(udt.Type);
+
+ (void)m_ast->GetOrCreateTypedefDecl(id);
+
+ Declaration decl;
+ return std::make_shared<lldb_private::Type>(
+ toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(),
+ nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
+ decl, target_type->GetForwardCompilerType(),
+ lldb_private::Type::eResolveStateForward);
+}
+
+TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
+ auto iter = m_types.find(toOpaqueUid(id));
+ if (iter != m_types.end())
+ return iter->second;
+
+ return CreateTypedef(id);
+}
+
size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
Block &block = GetOrCreateBlock(block_id);
@@ -1349,7 +1453,8 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
if (is_param)
--params_remaining;
- variables->AddVariableIfUnique(variable);
+ if (variable)
+ variables->AddVariableIfUnique(variable);
break;
default:
break;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index bb119a06d5d..2b112516407 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -203,12 +203,14 @@ private:
lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id,
bool is_param);
+ lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);
lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,
CompileUnit &comp_unit);
Block &CreateBlock(PdbCompilandSymId block_id);
lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id, bool is_param);
+ lldb::TypeSP CreateTypedef(PdbGlobalSymId id);
lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);
lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id);
@@ -222,6 +224,7 @@ private:
llvm::BumpPtrAllocator m_allocator;
lldb::addr_t m_obj_load_address = 0;
+ bool m_done_full_type_scan = false;
std::unique_ptr<PdbIndex> m_index;
OpenPOWER on IntegriCloud