Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 19 additions & 134 deletions lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDB.h"
Expand Down Expand Up @@ -1642,94 +1641,6 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) {
clang->GetNativePDBParser()->Dump(s, filter);
}

void SymbolFileNativePDB::CacheFunctionNames() {
if (!m_func_full_names.IsEmpty())
return;

// (segment, code offset) -> gid
std::map<std::pair<uint16_t, uint32_t>, uint32_t> addr_ids;

// First, find all function references in the globals table.
for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
CVSymbol ref_sym = m_index->symrecords().readRecord(gid);
auto kind = ref_sym.kind();
if (kind != S_PROCREF && kind != S_LPROCREF)
continue;

ProcRefSym ref =
llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(ref_sym));
if (ref.Name.empty())
continue;

// Find the function this is referencing.
CompilandIndexItem &cci =
m_index->compilands().GetOrCreateCompiland(ref.modi());
auto iter = cci.m_debug_stream.getSymbolArray().at(ref.SymOffset);
if (iter == cci.m_debug_stream.getSymbolArray().end())
continue;
kind = iter->kind();
if (kind != S_GPROC32 && kind != S_LPROC32)
continue;

ProcSym proc =
llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*iter));
if ((proc.Flags & ProcSymFlags::IsUnreachable) != ProcSymFlags::None)
continue;
if (proc.Name.empty())
continue;

// The function/procedure symbol only contains the demangled name.
// The mangled names are in the publics table. Save the address of this
// function to lookup the mangled name later.
addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);

llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name);
if (basename.empty())
basename = proc.Name;

m_func_base_names.Append(ConstString(basename), gid);
m_func_full_names.Append(ConstString(proc.Name), gid);

// To see if this is a member function, check the type.
auto type = m_index->tpi().getType(proc.FunctionType);
if (type.kind() == LF_MFUNCTION) {
MemberFunctionRecord mfr;
llvm::cantFail(
TypeDeserializer::deserializeAs<MemberFunctionRecord>(type, mfr));
if (!mfr.getThisType().isNoneType())
m_func_method_names.Append(ConstString(basename), gid);
}
}

// The publics stream contains all mangled function names and their address.
for (auto pid : m_index->publics().getPublicsTable()) {
PdbGlobalSymId global{pid, true};
CVSymbol sym = m_index->ReadSymbolRecord(global);
auto kind = sym.kind();
if (kind != S_PUB32)
continue;
PublicSym32 pub =
llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym));
// We only care about mangled names - if the name isn't mangled, it's
// already in the full name map.
if (!Mangled::IsMangledName(pub.Name))
continue;

// Check if this symbol is for one of our functions.
auto it = addr_ids.find({pub.Segment, pub.Offset});
if (it != addr_ids.end())
m_func_full_names.Append(ConstString(pub.Name), it->second);
}

// Sort them before value searching is working properly.
m_func_full_names.Sort();
m_func_full_names.SizeToFit();
m_func_method_names.Sort();
m_func_method_names.SizeToFit();
m_func_base_names.Sort();
m_func_base_names.SizeToFit();
}

void SymbolFileNativePDB::FindGlobalVariables(
ConstString name, const CompilerDeclContext &parent_decl_ctx,
uint32_t max_matches, VariableList &variables) {
Expand Down Expand Up @@ -1766,60 +1677,34 @@ void SymbolFileNativePDB::FindFunctions(
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 & eFunctionNameTypeBase ||
name_type_mask & eFunctionNameTypeMethod))
return;
CacheFunctionNames();

std::set<uint32_t> resolved_ids; // avoid duplicate lookups
auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) {
std::vector<uint32_t> ids;
if (!Names.GetValues(name, ids))
return;

for (uint32_t id : ids) {
if (!resolved_ids.insert(id).second)
continue;

PdbGlobalSymId global{id, false};
if (parent_decl_ctx.IsValid() &&
GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
continue;

CVSymbol sym = m_index->ReadSymbolRecord(global);
auto kind = sym.kind();
lldbassert(kind == S_PROCREF || kind == S_LPROCREF);

ProcRefSym proc =
cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym));

if (!IsValidRecord(proc))
continue;
using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;

CompilandIndexItem &cci =
m_index->compilands().GetOrCreateCompiland(proc.modi());
SymbolContext sc;
std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
name.GetStringRef(), m_index->symrecords());
for (const SymbolAndOffset &match : matches) {
if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
continue;
ProcRefSym proc(match.second.kind());
cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));

sc.comp_unit = GetOrCreateCompileUnit(cci).get();
if (!sc.comp_unit)
continue;
if (!IsValidRecord(proc))
continue;

PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
if (!sc.function)
continue;
CompilandIndexItem &cci =
m_index->compilands().GetOrCreateCompiland(proc.modi());
SymbolContext sc;

sc_list.Append(sc);
}
};
sc.comp_unit = GetOrCreateCompileUnit(cci).get();
PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();

if (name_type_mask & eFunctionNameTypeFull)
resolve_from(m_func_full_names);
if (name_type_mask & eFunctionNameTypeBase)
resolve_from(m_func_base_names);
if (name_type_mask & eFunctionNameTypeMethod)
resolve_from(m_func_method_names);
sc_list.Append(sc);
}
}

void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,6 @@ class SymbolFileNativePDB : public SymbolFileCommon {

std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti);

void CacheFunctionNames();

llvm::BumpPtrAllocator m_allocator;

lldb::addr_t m_obj_load_address = 0;
Expand All @@ -284,13 +282,6 @@ class SymbolFileNativePDB : public SymbolFileCommon {
m_parent_types;

lldb_private::UniqueCStringMap<uint32_t> m_type_base_names;

/// mangled name/full function name -> Global ID(s)
lldb_private::UniqueCStringMap<uint32_t> m_func_full_names;
/// basename -> Global ID(s)
lldb_private::UniqueCStringMap<uint32_t> m_func_base_names;
/// method basename -> Global ID(s)
lldb_private::UniqueCStringMap<uint32_t> m_func_method_names;
};

} // namespace npdb
Expand Down
87 changes: 6 additions & 81 deletions lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,24 @@

// RUN: lldb-test symbols --find=function --name=main --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-MAIN
// RUN: lldb-test symbols --find=function --name=main --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-NO-FUNCTION
// RUN: lldb-test symbols --find=function --name=main --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-MAIN

// RUN: lldb-test symbols --find=function --name=static_fn --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-STATIC
// RUN: lldb-test symbols --find=function --name=static_fn --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-NO-FUNCTION
// RUN: lldb-test symbols --find=function --name=static_fn --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-STATIC

// RUN: lldb-test symbols --find=function --name=varargs_fn --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-VAR
// RUN: lldb-test symbols --find=function --name=varargs_fn --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-NO-FUNCTION
// RUN: lldb-test symbols --find=function --name=varargs_fn --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-VAR

// RUN: lldb-test symbols --find=function --name=Struct::simple_method --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-SIMPLE
// RUN: lldb-test symbols --find=function --name=Struct::simple_method --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-SIMPLE
// RUN: lldb-test symbols --find=function --name=Struct::simple_method --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-SIMPLE

// RUN: lldb-test symbols --find=function --name=Struct::virtual_method --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-VIRTUAL
// RUN: lldb-test symbols --find=function --name=Struct::virtual_method --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-VIRTUAL
// RUN: lldb-test symbols --find=function --name=Struct::virtual_method --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-VIRTUAL

// RUN: lldb-test symbols --find=function --name=Struct::static_method --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-STATIC-METHOD
// RUN: lldb-test symbols --find=function --name=Struct::static_method --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-NO-FUNCTION
// RUN: lldb-test symbols --find=function --name=Struct::static_method --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-STATIC-METHOD

// RUN: lldb-test symbols --find=function --name=Struct::overloaded_method --function-flags=full %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-OVERLOAD-FULL
// RUN: lldb-test symbols --find=function --name=Struct::overloaded_method --function-flags=method %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-OVERLOAD-METHOD
// RUN: lldb-test symbols --find=function --name=Struct::overloaded_method --function-flags=base %t.exe \
// RUN: | FileCheck %s --check-prefix=FIND-OVERLOAD-BASE
// RUN: | FileCheck %s --check-prefix=FIND-OVERLOAD

struct Struct {
int simple_method() {
Expand Down Expand Up @@ -79,28 +51,7 @@ struct Struct {
}
};

class Class {
public:
bool overloaded_method() {
return false;
}
bool overloaded_method(int i) {
return i > 0;
}
static int overloaded_method(bool b) {
return b ? 1 : 2;
}
};

char overloaded_method() {
return 0;
}
char overloaded_method(int i) {
return 0;
}

Struct s;
Class c;

static int static_fn() {
return 42;
Expand All @@ -112,16 +63,12 @@ int varargs_fn(int x, int y, ...) {

int main(int argc, char **argv) {
return static_fn() + varargs_fn(argc, argc) + s.simple_method() +
Struct::static_method() + s.virtual_method() + s.overloaded_method() +
Class::overloaded_method(false) + c.overloaded_method(1) + c.overloaded_method()
+ overloaded_method() + overloaded_method(1);
Struct::static_method() + s.virtual_method() + s.overloaded_method();
}

// FIND-MAIN: Function: id = {{.*}}, name = "main"
// FIND-MAIN-NEXT: FuncType: id = {{.*}}, compiler_type = "int (int, char **)"

// FIND-NO-FUNCTION: Found 0 functions

// FIND-STATIC: Function: id = {{.*}}, name = "{{.*}}static_fn{{.*}}"
// FIND-STATIC-NEXT: FuncType: id = {{.*}}, compiler_type = "int (void)"

Expand All @@ -137,29 +84,7 @@ int main(int argc, char **argv) {
// FIND-STATIC-METHOD: Function: id = {{.*}}, name = "{{.*}}Struct::static_method{{.*}}"
// FIND-STATIC-METHOD-NEXT: FuncType: id = {{.*}}, compiler_type = "int (void)"

// FIND-OVERLOAD-FULL-NOT: "Class::overloaded_method"
// FIND-OVERLOAD-FULL-NOT: "overloaded_method"
// FIND-OVERLOAD-FULL: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
// FIND-OVERLOAD-FULL: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD-FULL: FuncType: id = {{.*}}, compiler_type = "int (char)"
// FIND-OVERLOAD-FULL: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)"

// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)"
// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "Class::overloaded_method"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (_Bool)"
// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "overloaded_method"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (int)"

// FIND-OVERLOAD-METHOD-NOT: "overloaded_method"
// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)"
// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "Class::overloaded_method"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)"
// FIND-OVERLOAD: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (char)"
// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)"
Loading