summaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2019-01-10 20:57:32 +0000
committerZachary Turner <zturner@google.com>2019-01-10 20:57:32 +0000
commit0a0f5e70563bd0de1e2018de1011c3b50ec57288 (patch)
tree58c9cfebb888fe6eefe8dcce7917d310a8cd0b94 /lldb
parent54b44fd8badaf0a93d140fc0df0d90e382be2beb (diff)
[NativePDB] Add support for parsing typedef records.
Typedefs are represented as S_UDT records in the globals stream. This creates a strange situation where "types" are actually represented as "symbols", so they need special handling. In order to test this, we don't just use lldb and print out some variables causing the AST to get created, because variables whose type is a typedef will have debug info referencing the original type, not the typedef. So we use lldb-test instead which will parse all debug info in the entire file. This exposed some problems with lldb-test and the native reader, mainly that certain types of obscure symbols which we can find when iterating every single record would trigger crashes. These have been fixed as well so that lldb-test can be used to test this functionality. Differential Revision: https://reviews.llvm.org/D56461
Diffstat (limited to 'lldb')
-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;