Make the eSearchDepthFunction searches work, add tests
authorJim Ingham <jingham@apple.com>
Fri, 14 Sep 2018 18:41:40 +0000 (18:41 +0000)
committerJim Ingham <jingham@apple.com>
Fri, 14 Sep 2018 18:41:40 +0000 (18:41 +0000)
using the scripted breakpoint resolver.

Differential Revision: https://reviews.llvm.org/D52111

llvm-svn: 342259

lldb/include/lldb/Core/SearchFilter.h
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py
lldb/source/Core/SearchFilter.cpp

index 08d4b95..57b3831 100644 (file)
@@ -184,6 +184,18 @@ public:
   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 9f4c180..62f756b 100644 (file)
@@ -106,10 +106,35 @@ class TestScriptedResolver(TestBase):
         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 @@ class TestScriptedResolver(TestBase):
         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 5e068d6..61f5f2d 100644 (file)
@@ -24,10 +24,9 @@ class Resolver:
       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 50c006c..baef7b0 100644 (file)
@@ -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(FileSpec &fileSpec) { return true; }
 
 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 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp,
             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;
+          });
         }
       }
     }