Relands #152295. Checking for the overloads did not account for them being out of order. For example, [the failed output](https://github.com/llvm/llvm-project/pull/152295#issuecomment-3177563247) contained the overloads, but out of order. The last commit here fixes that by using `-DAG`. --------- Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
This commit is contained in:
parent
d99b043279
commit
44f41f55b4
@ -39,6 +39,7 @@
|
||||
#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"
|
||||
@ -1641,6 +1642,94 @@ 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) {
|
||||
@ -1677,34 +1766,60 @@ 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();
|
||||
|
||||
using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
|
||||
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;
|
||||
|
||||
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));
|
||||
for (uint32_t id : ids) {
|
||||
if (!resolved_ids.insert(id).second)
|
||||
continue;
|
||||
|
||||
if (!IsValidRecord(proc))
|
||||
continue;
|
||||
PdbGlobalSymId global{id, false};
|
||||
if (parent_decl_ctx.IsValid() &&
|
||||
GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
|
||||
continue;
|
||||
|
||||
CompilandIndexItem &cci =
|
||||
m_index->compilands().GetOrCreateCompiland(proc.modi());
|
||||
SymbolContext sc;
|
||||
CVSymbol sym = m_index->ReadSymbolRecord(global);
|
||||
auto kind = sym.kind();
|
||||
lldbassert(kind == S_PROCREF || kind == S_LPROCREF);
|
||||
|
||||
sc.comp_unit = GetOrCreateCompileUnit(cci).get();
|
||||
PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
|
||||
sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
|
||||
ProcRefSym proc =
|
||||
cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym));
|
||||
|
||||
sc_list.Append(sc);
|
||||
}
|
||||
if (!IsValidRecord(proc))
|
||||
continue;
|
||||
|
||||
CompilandIndexItem &cci =
|
||||
m_index->compilands().GetOrCreateCompiland(proc.modi());
|
||||
SymbolContext sc;
|
||||
|
||||
sc.comp_unit = GetOrCreateCompileUnit(cci).get();
|
||||
if (!sc.comp_unit)
|
||||
continue;
|
||||
|
||||
PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
|
||||
sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
|
||||
if (!sc.function)
|
||||
continue;
|
||||
|
||||
sc_list.Append(sc);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex,
|
||||
|
@ -260,6 +260,8 @@ private:
|
||||
|
||||
std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti);
|
||||
|
||||
void CacheFunctionNames();
|
||||
|
||||
llvm::BumpPtrAllocator m_allocator;
|
||||
|
||||
lldb::addr_t m_obj_load_address = 0;
|
||||
@ -282,6 +284,13 @@ private:
|
||||
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
|
||||
|
@ -6,24 +6,52 @@
|
||||
|
||||
// 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
|
||||
// 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
|
||||
|
||||
struct Struct {
|
||||
int simple_method() {
|
||||
@ -51,7 +79,28 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
@ -63,12 +112,16 @@ 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();
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)"
|
||||
|
||||
@ -84,7 +137,29 @@ 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: 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, ...)"
|
||||
// FIND-OVERLOAD-FULL-NOT: "Class::overloaded_method"
|
||||
// FIND-OVERLOAD-FULL-NOT: "overloaded_method"
|
||||
// FIND-OVERLOAD-FULL-DAG: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
|
||||
// FIND-OVERLOAD-FULL-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)"
|
||||
// FIND-OVERLOAD-FULL-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)"
|
||||
// FIND-OVERLOAD-FULL-DAG: 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)"
|
||||
|
Loading…
x
Reference in New Issue
Block a user