diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 03d9f92799747..91188fe6ea483 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -84,6 +84,9 @@ FLAGS_ENUM(TypeQueryOptions){ /// matching type is found. When false, the type query should find all /// matching types. e_find_one = (1u << 4), + // If set, treat TypeQuery::m_name as a mangled name that should be + // searched. + e_search_by_mangled_name = (1u << 5), }; LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions) @@ -300,6 +303,19 @@ class TypeQuery { m_options &= ~e_find_one; } + /// Returns true if the type query is supposed to treat the name to be + /// searched as a mangled name. + bool GetSearchByMangledName() const { + return (m_options & e_search_by_mangled_name) != 0; + } + + void SetSearchByMangledName(bool b) { + if (b) + m_options |= e_search_by_mangled_name; + else + m_options &= ~e_search_by_mangled_name; + } + /// Access the internal compiler context array. /// /// Clients can use this to populate the context manually. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index d83740f8e2113..4c9f1d8505f6e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -199,9 +199,9 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const { return result; } -const char *DWARFDIE::GetMangledName() const { +const char *DWARFDIE::GetMangledName(bool substitute_name_allowed) const { if (IsValid()) - return m_die->GetMangledName(m_cu); + return m_die->GetMangledName(m_cu, substitute_name_allowed); else return nullptr; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index e1318953a384c..077b78eb26d0c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -28,7 +28,7 @@ class DWARFDIE : public DWARFBaseDIE { // Accessors // Accessing information about a DIE - const char *GetMangledName() const; + const char *GetMangledName(bool substitute_name_allowed = true) const; const char *GetPubname() const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index f23f8cc3d781d..f39189b6cead4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2758,6 +2758,20 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { return true; // Keep iterating over index types, language mismatch. } + // Since mangled names are unique, we only need to check if the names are + // the same. + if (query.GetSearchByMangledName()) { + if (die.GetMangledName(/*substitute_name_allowed=*/false) != + query.GetTypeBasename().GetStringRef()) + return true; // Keep iterating over index types, mangled name mismatch. + if (Type *matching_type = ResolveType(die, true, true)) { + results.InsertUnique(matching_type->shared_from_this()); + return !results.Done(query); // Keep iterating if we aren't done. + } + return true; // Keep iterating over index types, weren't able to resolve + // this type + } + // Check the context matches std::vector die_context; if (query.GetModuleSearch()) diff --git a/lldb/test/Shell/SymbolFile/DWARF/debug-types-mangled-name.ll b/lldb/test/Shell/SymbolFile/DWARF/debug-types-mangled-name.ll new file mode 100644 index 0000000000000..06dd817fc0f39 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/debug-types-mangled-name.ll @@ -0,0 +1,63 @@ +; Test finding types by CompilerContext. +; REQUIRES: aarch64 +; RUN: llc %s -filetype=obj -o %t.o +; RUN: lldb-test symbols %t.o -find=type --mangled-name=UniqueDifferentName | FileCheck %s +; +; NORESULTS: Found 0 types +; CHECK: Found 1 types: +; CHECK: struct DifferentName { +; CHECK-NEXT: int i; +; CHECK-NEXT: } + +source_filename = "t.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "arm64-unknown-linux-gnu" + +%struct.SameName = type { i32 } +%struct.DifferentName = type { i32 } + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @main() #0 !dbg !10 { +entry: + %retval = alloca i32, align 4 + %s = alloca %struct.SameName, align 4 + %d = alloca %struct.DifferentName, align 4 + store i32 0, ptr %retval, align 4 + #dbg_declare(ptr %s, !16, !DIExpression(), !20) + #dbg_declare(ptr %d, !21, !DIExpression(), !25) + ret i32 0, !dbg !26 +} + +attributes #0 = { noinline optnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 1} +!9 = !{!""} +!10 = distinct !DISubprogram(name: "main", scope: !11, file: !11, line: 9, type: !12, scopeLine: 9, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) +!11 = !DIFile(filename: "t.c", directory: "") +!12 = !DISubroutineType(types: !13) +!13 = !{!14} +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !{} +!16 = !DILocalVariable(name: "s", scope: !10, file: !11, line: 10, type: !17) +!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SameName", file: !11, line: 1, size: 32, elements: !18, runtimeLang: DW_LANG_Swift, identifier: "SameName") +!18 = !{!19} +!19 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !17, file: !11, line: 2, baseType: !14, size: 32) +!20 = !DILocation(line: 10, column: 19, scope: !10) +!21 = !DILocalVariable(name: "d", scope: !10, file: !11, line: 11, type: !22) +!22 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DifferentName", file: !11, line: 5, size: 32, elements: !23, runtimeLang: DW_LANG_Swift, identifier: "UniqueDifferentName") +!23 = !{!24} +!24 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !22, file: !11, line: 6, baseType: !14, size: 32) +!25 = !DILocation(line: 11, column: 24, scope: !10) +!26 = !DILocation(line: 12, column: 3, scope: !10) diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp index 50b85d4b51209..1960240dc4151 100644 --- a/lldb/tools/lldb-test/lldb-test.cpp +++ b/lldb/tools/lldb-test/lldb-test.cpp @@ -13,6 +13,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Expression/IRMemoryMap.h" @@ -23,6 +24,7 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Symtab.h" +#include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/VariableList.h" @@ -179,6 +181,10 @@ static cl::opt Find( static cl::opt Name("name", cl::desc("Name to find."), cl::sub(SymbolsSubcommand)); +static cl::opt MangledName( + "mangled-name", + cl::desc("Mangled name to find. Only compatible when searching types"), + cl::sub(SymbolsSubcommand)); static cl::opt Regex("regex", cl::desc("Search using regular expressions (available for variables " @@ -468,6 +474,9 @@ static lldb::DescriptionLevel GetDescriptionLevel() { } Error opts::symbols::findFunctions(lldb_private::Module &Module) { + if (!MangledName.empty()) + return make_string_error("Cannot search functions by mangled name."); + SymbolFile &Symfile = *Module.GetSymbolFile(); SymbolContextList List; auto compiler_context = parseCompilerContext(); @@ -529,6 +538,8 @@ Error opts::symbols::findBlocks(lldb_private::Module &Module) { assert(!Regex); assert(!File.empty()); assert(Line != 0); + if (!MangledName.empty()) + return make_string_error("Cannot search blocks by mangled name."); SymbolContextList List; @@ -563,6 +574,9 @@ Error opts::symbols::findBlocks(lldb_private::Module &Module) { } Error opts::symbols::findNamespaces(lldb_private::Module &Module) { + if (!MangledName.empty()) + return make_string_error("Cannot search namespaces by mangled name."); + SymbolFile &Symfile = *Module.GetSymbolFile(); Expected ContextOr = getDeclContext(Symfile); if (!ContextOr) @@ -585,11 +599,15 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { Expected ContextOr = getDeclContext(Symfile); if (!ContextOr) return ContextOr.takeError(); + ; TypeQueryOptions Opts = TypeQueryOptions::e_module_search; if (FindInAnyModule) Opts |= TypeQueryOptions::e_ignore_modules; TypeResults results; + if (!Name.empty() && !MangledName.empty()) + return make_string_error("Cannot search by both name and mangled name."); + if (!Name.empty()) { if (ContextOr->IsValid()) { TypeQuery query(*ContextOr, ConstString(Name), Opts); @@ -602,6 +620,20 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { query.AddLanguage(Language::GetLanguageTypeFromString(Language)); Symfile.FindTypes(query, results); } + } else if (!MangledName.empty()) { + Opts = TypeQueryOptions::e_search_by_mangled_name; + if (ContextOr->IsValid()) { + TypeQuery query(*ContextOr, ConstString(MangledName), Opts); + if (!Language.empty()) + query.AddLanguage(Language::GetLanguageTypeFromString(Language)); + Symfile.FindTypes(query, results); + } else { + TypeQuery query(MangledName, Opts); + if (!Language.empty()) + query.AddLanguage(Language::GetLanguageTypeFromString(Language)); + Symfile.FindTypes(query, results); + } + } else { TypeQuery query(parseCompilerContext(), Opts); if (!Language.empty()) @@ -619,6 +651,9 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { } Error opts::symbols::findVariables(lldb_private::Module &Module) { + if (!MangledName.empty()) + return make_string_error("Cannot search variables by mangled name."); + SymbolFile &Symfile = *Module.GetSymbolFile(); VariableList List; if (Regex) {