diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -246,6 +246,8 @@ // accelerate function lookup. At that point, we should switch the depth to // CompileUnit, and look in these tables. +#include "lldb/Symbol/CompileUnit.h" + Searcher::CallbackReturn BreakpointResolverName::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr) { @@ -260,6 +262,8 @@ SymbolContextList func_list; bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; + bool filter_by_function = + (filter.GetFilterRequiredItems() & eSymbolContextFunction) != 0; bool filter_by_language = (m_language != eLanguageTypeUnknown); const bool include_symbols = !filter_by_cu; const bool include_inlines = true; @@ -305,8 +309,26 @@ SymbolContext sc; func_list.GetContextAtIndex(idx, sc); if (filter_by_cu) { - if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) - remove_it = true; + if (!filter_by_function) { + if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) + remove_it = true; + } else { + // TODO(kwk): Currently this appears somewhat like a hack because only + // the SearchFilterByModuleListAndCUOrSupportFile search filter + // requires eSymbolContextCompUnit and eSymbolContextFunction + // (filter_by_cu && filter_by_function). + + // Keep this symbol context if it is a function call to a function + // whose declaration is located in a file that passes. This is needed + // for inlined functions (e.g. when LTO is enabled) and templates. + if (Type *type = sc.function->GetType()) { + Declaration &decl = + const_cast(type->GetDeclaration()); + FileSpec &source_file = decl.GetFile(); + if (!filter.CompUnitPasses(source_file)) + remove_it = true; + } + } } if (filter_by_language) { diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp --- a/lldb/source/Core/SearchFilter.cpp +++ b/lldb/source/Core/SearchFilter.cpp @@ -715,9 +715,13 @@ FileSpec cu_spec; if (sym_ctx.comp_unit) cu_spec = sym_ctx.comp_unit->GetPrimaryFile(); - if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX) - return false; // Fails the file check - return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp); + if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) != UINT32_MAX) + return true; + // ^ If the primary source file associated with the symbol's compile unit is in + // the list of CU's or support files, that's enough. + // TODO(kwk): Is that enough? + + return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp); } bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) { @@ -811,7 +815,7 @@ } uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() { - return eSymbolContextModule | eSymbolContextCompUnit; + return eSymbolContextModule | eSymbolContextCompUnit | eSymbolContextFunction; } void SearchFilterByModuleListAndCU::Dump(Stream *s) const {} diff --git a/lldb/test/Shell/Breakpoint/Inputs/search-support-files.h b/lldb/test/Shell/Breakpoint/Inputs/search-support-files.h new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Breakpoint/Inputs/search-support-files.h @@ -0,0 +1 @@ +int inlined_42() { return 42; } diff --git a/lldb/test/Shell/Breakpoint/Inputs/search-support-files.cpp b/lldb/test/Shell/Breakpoint/Inputs/search-support-files.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Breakpoint/Inputs/search-support-files.cpp @@ -0,0 +1,7 @@ +#include "search-support-files.h" +#include "search-support-files2.h" + +int main(int argc, char *argv[]) { + int a = inlined_42(); + return return_zero() + a; +} diff --git a/lldb/test/Shell/Breakpoint/Inputs/search-support-files2.h b/lldb/test/Shell/Breakpoint/Inputs/search-support-files2.h new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Breakpoint/Inputs/search-support-files2.h @@ -0,0 +1 @@ +int return_zero() { return 0; } \ No newline at end of file diff --git a/lldb/test/Shell/Breakpoint/search-support-files.test b/lldb/test/Shell/Breakpoint/search-support-files.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Breakpoint/search-support-files.test @@ -0,0 +1,51 @@ +# In these tests we will set breakpoints on a function by name. That function +# is defined in a header file (search-support-files.h) and will therefore be +# inlined into the file that includes it (search-support-files.cpp). +# +# TODO(kwk): Check that we can also do the same with C++ methods in files? +# (See https://lldb.llvm.org/use/tutorial.html and look for --method.) + +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: %build %p/Inputs/search-support-files.cpp -o dummy.out +# RUN: %lldb -b -s %s dummy.out | FileCheck --color --dump-input=fail %s + +#------------------------------------------------------------------------------- +# Set breakpoint by function name. + +breakpoint set -n inlined_42 +# CHECK: (lldb) breakpoint set -n inlined_42 +# CHECK-NEXT: Breakpoint 1: where = dummy.out`inlined_42() + 4 at search-support-files.h:1:20, address = 0x0{{.*}} + +breakpoint set -n main +# CHECK: (lldb) breakpoint set -n main +# CHECK-NEXT: Breakpoint 2: where = dummy.out`main + 22 at search-support-files.cpp:5:11, address = 0x0{{.*}} + +#------------------------------------------------------------------------------- +# Set breakpoint by function name and filename (the one in which the function is +# inlined, aka the compilation unit). + +breakpoint set -n inlined_42 -f search-support-files.cpp +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-support-files.cpp +# CHECK-NEXT: Breakpoint 3: no locations (pending). + +#------------------------------------------------------------------------------- +# Set breakpoint by function name and source filename (the file in which the +# function is defined). +# +# NOTE: This test is the really interesting one as it shows that we can now +# search by source files that are themselves no compulation units. + +breakpoint set -n inlined_42 -f search-support-files.h +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-support-files.h +# CHECK-NEXT: Breakpoint 4: where = dummy.out`inlined_42() + 4 at search-support-files.h:1:20, address = 0x0{{.*}} + +#------------------------------------------------------------------------------- +# Set breakpoint by function name and source filename. This time the file +# doesn't exist to prove that we haven't widen the search space too much. When +# we search for a function in file that doesn't exist, we should get no results. + +breakpoint set -n inlined_42 -f file-not-existing.h +# CHECK: (lldb) breakpoint set -n inlined_42 -f file-not-existing.h +# CHECK-NEXT: Breakpoint 5: no locations (pending). +# CHECK-NEXT: WARNING: Unable to resolve breakpoint to any actual locations.