Skip to content

[lldb] Extend FindTypes to optionally search by mangled type name #113007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
16 changes: 16 additions & 0 deletions lldb/include/lldb/Symbol/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
14 changes: 14 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) !=
Copy link
Member

@Michael137 Michael137 Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even with substitutions allowed, that would only cause problems if the DW_AT_name somehow contained the mangled name, right? Even then, that might not actually be a problem. For the purposes of this check, if a DIE didn't have a linkage name this comparison would have evaluated to false anyway, unless I'm missing something.

But I guess being more explicit about really only checking the linkage name seems fine/easier to reason about

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<lldb_private::CompilerContext> die_context;
if (query.GetModuleSearch())
Expand Down
63 changes: 63 additions & 0 deletions lldb/test/Shell/SymbolFile/DWARF/debug-types-mangled-name.ll
Original file line number Diff line number Diff line change
@@ -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 nounwind optnone uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+v8a,-fmv" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try to remove most of the attributes?


!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)
35 changes: 35 additions & 0 deletions lldb/tools/lldb-test/lldb-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -179,6 +181,10 @@ static cl::opt<FindType> Find(

static cl::opt<std::string> Name("name", cl::desc("Name to find."),
cl::sub(SymbolsSubcommand));
static cl::opt<std::string> MangledName(
"mangled-name",
cl::desc("Mangled name to find. Only compatible when searching types"),
cl::sub(SymbolsSubcommand));
static cl::opt<bool>
Regex("regex",
cl::desc("Search using regular expressions (available for variables "
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
if (!ContextOr)
Expand All @@ -585,11 +599,15 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) {
Expected<CompilerDeclContext> 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);
Expand All @@ -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())
Expand All @@ -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) {
Expand Down
Loading