Skip to content

Commit fa92845

Browse files
[lldb] DWARFDIE: Follow DW_AT_specification when computing CompilerCo… (#77157)
…ntext Following the specification chain seems to be clearly the expected behavior of GetDeclContext(). Otherwise C++ methods have an empty CompilerContext instead of being nested in their struct/class. Theprimary motivation for this functionality is the Swift plugin. In order to test the change I added a proof-of-concept implementation of a Module::FindFunction() variant that takes a CompilerContext, expesed via lldb-test. rdar://120553412
1 parent 7620f03 commit fa92845

File tree

6 files changed

+67
-21
lines changed

6 files changed

+67
-21
lines changed

lldb/include/lldb/Core/Module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ class Module : public std::enable_shared_from_this<Module>,
337337
const ModuleFunctionSearchOptions &options,
338338
SymbolContextList &sc_list);
339339

340+
/// Find functions by compiler context.
341+
void FindFunctions(llvm::ArrayRef<CompilerContext> compiler_ctx,
342+
lldb::FunctionNameType name_type_mask,
343+
const ModuleFunctionSearchOptions &options,
344+
SymbolContextList &sc_list);
345+
340346
/// Find functions by name.
341347
///
342348
/// If the function is an inlined function, it will have a block,

lldb/source/Core/Module.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,23 @@ void Module::FindFunctions(ConstString name,
855855
}
856856
}
857857

858+
void Module::FindFunctions(llvm::ArrayRef<CompilerContext> compiler_ctx,
859+
FunctionNameType name_type_mask,
860+
const ModuleFunctionSearchOptions &options,
861+
SymbolContextList &sc_list) {
862+
if (compiler_ctx.empty() ||
863+
compiler_ctx.back().kind != CompilerContextKind::Function)
864+
return;
865+
ConstString name = compiler_ctx.back().name;
866+
SymbolContextList unfiltered;
867+
FindFunctions(name, CompilerDeclContext(), name_type_mask, options,
868+
unfiltered);
869+
// Filter by context.
870+
for (auto &sc : unfiltered)
871+
if (sc.function && compiler_ctx.equals(sc.function->GetCompilerContext()))
872+
sc_list.Append(sc);
873+
}
874+
858875
void Module::FindFunctions(const RegularExpression &regex,
859876
const ModuleFunctionSearchOptions &options,
860877
SymbolContextList &sc_list) {

lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -373,51 +373,63 @@ std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const {
373373
return result;
374374
}
375375

376-
std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
376+
static std::vector<lldb_private::CompilerContext>
377+
GetDeclContextImpl(llvm::SmallSet<lldb::user_id_t, 4> &seen, DWARFDIE die) {
377378
std::vector<lldb_private::CompilerContext> context;
378-
const dw_tag_t tag = Tag();
379-
if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
379+
// Stop if we hit a cycle.
380+
if (!die || !seen.insert(die.GetID()).second)
380381
return context;
381-
DWARFDIE parent = GetParent();
382-
if (parent)
383-
context = parent.GetDeclContext();
382+
383+
// Handle outline member function DIEs by following the specification.
384+
if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_specification))
385+
return GetDeclContextImpl(seen, spec);
386+
387+
// Get the parent context chain.
388+
context = GetDeclContextImpl(seen, die.GetParent());
389+
390+
// Add this DIE's contribution at the end of the chain.
384391
auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
385392
context.push_back({kind, ConstString(name)});
386393
};
387-
switch (tag) {
394+
switch (die.Tag()) {
388395
case DW_TAG_module:
389-
push_ctx(CompilerContextKind::Module, GetName());
396+
push_ctx(CompilerContextKind::Module, die.GetName());
390397
break;
391398
case DW_TAG_namespace:
392-
push_ctx(CompilerContextKind::Namespace, GetName());
399+
push_ctx(CompilerContextKind::Namespace, die.GetName());
393400
break;
394401
case DW_TAG_structure_type:
395-
push_ctx(CompilerContextKind::Struct, GetName());
402+
push_ctx(CompilerContextKind::Struct, die.GetName());
396403
break;
397404
case DW_TAG_union_type:
398-
push_ctx(CompilerContextKind::Union, GetName());
405+
push_ctx(CompilerContextKind::Union, die.GetName());
399406
break;
400407
case DW_TAG_class_type:
401-
push_ctx(CompilerContextKind::Class, GetName());
408+
push_ctx(CompilerContextKind::Class, die.GetName());
402409
break;
403410
case DW_TAG_enumeration_type:
404-
push_ctx(CompilerContextKind::Enum, GetName());
411+
push_ctx(CompilerContextKind::Enum, die.GetName());
405412
break;
406413
case DW_TAG_subprogram:
407-
push_ctx(CompilerContextKind::Function, GetPubname());
414+
push_ctx(CompilerContextKind::Function, die.GetName());
408415
break;
409416
case DW_TAG_variable:
410-
push_ctx(CompilerContextKind::Variable, GetPubname());
417+
push_ctx(CompilerContextKind::Variable, die.GetPubname());
411418
break;
412419
case DW_TAG_typedef:
413-
push_ctx(CompilerContextKind::Typedef, GetName());
420+
push_ctx(CompilerContextKind::Typedef, die.GetName());
414421
break;
415422
default:
416423
break;
417424
}
418425
return context;
419426
}
420427

428+
std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
429+
llvm::SmallSet<lldb::user_id_t, 4> seen;
430+
return GetDeclContextImpl(seen, *this);
431+
}
432+
421433
std::vector<lldb_private::CompilerContext>
422434
DWARFDIE::GetTypeLookupContext() const {
423435
std::vector<lldb_private::CompilerContext> context;

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,11 +2574,12 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
25742574

25752575
Module::LookupInfo no_tp_lookup_info(lookup_info);
25762576
no_tp_lookup_info.SetLookupName(ConstString(name_no_template_params));
2577-
m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
2578-
if (resolved_dies.insert(die.GetDIE()).second)
2579-
ResolveFunction(die, include_inlines, sc_list);
2580-
return true;
2581-
});
2577+
m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx,
2578+
[&](DWARFDIE die) {
2579+
if (resolved_dies.insert(die.GetDIE()).second)
2580+
ResolveFunction(die, include_inlines, sc_list);
2581+
return true;
2582+
});
25822583
}
25832584
}
25842585

lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-function.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
// RUN: FileCheck --check-prefix=FULL-MANGLED-METHOD %s
3535
// RUN: lldb-test symbols --name=foo --context=context --find=function --function-flags=base %t | \
3636
// RUN: FileCheck --check-prefix=CONTEXT %s
37+
// RUN: lldb-test symbols --compiler-context=Struct:sbar,Function:foo -language=c++ -find=function -function-flags=method %t | \
38+
// RUN: FileCheck --check-prefix=COMPILER-CONTEXT %s
3739
// RUN: lldb-test symbols --name=not_there --find=function %t | \
3840
// RUN: FileCheck --check-prefix=EMPTY %s
3941

@@ -84,6 +86,10 @@
8486
// CONTEXT: Found 1 functions:
8587
// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv", decl_context = {Namespace(bar)}
8688

89+
// COMPILER-CONTEXT: Found 2 functions:
90+
// COMPILER-CONTEXT-DAG: name = "sbar::foo()", mangled = "_ZN4sbar3fooEv"
91+
// COMPILER-CONTEXT-DAG: name = "sbar::foo(int)", mangled = "_ZN4sbar3fooEi"
92+
8793
// EMPTY: Found 0 functions:
8894

8995
void foo() {}

lldb/tools/lldb-test/lldb-test.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ static lldb::DescriptionLevel GetDescriptionLevel() {
466466
Error opts::symbols::findFunctions(lldb_private::Module &Module) {
467467
SymbolFile &Symfile = *Module.GetSymbolFile();
468468
SymbolContextList List;
469+
auto compiler_context = parseCompilerContext();
469470
if (!File.empty()) {
470471
assert(Line != 0);
471472

@@ -498,6 +499,9 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) {
498499
assert(RE.IsValid());
499500
List.Clear();
500501
Symfile.FindFunctions(RE, true, List);
502+
} else if (!compiler_context.empty()) {
503+
List.Clear();
504+
Module.FindFunctions(compiler_context, getFunctionNameFlags(), {}, List);
501505
} else {
502506
Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
503507
if (!ContextOr)

0 commit comments

Comments
 (0)