New RenderScript command to break on all kernels
authorEwan Crawford <ewan@codeplay.com>
Thu, 10 Sep 2015 10:08:48 +0000 (10:08 +0000)
committerEwan Crawford <ewan@codeplay.com>
Thu, 10 Sep 2015 10:08:48 +0000 (10:08 +0000)
Patch adds a command to RenderScript plugin allowing users to automatically set breakpoints on every RS kernel.

Command syntax is 'language renderscript kernel breakpoint all <enable/disable>.'
Enable sets breakpoints on all currently loaded kernels, and any kernels which will be loaded in future.
Disable results in breakpoints no longer being set on loaded kernels, but doesn't affect existing breakpoints.

Current command 'language renderscript kernel breakpoint' is changed to 'language renderscript kernel breakpoint set'

Reviewed by: clayborg, jingham
Subscribers: lldb-commits, ADodds, domipheus
Differential Revision: http://reviews.llvm.org/D12728

llvm-svn: 247262

lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h

index 1959712..9289efa 100644 (file)
@@ -538,7 +538,14 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
         for (const auto &rs_module : m_rsmodules)
         {
             if (rs_module->m_module == module_sp)
+            {
+                // Check if the user has enabled automatically breaking on
+                // all RS kernels.
+                if (m_breakAllKernels)
+                    BreakOnModuleKernels(rs_module);
+
                 return false;
+            }
         }
         bool module_loaded = false;
         switch (GetModuleKind(module_sp))
@@ -809,6 +816,73 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const
     strm.IndentLess();
 }
 
+// Set breakpoints on every kernel found in RS module
+void
+RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
+{
+    for (const auto &kernel : rsmodule_sp->m_kernels)
+    {
+        // Don't set breakpoint on 'root' kernel
+        if (strcmp(kernel.m_name.AsCString(), "root") == 0)
+            continue;
+
+        CreateKernelBreakpoint(kernel.m_name);
+    }
+}
+
+// Method is internally called by the 'kernel breakpoint all' command to
+// enable or disable breaking on all kernels.
+//
+// When do_break is true we want to enable this functionality.
+// When do_break is false we want to disable it.
+void
+RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    InitSearchFilter(target);
+
+    // Set breakpoints on all the kernels
+    if (do_break && !m_breakAllKernels)
+    {
+        m_breakAllKernels = true;
+
+        for (const auto &module : m_rsmodules)
+            BreakOnModuleKernels(module);
+
+        if (log)
+            log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
+                        "- breakpoints set on all currently loaded kernels");
+    }
+    else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
+    {
+        m_breakAllKernels = false;
+
+        if (log)
+            log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
+    }
+}
+
+// Given the name of a kernel this function creates a breakpoint using our
+// own breakpoint resolver, and returns the Breakpoint shared pointer.
+BreakpointSP
+RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    if (!m_filtersp)
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
+        return nullptr;
+    }
+
+    BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
+    BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
+
+    return bp;
+}
+
 void
 RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
 {
@@ -818,12 +892,10 @@ RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* nam
         return;
     }
 
-    SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches(target));
+    InitSearchFilter(target);
 
     ConstString kernel_name(name);
-    BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, kernel_name));
-
-    BreakpointSP bp = target->CreateBreakpoint(filter_sp, resolver_sp, false, false, false);
+    BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
     if (bp)
         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
 
@@ -1029,18 +1101,18 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
     }
 };
 
-class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectParsed
+class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
 {
   private:
   public:
-    CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
-        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint",
-                              "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint <kernel_name>",
+    CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
+        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
+                              "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
     {
     }
 
-    ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
+    ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
 
     bool
     DoExecute(Args &command, CommandReturnObject &result)
@@ -1072,6 +1144,77 @@ class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectPar
     }
 };
 
+class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
+{
+  private:
+  public:
+    CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
+        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
+                              "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
+                              "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
+                              "but does not remove currently set breakpoints.",
+                              "renderscript kernel breakpoint all <enable/disable>",
+                              eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+    {
+    }
+
+    ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
+
+    bool
+    DoExecute(Args &command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        if (argc != 1)
+        {
+            result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        RenderScriptRuntime *runtime =
+          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+        bool do_break = false;
+        const char* argument = command.GetArgumentAtIndex(0);
+        if (strcmp(argument, "enable") == 0)
+        {
+            do_break = true;
+            result.AppendMessage("Breakpoints will be set on all kernels.");
+        }
+        else if (strcmp(argument, "disable") == 0)
+        {
+            do_break = false;
+            result.AppendMessage("Breakpoints will not be set on any new kernels.");
+        }
+        else
+        {
+            result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
+
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return true;
+    }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
+{
+  private:
+  public:
+    CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
+        : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
+                                 nullptr)
+    {
+        LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
+        LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
+    }
+
+    ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
+};
+
 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
 {
   private:
@@ -1172,7 +1315,8 @@ RenderScriptRuntime::Initiate()
 }
 
 RenderScriptRuntime::RenderScriptRuntime(Process *process)
-    : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false)
+    : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
+      m_breakAllKernels(false)
 {
     ModulesDidLoad(process->GetTarget().GetImages());
 }
index 755d33d..7b9f6cf 100644 (file)
@@ -200,6 +200,8 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
 
     void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error, lldb::TargetSP target);
 
+    void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
+
     void Status(Stream &strm) const;
 
     virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) {
@@ -213,10 +215,20 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
     void Initiate();
     
   protected:
+
+    void InitSearchFilter(lldb::TargetSP target)
+    {
+        if (!m_filtersp)
+            m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
+    }
     
     void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
 
     void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+
+    lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
+
+    void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
     
     struct RuntimeHook;
     typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context);  // Please do this!
@@ -257,8 +269,11 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
     std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
     std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
 
+    lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
+
     bool m_initiated;
     bool m_debuggerPresentFlagged;
+    bool m_breakAllKernels;
     static const HookDefn s_runtimeHookDefns[];
     static const size_t s_runtimeHookCount;