Index: include/lldb/Core/SearchFilter.h =================================================================== --- include/lldb/Core/SearchFilter.h +++ include/lldb/Core/SearchFilter.h @@ -184,6 +184,18 @@ virtual bool CompUnitPasses(CompileUnit &compUnit); //------------------------------------------------------------------ + /// Call this method with a Function to see if \a function passes the + /// filter. + /// + /// @param[in] function + /// The Functions to check against the filter. + /// + /// @return + /// \b true if \a function passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool FunctionPasses(Function &function); + + //------------------------------------------------------------------ /// Call this method to do the search using the Searcher. /// /// @param[in] searcher Index: packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py +++ packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -106,10 +106,35 @@ wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # one with the wrong file - also should not fire: + file_list.Clear() module_list.Clear() file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + # Now make sure the CU level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # Now make sure the Function level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + # Make sure these didn't get locations: for i in range(0, len(wrong)): self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) @@ -158,12 +183,11 @@ self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules") - # Make a breakpoint that searches at function depth - FIXME: uncomment this when I fix the function - # depth search. - #bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) - #self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") - #self.expect("script print resolver.Resolver.got_files", substrs=["3"], msg="Was only passed modules") - #self.expect("script print resolver.Resolver.func_list", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions") + # Make a breakpoint that searches at function depth: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["3"], msg="Was only passed modules") + self.expect("script print resolver.Resolver.func_list", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions") def do_test_cli(self): target = self.make_target_and_import() Index: packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py +++ packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -24,10 +24,9 @@ if sym_ctx.function.IsValid(): Resolver.got_files = 3 func_name = sym_ctx.function.GetName() - print("got called with: ", func_name) Resolver.func_list.append(func_name) if sym_name == func_name: - self.bkpt.AddLocations(func.GetStartAddress()) + self.bkpt.AddLocation(sym_ctx.function.GetStartAddress()) return if sym_ctx.module.IsValid(): Index: source/Core/SearchFilter.cpp =================================================================== --- source/Core/SearchFilter.cpp +++ source/Core/SearchFilter.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/ModuleList.h" // for ModuleList #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" // for SymbolContext +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ConstString.h" // for ConstString #include "lldb/Utility/Status.h" // for Status @@ -147,6 +148,15 @@ bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; } +bool SearchFilter::FunctionPasses(Function &function) { + // This is a slightly cheesy job, but since we don't have finer grained + // filters yet, just checking that the start address passes is probably + // good enough for the base class behavior. + Address addr = function.GetAddressRange().GetBaseAddress(); + return AddressPasses(addr); +} + + uint32_t SearchFilter::GetFilterRequiredItems() { return (lldb::SymbolContextItem)0; } @@ -311,8 +321,33 @@ return Searcher::eCallbackReturnContinue; else if (shouldContinue == Searcher::eCallbackReturnStop) return shouldContinue; - } else if (searcher.GetDepth() == lldb::eSearchDepthFunction) { - // FIXME Descend to block. + } else { + // First make sure this compile unit's functions are parsed + // since CompUnit::ForeachFunction only iterates over already + // parsed functions. + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + if (!sym_vendor) + continue; + SymbolContext sym_ctx; + cu_sp->CalculateSymbolContext(&sym_ctx); + if (!sym_vendor->ParseCompileUnitFunctions(sym_ctx)) + continue; + // If we got any functions, use ForeachFunction to do the iteration. + cu_sp->ForeachFunction([&](const FunctionSP &func_sp) { + if (!FunctionPasses(*func_sp.get())) + return false; // Didn't pass the filter, just keep going. + if (searcher.GetDepth() == lldb::eSearchDepthFunction) { + SymbolContext matchingContext(m_target_sp, module_sp, + cu_sp.get(), func_sp.get()); + shouldContinue = searcher.SearchCallback(*this, + matchingContext, + nullptr, false); + } else { + shouldContinue = DoFunctionIteration(func_sp.get(), context, + searcher); + } + return shouldContinue != Searcher::eCallbackReturnContinue; + }); } } }