diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 986d647b4de2d..dcea33dd9f854 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -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" @@ -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, 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(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(*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(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(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) { @@ -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 resolved_ids; // avoid duplicate lookups - auto resolve_from = [&](UniqueCStringMap &Names) { - std::vector 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(sym)); - - if (!IsValidRecord(proc)) - continue; + using SymbolAndOffset = std::pair; - CompilandIndexItem &cci = - m_index->compilands().GetOrCreateCompiland(proc.modi()); - SymbolContext sc; + std::vector 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(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 ®ex, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 6bbeb8bb14428..eda375d4cebe7 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -260,8 +260,6 @@ class SymbolFileNativePDB : public SymbolFileCommon { std::vector GetContextForType(llvm::codeview::TypeIndex ti); - void CacheFunctionNames(); - llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; @@ -284,13 +282,6 @@ class SymbolFileNativePDB : public SymbolFileCommon { m_parent_types; lldb_private::UniqueCStringMap m_type_base_names; - - /// mangled name/full function name -> Global ID(s) - lldb_private::UniqueCStringMap m_func_full_names; - /// basename -> Global ID(s) - lldb_private::UniqueCStringMap m_func_base_names; - /// method basename -> Global ID(s) - lldb_private::UniqueCStringMap m_func_method_names; }; } // namespace npdb diff --git a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp index 37a0b10d445f3..5ebef61bdbfef 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp @@ -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() { @@ -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; @@ -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)" @@ -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, ...)"