[Lldb-commits] [lldb] r373675 - Pass an SBStructuredData to scripted ThreadPlans on use.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 3 15:50:18 PDT 2019


Author: jingham
Date: Thu Oct  3 15:50:18 2019
New Revision: 373675

URL: http://llvm.org/viewvc/llvm-project?rev=373675&view=rev
Log:
Pass an SBStructuredData to scripted ThreadPlans on use.

This will allow us to write reusable scripted ThreadPlans, since
you can use key/value pairs with known keys in the plan to parametrize
its behavior.

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

Modified:
    lldb/trunk/include/lldb/API/SBStructuredData.h
    lldb/trunk/include/lldb/API/SBThread.h
    lldb/trunk/include/lldb/API/SBThreadPlan.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlanPython.h
    lldb/trunk/packages/Python/lldbsuite/test/commands/help/TestHelp.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
    lldb/trunk/scripts/Python/python-wrapper.swig
    lldb/trunk/scripts/interface/SBThread.i
    lldb/trunk/scripts/interface/SBThreadPlan.i
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/API/SBThreadPlan.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanPython.cpp
    lldb/trunk/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Modified: lldb/trunk/include/lldb/API/SBStructuredData.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBStructuredData.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBStructuredData.h (original)
+++ lldb/trunk/include/lldb/API/SBStructuredData.h Thu Oct  3 15:50:18 2019
@@ -91,6 +91,8 @@ protected:
   friend class SBTraceOptions;
   friend class SBDebugger;
   friend class SBTarget;
+  friend class SBThread;
+  friend class SBThreadPlan;
 
   StructuredDataImplUP m_impl_up;
 };

Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Thu Oct  3 15:50:18 2019
@@ -122,6 +122,10 @@ public:
   SBError StepUsingScriptedThreadPlan(const char *script_class_name,
                                       bool resume_immediately);
 
+  SBError StepUsingScriptedThreadPlan(const char *script_class_name,
+                                      lldb::SBStructuredData &args_data,
+                                      bool resume_immediately);
+
   SBError JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line);
 
   void RunToAddress(lldb::addr_t addr);

Modified: lldb/trunk/include/lldb/API/SBThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThreadPlan.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThreadPlan.h (original)
+++ lldb/trunk/include/lldb/API/SBThreadPlan.h Thu Oct  3 15:50:18 2019
@@ -28,6 +28,9 @@ public:
 
   SBThreadPlan(lldb::SBThread &thread, const char *class_name);
 
+  SBThreadPlan(lldb::SBThread &thread, const char *class_name, 
+               lldb::SBStructuredData &args_data);
+
   ~SBThreadPlan();
 
   explicit operator bool() const;
@@ -100,6 +103,9 @@ public:
   SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name);
   SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name,
                                               SBError &error);
+  SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name,
+                                              lldb::SBStructuredData &args_data,
+                                              SBError &error);
 
 private:
   friend class SBBreakpoint;

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Thu Oct  3 15:50:18 2019
@@ -208,6 +208,7 @@ public:
 
   virtual StructuredData::ObjectSP
   CreateScriptedThreadPlan(const char *class_name,
+                           StructuredDataImpl *args_data,
                            std::string &error_str,
                            lldb::ThreadPlanSP thread_plan_sp) {
     return StructuredData::ObjectSP();

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Thu Oct  3 15:50:18 2019
@@ -899,6 +899,7 @@ public:
 
   virtual lldb::ThreadPlanSP
   QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
+                                 StructuredData::ObjectSP extra_args_sp,  
                                  bool stop_other_threads, Status &status);
 
   // Thread Plan accessors:

Modified: lldb/trunk/include/lldb/Target/ThreadPlanPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanPython.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanPython.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanPython.h Thu Oct  3 15:50:18 2019
@@ -12,6 +12,8 @@
 
 #include <string>
 
+#include "lldb/lldb-forward.h"
+
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
@@ -29,7 +31,8 @@ namespace lldb_private {
 
 class ThreadPlanPython : public ThreadPlan {
 public:
-  ThreadPlanPython(Thread &thread, const char *class_name);
+  ThreadPlanPython(Thread &thread, const char *class_name, 
+                   StructuredDataImpl *args_data);
   ~ThreadPlanPython() override;
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
@@ -55,6 +58,10 @@ protected:
 
 private:
   std::string m_class_name;
+  StructuredDataImpl *m_args_data; // We own this, but the implementation
+                                   // has to manage the UP (since that is
+                                   // how it gets stored in the
+                                   // SBStructuredData).
   std::string m_error_str;
   StructuredData::ObjectSP m_implementation_sp;
   bool m_did_push;

Modified: lldb/trunk/packages/Python/lldbsuite/test/commands/help/TestHelp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/commands/help/TestHelp.py?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/commands/help/TestHelp.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/commands/help/TestHelp.py Thu Oct  3 15:50:18 2019
@@ -188,7 +188,7 @@ class HelpCommandTestCase(TestBase):
     def test_help_next_shows_options(self):
         """Test that 'help next' shows all the options for thread step-over"""
         self.expect("help next",
-                    substrs=['--python-class', '--run-mode'], matching=True)
+                    substrs=['--step-out-avoids-no-debug', '--run-mode'], matching=True)
 
     @no_debug_info_test
     def test_help_provides_alternatives(self):

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py Thu Oct  3 15:50:18 2019
@@ -38,18 +38,29 @@ class StepScripted(StepWithChild):
 
 # This plan does a step-over until a variable changes value.
 class StepUntil(StepWithChild):
-    def __init__(self, thread_plan, dict):
+    def __init__(self, thread_plan, args_data, dict):
         self.frame = thread_plan.GetThread().frames[0]
         self.target = thread_plan.GetThread().GetProcess().GetTarget()
-        self.value = self.frame.FindVariable("foo")
+        func_entry = args_data.GetValueForKey("variable_name")
+        
+        if not func_entry.IsValid():
+            print("Did not get a valid entry for variable_name")
+        func_name = func_entry.GetStringValue(100)
+
+        self.value = self.frame.FindVariable(func_name)
+        if self.value.GetError().Fail():
+            print("Failed to get foo value: %s"%(self.value.GetError().GetCString()))
+        else:
+            print("'foo' value: %d"%(self.value.GetValueAsUnsigned()))
+
         StepWithChild.__init__(self, thread_plan)
 
+
     def queue_child_thread_plan(self):
         le = self.frame.GetLineEntry()
         start_addr = le.GetStartAddress() 
         start = start_addr.GetLoadAddress(self.target)
         end = le.GetEndAddress().GetLoadAddress(self.target)
-        print("Stepping from 0x%x to 0x%x (0x%x)"%(start, end, end - start))
         return self.thread_plan.QueueThreadPlanForStepOverRange(start_addr,
                                                                 end - start)
 

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py Thu Oct  3 15:50:18 2019
@@ -63,7 +63,14 @@ class StepScriptedTestCase(TestBase):
         self.assertEqual(stop_id, process.GetStopID(), "Process didn't run")
         
     def test_checking_variable(self):
-        """Test that we can call SBValue API's from a scripted thread plan"""
+        """Test that we can call SBValue API's from a scripted thread plan - using SBAPI's to step"""
+        self.do_test_checking_variable(False)
+        
+    def test_checking_variable_cli(self):
+        """Test that we can call SBValue API's from a scripted thread plan - using cli to step"""
+        self.do_test_checking_variable(True)
+        
+    def do_test_checking_variable(self, use_cli):
         self.build()
         (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
                                                                             "Set a breakpoint here",
@@ -75,8 +82,21 @@ class StepScriptedTestCase(TestBase):
         self.assertTrue(foo_val.GetError().Success(), "Got the foo variable")
         self.assertEqual(foo_val.GetValueAsUnsigned(), 10, "foo starts at 10")
 
-        err = thread.StepUsingScriptedThreadPlan("Steps.StepUntil")
-        self.assertTrue(err.Success(), err.GetCString())
+        if use_cli:
+            result = lldb.SBCommandReturnObject()
+            self.dbg.GetCommandInterpreter().HandleCommand(
+                "thread step-scripted -C Steps.StepUntil -k variable_name -v foo",
+                result)
+            self.assertTrue(result.Succeeded())
+        else:
+            args_data = lldb.SBStructuredData()
+            data = lldb.SBStream()
+            data.Print('{"variable_name" : "foo"}')
+            error = args_data.SetFromJSON(data)
+            self.assertTrue(error.Success(), "Made the args_data correctly")
+
+            err = thread.StepUsingScriptedThreadPlan("Steps.StepUntil", args_data, True)
+            self.assertTrue(err.Success(), err.GetCString())
 
         # We should not have exited:
         self.assertEqual(process.GetState(), lldb.eStateStopped, "We are stopped")

Modified: lldb/trunk/scripts/Python/python-wrapper.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-wrapper.swig (original)
+++ lldb/trunk/scripts/Python/python-wrapper.swig Thu Oct  3 15:50:18 2019
@@ -250,6 +250,7 @@ LLDBSwigPythonCreateScriptedThreadPlan
 (
     const char *python_class_name,
     const char *session_dictionary_name,
+    lldb_private::StructuredDataImpl *args_impl,
     std::string &error_string,
     const lldb::ThreadPlanSP& thread_plan_sp
 )
@@ -279,7 +280,23 @@ LLDBSwigPythonCreateScriptedThreadPlan
     if (!tp_arg.IsAllocated())
         Py_RETURN_NONE;
 
-    PythonObject result = pfunc(tp_arg, dict);
+    PythonObject result = {};
+    size_t init_num_args = pfunc.GetNumInitArguments().count;
+    if (init_num_args == 3) {
+        if (args_impl != nullptr) {
+           error_string.assign("args passed, but __init__ does not take an args dictionary");
+           Py_RETURN_NONE;
+        }
+        result = pfunc(tp_arg, dict);
+    } else if (init_num_args = 4) {
+        lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
+        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
+        result = pfunc(tp_arg, args_arg, dict);
+    } else {
+        error_string.assign("wrong number of arguments in __init__, should be 1 or 2 (not including self & dict)");
+        Py_RETURN_NONE;
+    }
+
     // FIXME: At this point we should check that the class we found supports all the methods
     // that we need.
 

Modified: lldb/trunk/scripts/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBThread.i?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBThread.i (original)
+++ lldb/trunk/scripts/interface/SBThread.i Thu Oct  3 15:50:18 2019
@@ -254,6 +254,11 @@ public:
     StepUsingScriptedThreadPlan (const char *script_class_name, bool resume_immediately);
 
     SBError
+    StepUsingScriptedThreadPlan(const char *script_class_name,
+                                lldb::SBStructuredData &args_data,
+                                bool resume_immediately);
+
+    SBError
     JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
 
     void

Modified: lldb/trunk/scripts/interface/SBThreadPlan.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBThreadPlan.i?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBThreadPlan.i (original)
+++ lldb/trunk/scripts/interface/SBThreadPlan.i Thu Oct  3 15:50:18 2019
@@ -109,6 +109,14 @@ public:
     SBThreadPlan
     QueueThreadPlanForStepScripted(const char *script_class_name);
 
+    SBThreadPlan
+    QueueThreadPlanForStepScripted(const char *script_class_name,
+                                   SBError &error);
+    SBThreadPlan
+    QueueThreadPlanForStepScripted(const char *script_class_name,
+                                   SBStructuredData &args_data,
+                                   SBError &error);
+
 
 protected:
     friend class SBBreakpoint;

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Thu Oct  3 15:50:18 2019
@@ -16,6 +16,7 @@
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBSymbolContext.h"
 #include "lldb/API/SBThreadCollection.h"
 #include "lldb/API/SBThreadPlan.h"
@@ -23,6 +24,7 @@
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Symbol/CompileUnit.h"
@@ -965,9 +967,24 @@ SBError SBThread::StepUsingScriptedThrea
 }
 
 SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
+                                            bool resume_immediately) {
+  LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
+                     (const char *, bool), script_class_name, 
+                     resume_immediately);
+
+  lldb::SBStructuredData no_data;
+  return LLDB_RECORD_RESULT(
+      StepUsingScriptedThreadPlan(script_class_name, 
+                                  no_data, 
+                                  resume_immediately));
+}
+
+SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
+                                              SBStructuredData &args_data,
                                               bool resume_immediately) {
   LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
-                     (const char *, bool), script_class_name,
+                     (const char *, lldb::SBStructuredData &, bool), 
+                     script_class_name, args_data,
                      resume_immediately);
 
   SBError error;
@@ -982,8 +999,10 @@ SBError SBThread::StepUsingScriptedThrea
 
   Thread *thread = exe_ctx.GetThreadPtr();
   Status new_plan_status;
+  StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
+
   ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
-      false, script_class_name, false, new_plan_status);
+      false, script_class_name, obj_sp, false, new_plan_status);
 
   if (new_plan_status.Fail()) {
     error.SetErrorString(new_plan_status.AsCString());
@@ -1460,6 +1479,8 @@ void RegisterMethods<SBThread>(Registry
                        (const char *));
   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
                        (const char *, bool));
+  LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
+                       (const char *, SBStructuredData &, bool));
   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, JumpToLine,
                        (lldb::SBFileSpec &, uint32_t));
   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, ReturnFromFrame,

Modified: lldb/trunk/source/API/SBThreadPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThreadPlan.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThreadPlan.cpp (original)
+++ lldb/trunk/source/API/SBThreadPlan.cpp Thu Oct  3 15:50:18 2019
@@ -11,10 +11,12 @@
 
 #include "lldb/API/SBFileSpec.h"
 #include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBSymbolContext.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/SymbolContext.h"
@@ -67,7 +69,20 @@ SBThreadPlan::SBThreadPlan(lldb::SBThrea
 
   Thread *thread = sb_thread.get();
   if (thread)
-    m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name);
+    m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name, 
+                                                     nullptr);
+}
+
+SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name,
+                           lldb::SBStructuredData &args_data) {
+  LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *,
+                                         SBStructuredData &),
+                          sb_thread, class_name, args_data);
+
+  Thread *thread = sb_thread.get();
+  if (thread)
+    m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name, 
+                                                     args_data.m_impl_up.get());
 }
 
 // Assignment operator
@@ -368,9 +383,35 @@ SBThreadPlan::QueueThreadPlanForStepScri
 
   if (m_opaque_sp) {
     Status plan_status;
+    StructuredData::ObjectSP empty_args;
     SBThreadPlan plan =
         SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
-            false, script_class_name, false, plan_status));
+            false, script_class_name, empty_args, false, plan_status));
+
+    if (plan_status.Fail())
+      error.SetErrorString(plan_status.AsCString());
+
+    return LLDB_RECORD_RESULT(plan);
+  } else {
+    return LLDB_RECORD_RESULT(SBThreadPlan());
+  }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,
+                                             lldb::SBStructuredData &args_data,
+                                             SBError &error) {
+  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan,
+                     QueueThreadPlanForStepScripted,
+                     (const char *, lldb::SBStructuredData &, lldb::SBError &), 
+                     script_class_name, args_data, error);
+
+  if (m_opaque_sp) {
+    Status plan_status;
+    StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();
+    SBThreadPlan plan =
+        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
+            false, script_class_name, args_obj, false, plan_status));
 
     if (plan_status.Fail())
       error.SetErrorString(plan_status.AsCString());
@@ -390,6 +431,8 @@ void RegisterMethods<SBThreadPlan>(Regis
   LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &));
   LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &));
   LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *));
+  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *,
+                       lldb::SBStructuredData &));
   LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &,
                        SBThreadPlan, operator=,(const lldb::SBThreadPlan &));
   LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ());
@@ -433,6 +476,10 @@ void RegisterMethods<SBThreadPlan>(Regis
   LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan,
                        QueueThreadPlanForStepScripted,
                        (const char *, lldb::SBError &));
+  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan,
+                       QueueThreadPlanForStepScripted,
+                       (const char *, lldb::SBStructuredData &,
+                       lldb::SBError &));
 }
 
 }

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Thu Oct  3 15:50:18 2019
@@ -16,6 +16,7 @@
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
 #include "lldb/Interpreter/Options.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
@@ -401,127 +402,122 @@ static constexpr OptionEnumValues TriRun
 #define LLDB_OPTIONS_thread_step_scope
 #include "CommandOptions.inc"
 
-class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
+class ThreadStepScopeOptionGroup : public OptionGroup {
 public:
-  class CommandOptions : public Options {
-  public:
-    CommandOptions() : Options() {
-      // Keep default values of all options in one place: OptionParsingStarting
-      // ()
-      OptionParsingStarting(nullptr);
-    }
-
-    ~CommandOptions() override = default;
-
-    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
-                          ExecutionContext *execution_context) override {
-      Status error;
-      const int short_option = m_getopt_table[option_idx].val;
-
-      switch (short_option) {
-      case 'a': {
-        bool success;
-        bool avoid_no_debug =
-            OptionArgParser::ToBoolean(option_arg, true, &success);
-        if (!success)
-          error.SetErrorStringWithFormat(
-              "invalid boolean value for option '%c'", short_option);
-        else {
-          m_step_in_avoid_no_debug =
-              avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
-        }
-      } break;
-
-      case 'A': {
-        bool success;
-        bool avoid_no_debug =
-            OptionArgParser::ToBoolean(option_arg, true, &success);
-        if (!success)
-          error.SetErrorStringWithFormat(
-              "invalid boolean value for option '%c'", short_option);
-        else {
-          m_step_out_avoid_no_debug =
-              avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
-        }
-      } break;
-
-      case 'c':
-        if (option_arg.getAsInteger(0, m_step_count))
-          error.SetErrorStringWithFormat("invalid step count '%s'",
-                                         option_arg.str().c_str());
-        break;
+  ThreadStepScopeOptionGroup() : OptionGroup() {
+    // Keep default values of all options in one place: OptionParsingStarting
+    // ()
+    OptionParsingStarting(nullptr);
+  }
 
-      case 'C':
-        m_class_name.clear();
-        m_class_name.assign(option_arg);
-        break;
+  ~ThreadStepScopeOptionGroup() override = default;
 
-      case 'm': {
-        auto enum_values = GetDefinitions()[option_idx].enum_values;
-        m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
-            option_arg, enum_values, eOnlyDuringStepping, error);
-      } break;
-
-      case 'e':
-        if (option_arg == "block") {
-          m_end_line_is_block_end = true;
-          break;
-        }
-        if (option_arg.getAsInteger(0, m_end_line))
-          error.SetErrorStringWithFormat("invalid end line number '%s'",
-                                         option_arg.str().c_str());
-        break;
+  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+    return llvm::makeArrayRef(g_thread_step_scope_options);
+  }
 
-      case 'r':
-        m_avoid_regexp.clear();
-        m_avoid_regexp.assign(option_arg);
-        break;
+  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+                        ExecutionContext *execution_context) override {
+    Status error;
+    const int short_option 
+        = g_thread_step_scope_options[option_idx].short_option;
 
-      case 't':
-        m_step_in_target.clear();
-        m_step_in_target.assign(option_arg);
+    switch (short_option) {
+    case 'a': {
+      bool success;
+      bool avoid_no_debug =
+          OptionArgParser::ToBoolean(option_arg, true, &success);
+      if (!success)
+        error.SetErrorStringWithFormat(
+            "invalid boolean value for option '%c'", short_option);
+      else {
+        m_step_in_avoid_no_debug =
+            avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+      }
+    } break;
+
+    case 'A': {
+      bool success;
+      bool avoid_no_debug =
+          OptionArgParser::ToBoolean(option_arg, true, &success);
+      if (!success)
+        error.SetErrorStringWithFormat(
+            "invalid boolean value for option '%c'", short_option);
+      else {
+        m_step_out_avoid_no_debug =
+            avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+      }
+    } break;
+
+    case 'c':
+      if (option_arg.getAsInteger(0, m_step_count))
+        error.SetErrorStringWithFormat("invalid step count '%s'",
+                                       option_arg.str().c_str());
+      break;
+
+    case 'm': {
+      auto enum_values = GetDefinitions()[option_idx].enum_values;
+      m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
+          option_arg, enum_values, eOnlyDuringStepping, error);
+    } break;
+
+    case 'e':
+      if (option_arg == "block") {
+        m_end_line_is_block_end = true;
         break;
-
-      default:
-        llvm_unreachable("Unimplemented option");
       }
-      return error;
-    }
-
-    void OptionParsingStarting(ExecutionContext *execution_context) override {
-      m_step_in_avoid_no_debug = eLazyBoolCalculate;
-      m_step_out_avoid_no_debug = eLazyBoolCalculate;
-      m_run_mode = eOnlyDuringStepping;
-
-      // Check if we are in Non-Stop mode
-      TargetSP target_sp =
-          execution_context ? execution_context->GetTargetSP() : TargetSP();
-      if (target_sp && target_sp->GetNonStopModeEnabled())
-        m_run_mode = eOnlyThisThread;
+      if (option_arg.getAsInteger(0, m_end_line))
+        error.SetErrorStringWithFormat("invalid end line number '%s'",
+                                       option_arg.str().c_str());
+      break;
 
+    case 'r':
       m_avoid_regexp.clear();
+      m_avoid_regexp.assign(option_arg);
+      break;
+
+    case 't':
       m_step_in_target.clear();
-      m_class_name.clear();
-      m_step_count = 1;
-      m_end_line = LLDB_INVALID_LINE_NUMBER;
-      m_end_line_is_block_end = false;
-    }
+      m_step_in_target.assign(option_arg);
+      break;
 
-    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
-      return llvm::makeArrayRef(g_thread_step_scope_options);
+    default:
+      llvm_unreachable("Unimplemented option");
     }
+    return error;
+  }
 
-    // Instance variables to hold the values for command options.
-    LazyBool m_step_in_avoid_no_debug;
-    LazyBool m_step_out_avoid_no_debug;
-    RunMode m_run_mode;
-    std::string m_avoid_regexp;
-    std::string m_step_in_target;
-    std::string m_class_name;
-    uint32_t m_step_count;
-    uint32_t m_end_line;
-    bool m_end_line_is_block_end;
-  };
+  void OptionParsingStarting(ExecutionContext *execution_context) override {
+    m_step_in_avoid_no_debug = eLazyBoolCalculate;
+    m_step_out_avoid_no_debug = eLazyBoolCalculate;
+    m_run_mode = eOnlyDuringStepping;
+
+    // Check if we are in Non-Stop mode
+    TargetSP target_sp =
+        execution_context ? execution_context->GetTargetSP() : TargetSP();
+    if (target_sp && target_sp->GetNonStopModeEnabled())
+      m_run_mode = eOnlyThisThread;
+
+    m_avoid_regexp.clear();
+    m_step_in_target.clear();
+    m_step_count = 1;
+    m_end_line = LLDB_INVALID_LINE_NUMBER;
+    m_end_line_is_block_end = false;
+  }
+
+  // Instance variables to hold the values for command options.
+  LazyBool m_step_in_avoid_no_debug;
+  LazyBool m_step_out_avoid_no_debug;
+  RunMode m_run_mode;
+  std::string m_avoid_regexp;
+  std::string m_step_in_target;
+  uint32_t m_step_count;
+  uint32_t m_end_line;
+  bool m_end_line_is_block_end;
+};
+
+class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
+public:
 
   CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter,
                                           const char *name, const char *help,
@@ -533,7 +529,8 @@ public:
                                 eCommandTryTargetAPILock |
                                 eCommandProcessMustBeLaunched |
                                 eCommandProcessMustBePaused),
-        m_step_type(step_type), m_step_scope(step_scope), m_options() {
+        m_step_type(step_type), m_step_scope(step_scope), m_options(),
+        m_class_options("scripted step", 'C') {
     CommandArgumentEntry arg;
     CommandArgumentData thread_id_arg;
 
@@ -547,11 +544,19 @@ public:
 
     // Push the data for the first argument into the m_arguments vector.
     m_arguments.push_back(arg);
+    
+    if (step_type == eStepTypeScripted) {
+      m_all_options.Append(&m_class_options, LLDB_OPT_SET_1, LLDB_OPT_SET_1);
+    }
+    m_all_options.Append(&m_options);
+    m_all_options.Finalize();
   }
 
   ~CommandObjectThreadStepWithTypeAndScope() override = default;
 
-  Options *GetOptions() override { return &m_options; }
+  Options *GetOptions() override { 
+      return &m_all_options;
+  }
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -591,15 +596,15 @@ protected:
     }
 
     if (m_step_type == eStepTypeScripted) {
-      if (m_options.m_class_name.empty()) {
+      if (m_class_options.GetClassName().empty()) {
         result.AppendErrorWithFormat("empty class name for scripted step.");
         result.SetStatus(eReturnStatusFailed);
         return false;
       } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists(
-                     m_options.m_class_name.c_str())) {
+                     m_class_options.GetClassName().c_str())) {
         result.AppendErrorWithFormat(
             "class for scripted step: \"%s\" does not exist.",
-            m_options.m_class_name.c_str());
+            m_class_options.GetClassName().c_str());
         result.SetStatus(eReturnStatusFailed);
         return false;
       }
@@ -715,7 +720,8 @@ protected:
           m_options.m_step_out_avoid_no_debug);
     } else if (m_step_type == eStepTypeScripted) {
       new_plan_sp = thread->QueueThreadPlanForStepScripted(
-          abort_other_plans, m_options.m_class_name.c_str(),
+          abort_other_plans, m_class_options.GetClassName().c_str(), 
+          m_class_options.GetStructuredData(),
           bool_stop_other_threads, new_plan_status);
     } else {
       result.AppendError("step type is not supported");
@@ -783,7 +789,9 @@ protected:
 protected:
   StepType m_step_type;
   StepScope m_step_scope;
-  CommandOptions m_options;
+  ThreadStepScopeOptionGroup m_options;
+  OptionGroupPythonClassWithDict m_class_options;
+  OptionGroupOptions m_all_options;
 };
 
 // CommandObjectThreadContinue
@@ -2060,7 +2068,11 @@ CommandObjectMultiwordThread::CommandObj
       "step-scripted",
       CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
           interpreter, "thread step-scripted",
-          "Step as instructed by the script class passed in the -C option.",
+          "Step as instructed by the script class passed in the -C option.  "
+          "You can also specify a dictionary of key (-k) and value (-v) pairs "
+          "that will be used to populate an SBStructuredData Dictionary, which "
+          "will be passed to the constructor of the class implementing the "
+          "scripted step.  See the Python Reference for more details.",
           nullptr, eStepTypeScripted, eStepScopeSource)));
 
   LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp Thu Oct  3 15:50:18 2019
@@ -887,6 +887,23 @@ void PythonCallable::Reset(PyRefType typ
   PythonObject::Reset(PyRefType::Borrowed, result.get());
 }
 
+PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
+  ArgInfo result = {0, false, false, false};
+  if (!IsValid())
+    return result;
+  PyObject *py_func_obj = m_py_obj;
+  if (!PyClass_Check(m_py_obj))
+    return result;
+
+  PythonObject __init__ = GetAttributeValue("__init__");
+  if (__init__.IsValid() ) {
+    auto __init_callable__ = __init__.AsType<PythonCallable>();
+    if (__init_callable__.IsValid())
+      return __init_callable__.GetNumArguments();
+  }
+  return result;
+}
+
 PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
   ArgInfo result = {0, false, false, false};
   if (!IsValid())

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h Thu Oct  3 15:50:18 2019
@@ -438,6 +438,10 @@ public:
   void Reset(PyRefType type, PyObject *py_obj) override;
 
   ArgInfo GetNumArguments() const;
+  
+  // If the callable is a Py_Class, then find the number of arguments
+  // of the __init__ method.
+  ArgInfo GetNumInitArguments() const;
 
   PythonObject operator()();
 

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Thu Oct  3 15:50:18 2019
@@ -97,6 +97,7 @@ LLDBSwigPythonCreateCommandObject(const
 
 extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan(
     const char *python_class_name, const char *session_dictionary_name,
+    StructuredDataImpl *args_data,
     std::string &error_string,
     const lldb::ThreadPlanSP &thread_plan_sp);
 
@@ -1845,7 +1846,8 @@ StructuredData::DictionarySP ScriptInter
 }
 
 StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
-    const char *class_name, std::string &error_str, 
+    const char *class_name, StructuredDataImpl *args_data,
+    std::string &error_str, 
     lldb::ThreadPlanSP thread_plan_sp) {
   if (class_name == nullptr || class_name[0] == '\0')
     return StructuredData::ObjectSP();
@@ -1868,7 +1870,7 @@ StructuredData::ObjectSP ScriptInterpret
                    Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
     ret_val = LLDBSwigPythonCreateScriptedThreadPlan(
         class_name, python_interpreter->m_dictionary_name.c_str(),
-        error_str, thread_plan_sp);
+        args_data, error_str, thread_plan_sp);
     if (!ret_val)
       return {};
   }

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h Thu Oct  3 15:50:18 2019
@@ -78,6 +78,7 @@ public:
 
   StructuredData::ObjectSP
   CreateScriptedThreadPlan(const char *class_name,
+                           StructuredDataImpl *args_data,
                            std::string &error_str,
                            lldb::ThreadPlanSP thread_plan) override;
 

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Oct  3 15:50:18 2019
@@ -13,6 +13,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/FormatEntity.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Interpreter/OptionValueFileSpecList.h"
@@ -1482,9 +1483,18 @@ ThreadPlanSP Thread::QueueThreadPlanForS
 }
 
 lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
-    bool abort_other_plans, const char *class_name, bool stop_other_threads,
+    bool abort_other_plans, const char *class_name, 
+    StructuredData::ObjectSP extra_args_sp,  bool stop_other_threads,
     Status &status) {
-  ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
+    
+  StructuredDataImpl *extra_args_impl = nullptr; 
+  if (extra_args_sp) {
+    extra_args_impl = new StructuredDataImpl();
+    extra_args_impl->SetObjectSP(extra_args_sp);
+  }
+
+  ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name, 
+                                                   extra_args_impl));
 
   status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
   return thread_plan_sp;

Modified: lldb/trunk/source/Target/ThreadPlanPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanPython.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanPython.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanPython.cpp Thu Oct  3 15:50:18 2019
@@ -25,10 +25,11 @@ using namespace lldb_private;
 
 // ThreadPlanPython
 
-ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
+ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, 
+                                   StructuredDataImpl *args_data)
     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
                  eVoteNoOpinion, eVoteNoOpinion),
-      m_class_name(class_name), m_did_push(false) {
+      m_class_name(class_name), m_args_data(args_data), m_did_push(false) {
   SetIsMasterPlan(true);
   SetOkayToDiscard(true);
   SetPrivate(false);
@@ -65,7 +66,8 @@ void ThreadPlanPython::DidPush() {
                                            .GetScriptInterpreter();
     if (script_interp) {
       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
-          m_class_name.c_str(), m_error_str, this->shared_from_this());
+          m_class_name.c_str(), m_args_data, m_error_str, 
+          this->shared_from_this());
     }
   }
 }

Modified: lldb/trunk/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp?rev=373675&r1=373674&r2=373675&view=diff
==============================================================================
--- lldb/trunk/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp (original)
+++ lldb/trunk/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp Thu Oct  3 15:50:18 2019
@@ -95,6 +95,7 @@ LLDBSwigPythonCreateCommandObject(const
 
 extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan(
     const char *python_class_name, const char *session_dictionary_name,
+    StructuredDataImpl *args_data,
     std::string &error_string,
     const lldb::ThreadPlanSP &thread_plan_sp) {
   return nullptr;




More information about the lldb-commits mailing list