aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp588
1 files changed, 471 insertions, 117 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7e10e315be20..82d3707acfa4 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -8,12 +8,6 @@
#include "SymbolFileNativePDB.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
-
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
@@ -59,10 +53,10 @@
#include "llvm/Support/MemoryBuffer.h"
#include "DWARFLocationExpression.h"
-#include "PdbAstBuilder.h"
#include "PdbSymUid.h"
#include "PdbUtil.h"
#include "UdtRecordCompleter.h"
+#include <optional>
using namespace lldb;
using namespace lldb_private;
@@ -120,7 +114,7 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
if (!FileSystem::Instance().Exists(pdb_file)) {
const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
- pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetCString();
+ pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef();
}
// If the file is not a PDB or if it doesn't have a matching GUID, fail.
@@ -233,6 +227,57 @@ static bool IsClassRecord(TypeLeafKind kind) {
}
}
+static std::optional<CVTagRecord>
+GetNestedTagDefinition(const NestedTypeRecord &Record,
+ const CVTagRecord &parent, TpiStream &tpi) {
+ // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
+ // is also used to indicate the primary definition of a nested class. That is
+ // to say, if you have:
+ // struct A {
+ // struct B {};
+ // using C = B;
+ // };
+ // Then in the debug info, this will appear as:
+ // LF_STRUCTURE `A::B` [type index = N]
+ // LF_STRUCTURE `A`
+ // LF_NESTTYPE [name = `B`, index = N]
+ // LF_NESTTYPE [name = `C`, index = N]
+ // In order to accurately reconstruct the decl context hierarchy, we need to
+ // know which ones are actual definitions and which ones are just aliases.
+
+ // If it's a simple type, then this is something like `using foo = int`.
+ if (Record.Type.isSimple())
+ return std::nullopt;
+
+ CVType cvt = tpi.getType(Record.Type);
+
+ if (!IsTagRecord(cvt))
+ return std::nullopt;
+
+ // If it's an inner definition, then treat whatever name we have here as a
+ // single component of a mangled name. So we can inject it into the parent's
+ // mangled name to see if it matches.
+ CVTagRecord child = CVTagRecord::create(cvt);
+ std::string qname = std::string(parent.asTag().getUniqueName());
+ if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
+ return std::nullopt;
+
+ // qname[3] is the tag type identifier (struct, class, union, etc). Since the
+ // inner tag type is not necessarily the same as the outer tag type, re-write
+ // it to match the inner tag type.
+ qname[3] = child.asTag().getUniqueName()[3];
+ std::string piece;
+ if (qname[3] == 'W')
+ piece = "4";
+ piece += Record.Name;
+ piece.push_back('@');
+ qname.insert(4, std::move(piece));
+ if (qname != child.asTag().UniqueName)
+ return std::nullopt;
+
+ return std::move(child);
+}
+
void SymbolFileNativePDB::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
@@ -310,10 +355,9 @@ void SymbolFileNativePDB::InitializeObject() {
LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
"Failed to initialize");
} else {
- ts_or_err->SetSymbolFile(this);
- auto *clang = llvm::cast_or_null<TypeSystemClang>(&ts_or_err.get());
- lldbassert(clang);
- m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang);
+ if (auto ts = *ts_or_err)
+ ts->SetSymbolFile(this);
+ BuildParentMap();
}
}
@@ -338,6 +382,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return *child_block;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return *child_block;
+ PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
switch (sym.kind()) {
case S_GPROC32:
@@ -345,10 +396,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
// This is a function. It must be global. Creating the Function entry
// for it automatically creates a block for it.
FunctionSP func = GetOrCreateFunction(block_id, *comp_unit);
- Block &block = func->GetBlock(false);
- if (block.GetNumRanges() == 0)
- block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
- return block;
+ if (func) {
+ Block &block = func->GetBlock(false);
+ if (block.GetNumRanges() == 0)
+ block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
+ return block;
+ }
+ break;
}
case S_BLOCK32: {
// This is a block. Its parent is either a function or another block. In
@@ -360,8 +414,26 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
lldbassert(block.Parent != 0);
PdbCompilandSymId parent_id(block_id.modi, block.Parent);
Block &parent_block = GetOrCreateBlock(parent_id);
+ Function *func = parent_block.CalculateSymbolContextFunction();
+ lldbassert(func);
+ lldb::addr_t block_base =
+ m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
+ lldb::addr_t func_base =
+ func->GetAddressRange().GetBaseAddress().GetFileAddress();
+ if (block_base >= func_base)
+ child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
+ else {
+ GetObjectFile()->GetModule()->ReportError(
+ "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
+ "[{2:x16}-{3:x16}) which has a base that is less than the "
+ "function's "
+ "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
+ "start of this error message",
+ block_id.modi, block_id.offset, block_base,
+ block_base + block.CodeSize, func_base);
+ }
parent_block.AddChild(child_block);
- m_ast->GetOrCreateBlockDecl(block_id);
+ ast_builder->GetOrCreateBlockDecl(block_id);
m_blocks.insert({opaque_block_uid, child_block});
break;
}
@@ -372,7 +444,7 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
parent_block.AddChild(child_block);
- m_ast->GetOrCreateInlinedFunctionDecl(block_id);
+ ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
// Copy ranges from InlineSite to Block.
for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
auto *entry = inline_site->ranges.GetEntryAtIndex(i);
@@ -433,7 +505,13 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
comp_unit.AddFunction(func_sp);
- m_ast->GetOrCreateFunctionDecl(func_id);
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return func_sp;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return func_sp;
+ ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
return func_sp;
}
@@ -474,10 +552,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
Declaration decl;
lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
- return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
- modified_type->GetByteSize(nullptr), nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- ct, Type::ResolveState::Full);
+ return MakeType(toOpaqueUid(type_id), ConstString(name),
+ modified_type->GetByteSize(nullptr), nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
+ Type::ResolveState::Full);
}
lldb::TypeSP
@@ -494,10 +572,9 @@ SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
}
Declaration decl;
- return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
- pr.getSize(), nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct,
- Type::ResolveState::Full);
+ return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
+ Type::ResolveState::Full);
}
lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
@@ -505,9 +582,9 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
if (ti == TypeIndex::NullptrT()) {
Declaration decl;
- return std::make_shared<Type>(
- uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
+ return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
+ Type::ResolveState::Full);
}
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
@@ -526,9 +603,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
return nullptr;
}
Declaration decl;
- return std::make_shared<Type>(
- uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
+ return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
@@ -538,9 +614,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
Declaration decl;
- return std::make_shared<Type>(uid, this, ConstString(type_name), size,
- nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- decl, ct, Type::ResolveState::Full);
+ return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
static std::string GetUnqualifiedTypeName(const TagRecord &record) {
@@ -571,10 +646,9 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
// FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
Declaration decl;
- return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
- size, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct,
- Type::ResolveState::Forward);
+ return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
+ Type::ResolveState::Forward);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
@@ -597,11 +671,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
Declaration decl;
TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
- return std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), this, ConstString(uname),
- underlying_type->GetByteSize(nullptr), nullptr, LLDB_INVALID_UID,
- lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::ResolveState::Forward);
+ return MakeType(toOpaqueUid(type_id), ConstString(uname),
+ underlying_type->GetByteSize(nullptr), nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+ ct, lldb_private::Type::ResolveState::Forward);
}
TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
@@ -610,33 +683,30 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
TypeSP element_type = GetOrCreateType(ar.ElementType);
Declaration decl;
- TypeSP array_sp = std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
- LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::ResolveState::Full);
+ TypeSP array_sp =
+ MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
+ lldb_private::Type::ResolveState::Full);
array_sp->SetEncodingType(element_type.get());
return array_sp;
}
-
TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
const MemberFunctionRecord &mfr,
CompilerType ct) {
Declaration decl;
- return std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
- lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::ResolveState::Full);
+ return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+ ct, lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
const ProcedureRecord &pr,
CompilerType ct) {
Declaration decl;
- return std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
- lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::ResolveState::Full);
+ return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+ ct, lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
@@ -701,7 +771,7 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
// If they search for a UDT which is a forward ref, try and resolve the full
// decl and just map the forward ref uid to the full decl record.
- llvm::Optional<PdbTypeSymId> full_decl_uid;
+ std::optional<PdbTypeSymId> full_decl_uid;
if (IsForwardRefUdt(type_id, m_index->tpi())) {
auto expected_full_ti =
m_index->tpi().findFullDeclForForwardRef(type_id.index);
@@ -726,12 +796,19 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
}
PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return nullptr;
- clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+ PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
+ clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
if (qt.isNull())
return nullptr;
- TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
+ TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
if (!result)
return nullptr;
@@ -774,7 +851,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
switch (sym.kind()) {
case S_GDATA32:
is_external = true;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case S_LDATA32: {
DataSym ds(sym.kind());
llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
@@ -789,7 +866,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
}
case S_GTHREAD32:
is_external = true;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case S_LTHREAD32: {
ThreadLocalDataSym tlds(sym.kind());
llvm::cantFail(
@@ -807,7 +884,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
}
CompUnitSP comp_unit;
- llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
+ std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
if (!modi) {
return nullptr;
}
@@ -820,8 +897,14 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
SymbolFileTypeSP type_sp =
std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
Variable::RangeList ranges;
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return nullptr;
- m_ast->GetOrCreateVariableDecl(var_id);
+ ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
ModuleSP module_sp = GetObjectFile()->GetModule();
DWARFExpressionList location(
@@ -921,10 +1004,14 @@ Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
void SymbolFileNativePDB::ParseDeclsForContext(
lldb_private::CompilerDeclContext decl_ctx) {
- clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx);
+ TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
+ if (!ts_or_err)
+ return;
+ PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
+ clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
if (!context)
return;
- m_ast->ParseDeclsForContext(*context);
+ ast_builder->ParseDeclsForContext(*context);
}
lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
@@ -995,7 +1082,7 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext(
lldb::addr_t file_addr = addr.GetFileAddress();
if (NeedsResolvedCompileUnit(resolve_scope)) {
- llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
+ std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
if (!modi)
return 0;
CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
@@ -1024,16 +1111,25 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext(
continue;
if (type == PDB_SymType::Function) {
sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
- Block &block = sc.function->GetBlock(true);
- addr_t func_base =
- sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- addr_t offset = file_addr - func_base;
- sc.block = block.FindInnermostBlockByOffset(offset);
+ if (sc.function) {
+ Block &block = sc.function->GetBlock(true);
+ addr_t func_base =
+ sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
+ addr_t offset = file_addr - func_base;
+ sc.block = block.FindInnermostBlockByOffset(offset);
+ }
}
if (type == PDB_SymType::Block) {
- sc.block = &GetOrCreateBlock(csid);
- sc.function = sc.block->CalculateSymbolContextFunction();
+ Block &block = GetOrCreateBlock(csid);
+ sc.function = block.CalculateSymbolContextFunction();
+ if (sc.function) {
+ sc.function->GetBlock(true);
+ addr_t func_base =
+ sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
+ addr_t offset = file_addr - func_base;
+ sc.block = block.FindInnermostBlockByOffset(offset);
+ }
}
if (sc.function)
resolved_flags |= eSymbolContextFunction;
@@ -1329,11 +1425,11 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
// Parse range and line info.
uint32_t code_offset = 0;
int32_t line_offset = 0;
- llvm::Optional<uint32_t> code_offset_base;
- llvm::Optional<uint32_t> code_offset_end;
- llvm::Optional<int32_t> cur_line_offset;
- llvm::Optional<int32_t> next_line_offset;
- llvm::Optional<uint32_t> next_file_offset;
+ std::optional<uint32_t> code_offset_base;
+ std::optional<uint32_t> code_offset_end;
+ std::optional<int32_t> cur_line_offset;
+ std::optional<int32_t> next_line_offset;
+ std::optional<uint32_t> next_file_offset;
bool is_terminal_entry = false;
bool is_start_of_statement = true;
@@ -1406,10 +1502,10 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
file_offset = *next_file_offset;
if (next_line_offset) {
cur_line_offset = next_line_offset;
- next_line_offset = llvm::None;
+ next_line_offset = std::nullopt;
}
- code_offset_base = is_terminal_entry ? llvm::None : code_offset_end;
- code_offset_end = next_file_offset = llvm::None;
+ code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
+ code_offset_end = next_file_offset = std::nullopt;
}
if (code_offset_base && cur_line_offset) {
if (is_terminal_entry) {
@@ -1534,7 +1630,16 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
return count;
}
-void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); }
+void SymbolFileNativePDB::DumpClangAST(Stream &s) {
+ auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
+ if (!ts_or_err)
+ return;
+ auto ts = *ts_or_err;
+ TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
+ if (!clang)
+ return;
+ clang->GetNativePDBParser()->Dump(s);
+}
void SymbolFileNativePDB::FindGlobalVariables(
ConstString name, const CompilerDeclContext &parent_decl_ctx,
@@ -1563,10 +1668,15 @@ void SymbolFileNativePDB::FindGlobalVariables(
}
void SymbolFileNativePDB::FindFunctions(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- FunctionNameType name_type_mask, bool include_inlines,
+ const Module::LookupInfo &lookup_info,
+ const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ ConstString name = lookup_info.GetLookupName();
+ FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
+ if (name_type_mask & eFunctionNameTypeFull)
+ name = lookup_info.GetName();
+
// For now we only support lookup by method name or full name.
if (!(name_type_mask & eFunctionNameTypeFull ||
name_type_mask & eFunctionNameTypeMethod))
@@ -1702,12 +1812,20 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
func_block->GetStartAddress(addr);
VariableInfo var_info =
GetVariableLocationInfo(*m_index, var_id, *func_block, module);
- if (!var_info.location || !var_info.ranges)
+ Function *func = func_block->CalculateSymbolContextFunction();
+ if (!func)
return nullptr;
-
+ // Use empty dwarf expr if optimized away so that it won't be filtered out
+ // when lookuping local variables in this scope.
+ if (!var_info.location.IsValid())
+ var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
+ var_info.location.SetFuncFileAddress(
+ func->GetAddressRange().GetBaseAddress().GetFileAddress());
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
TypeSP type_sp = GetOrCreateType(var_info.type);
+ if (!type_sp)
+ return nullptr;
std::string name = var_info.name.str();
Declaration decl;
SymbolFileTypeSP sftype =
@@ -1720,15 +1838,21 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
bool artificial = false;
bool location_is_constant_data = false;
bool static_member = false;
- DWARFExpressionList locaiton_list = DWARFExpressionList(
- module, *var_info.location, nullptr);
+ Variable::RangeList scope_ranges;
VariableSP var_sp = std::make_shared<Variable>(
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
- &block, *var_info.ranges, &decl, locaiton_list, external, artificial,
+ &block, scope_ranges, &decl, var_info.location, external, artificial,
location_is_constant_data, static_member);
- if (!is_param)
- m_ast->GetOrCreateVariableDecl(scope_id, var_id);
+ if (!is_param) {
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return nullptr;
+ ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
+ }
m_local_variables[toOpaqueUid(var_id)] = var_sp;
return var_sp;
}
@@ -1750,14 +1874,20 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
TypeSP target_type = GetOrCreateType(udt.Type);
- (void)m_ast->GetOrCreateTypedefDecl(id);
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ auto ts = *ts_or_err;
+ if (!ts)
+ return nullptr;
+
+ ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
Declaration decl;
- return std::make_shared<lldb_private::Type>(
- toOpaqueUid(id), this, ConstString(udt.Name),
- target_type->GetByteSize(nullptr), nullptr, target_type->GetID(),
- lldb_private::Type::eEncodingIsTypedefUID, decl,
- target_type->GetForwardCompilerType(),
+ return MakeType(
+ toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr),
+ nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
+ decl, target_type->GetForwardCompilerType(),
lldb_private::Type::ResolveState::Forward);
}
@@ -1783,9 +1913,24 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
CVType signature = m_index->tpi().getType(proc.FunctionType);
- ProcedureRecord sig;
- cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(signature, sig));
- params_remaining = sig.getParameterCount();
+ if (signature.kind() == LF_PROCEDURE) {
+ ProcedureRecord sig;
+ if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
+ signature, sig)) {
+ llvm::consumeError(std::move(e));
+ return 0;
+ }
+ params_remaining = sig.getParameterCount();
+ } else if (signature.kind() == LF_MFUNCTION) {
+ MemberFunctionRecord sig;
+ if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
+ signature, sig)) {
+ llvm::consumeError(std::move(e));
+ return 0;
+ }
+ params_remaining = sig.getParameterCount();
+ } else
+ return 0;
break;
}
case S_BLOCK32:
@@ -1884,26 +2029,50 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
}
CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
- if (auto decl = m_ast->GetOrCreateDeclForUid(uid))
- return *decl;
- else
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
return CompilerDecl();
+ auto ts = *ts_or_err;
+ if (!ts)
+ return {};
+
+ if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
+ return *decl;
+ return CompilerDecl();
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return {};
+ auto ts = *ts_or_err;
+ if (!ts)
+ return {};
+
+ PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
clang::DeclContext *context =
- m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid));
+ ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
if (!context)
return {};
- return m_ast->ToCompilerDeclContext(*context);
+ return ast_builder->ToCompilerDeclContext(*context);
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
- clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid));
- return m_ast->ToCompilerDeclContext(*context);
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return CompilerDeclContext();
+ auto ts = *ts_or_err;
+ if (!ts)
+ return {};
+
+ PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
+ clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
+ if (!context)
+ return CompilerDeclContext();
+ return ast_builder->ToCompilerDeclContext(*context);
}
Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -1924,21 +2093,33 @@ Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
return nullptr;
TypeSP type_sp = CreateAndCacheType(type_id);
+ if (!type_sp)
+ return nullptr;
return &*type_sp;
}
-llvm::Optional<SymbolFile::ArrayInfo>
+std::optional<SymbolFile::ArrayInfo>
SymbolFileNativePDB::GetDynamicArrayInfoForUID(
lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
- return llvm::None;
+ return std::nullopt;
}
-
bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ auto ts = compiler_type.GetTypeSystem();
+ auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>();
+ if (!clang_type_system)
+ return false;
+
+ PdbAstBuilder *ast_builder =
+ static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
+ if (ast_builder &&
+ ast_builder->GetClangASTImporter().CanImport(compiler_type))
+ return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
clang::QualType qt =
clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
- return m_ast->CompleteType(qt);
+ return ast_builder->CompleteType(qt);
}
void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
@@ -1951,13 +2132,13 @@ SymbolFileNativePDB::FindNamespace(ConstString name,
return {};
}
-llvm::Expected<TypeSystem &>
+llvm::Expected<lldb::TypeSystemSP>
SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
auto type_system_or_err =
m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
- if (type_system_or_err) {
- type_system_or_err->SetSymbolFile(this);
- }
+ if (type_system_or_err)
+ if (auto ts = *type_system_or_err)
+ ts->SetSymbolFile(this);
return type_system_or_err;
}
@@ -1965,3 +2146,176 @@ uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
// PDB files are a separate file that contains all debug info.
return m_index->pdb().getFileSize();
}
+
+void SymbolFileNativePDB::BuildParentMap() {
+ LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
+
+ llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
+ llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
+
+ struct RecordIndices {
+ TypeIndex forward;
+ TypeIndex full;
+ };
+
+ llvm::StringMap<RecordIndices> record_indices;
+
+ for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+ CVType type = types.getType(*ti);
+ if (!IsTagRecord(type))
+ continue;
+
+ CVTagRecord tag = CVTagRecord::create(type);
+
+ RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
+ if (tag.asTag().isForwardRef())
+ indices.forward = *ti;
+ else
+ indices.full = *ti;
+
+ if (indices.full != TypeIndex::None() &&
+ indices.forward != TypeIndex::None()) {
+ forward_to_full[indices.forward] = indices.full;
+ full_to_forward[indices.full] = indices.forward;
+ }
+
+ // We're looking for LF_NESTTYPE records in the field list, so ignore
+ // forward references (no field list), and anything without a nested class
+ // (since there won't be any LF_NESTTYPE records).
+ if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
+ continue;
+
+ struct ProcessTpiStream : public TypeVisitorCallbacks {
+ ProcessTpiStream(PdbIndex &index, TypeIndex parent,
+ const CVTagRecord &parent_cvt,
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents)
+ : index(index), parents(parents), parent(parent),
+ parent_cvt(parent_cvt) {}
+
+ PdbIndex &index;
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+
+ unsigned unnamed_type_index = 1;
+ TypeIndex parent;
+ const CVTagRecord &parent_cvt;
+
+ llvm::Error visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Record) override {
+ std::string unnamed_type_name;
+ if (Record.Name.empty()) {
+ unnamed_type_name =
+ llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
+ Record.Name = unnamed_type_name;
+ ++unnamed_type_index;
+ }
+ std::optional<CVTagRecord> tag =
+ GetNestedTagDefinition(Record, parent_cvt, index.tpi());
+ if (!tag)
+ return llvm::ErrorSuccess();
+
+ parents[Record.Type] = parent;
+ return llvm::ErrorSuccess();
+ }
+ };
+
+ CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
+ ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
+ FieldListRecord field_list;
+ if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+ field_list_cvt, field_list))
+ llvm::consumeError(std::move(error));
+ if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
+ llvm::consumeError(std::move(error));
+ }
+
+ // Now that we know the forward -> full mapping of all type indices, we can
+ // re-write all the indices. At the end of this process, we want a mapping
+ // consisting of fwd -> full and full -> full for all child -> parent indices.
+ // We can re-write the values in place, but for the keys, we must save them
+ // off so that we don't modify the map in place while also iterating it.
+ std::vector<TypeIndex> full_keys;
+ std::vector<TypeIndex> fwd_keys;
+ for (auto &entry : m_parent_types) {
+ TypeIndex key = entry.first;
+ TypeIndex value = entry.second;
+
+ auto iter = forward_to_full.find(value);
+ if (iter != forward_to_full.end())
+ entry.second = iter->second;
+
+ iter = forward_to_full.find(key);
+ if (iter != forward_to_full.end())
+ fwd_keys.push_back(key);
+ else
+ full_keys.push_back(key);
+ }
+ for (TypeIndex fwd : fwd_keys) {
+ TypeIndex full = forward_to_full[fwd];
+ m_parent_types[full] = m_parent_types[fwd];
+ }
+ for (TypeIndex full : full_keys) {
+ TypeIndex fwd = full_to_forward[full];
+ m_parent_types[fwd] = m_parent_types[full];
+ }
+}
+
+std::optional<PdbCompilandSymId>
+SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
+ CVSymbol sym = m_index->ReadSymbolRecord(id);
+ if (symbolOpensScope(sym.kind())) {
+ // If this exact symbol opens a scope, we can just directly access its
+ // parent.
+ id.offset = getScopeParentOffset(sym);
+ // Global symbols have parent offset of 0. Return std::nullopt to indicate
+ // this.
+ if (id.offset == 0)
+ return std::nullopt;
+ return id;
+ }
+
+ // Otherwise we need to start at the beginning and iterate forward until we
+ // reach (or pass) this particular symbol
+ CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
+ const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+
+ auto begin = syms.begin();
+ auto end = syms.at(id.offset);
+ std::vector<PdbCompilandSymId> scope_stack;
+
+ while (begin != end) {
+ if (begin.offset() > id.offset) {
+ // We passed it. We couldn't even find this symbol record.
+ lldbassert(false && "Invalid compiland symbol id!");
+ return std::nullopt;
+ }
+
+ // We haven't found the symbol yet. Check if we need to open or close the
+ // scope stack.
+ if (symbolOpensScope(begin->kind())) {
+ // We can use the end offset of the scope to determine whether or not
+ // we can just outright skip this entire scope.
+ uint32_t scope_end = getScopeEndOffset(*begin);
+ if (scope_end < id.offset) {
+ begin = syms.at(scope_end);
+ } else {
+ // The symbol we're looking for is somewhere in this scope.
+ scope_stack.emplace_back(id.modi, begin.offset());
+ }
+ } else if (symbolEndsScope(begin->kind())) {
+ scope_stack.pop_back();
+ }
+ ++begin;
+ }
+ if (scope_stack.empty())
+ return std::nullopt;
+ // We have a match! Return the top of the stack
+ return scope_stack.back();
+}
+
+std::optional<llvm::codeview::TypeIndex>
+SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
+ auto parent_iter = m_parent_types.find(ti);
+ if (parent_iter == m_parent_types.end())
+ return std::nullopt;
+ return parent_iter->second;
+}