jingham created this revision.
Herald added subscribers: lldb-commits, JDevlieghere, abidh.
Herald added a project: LLDB.

Before this patch if you used SBThread.StepUsingScriptedThreadPlan but mistyped 
the Python ThreadPlan class name, you wouldn't get any error, and a bogus 
ThreadPlan would get executed.  This patch adds an error string and plumbs it 
through to where we look up the Python class, so now you get a decent error 
string.  We also tell ourselves the plan has failed (by returning an empty 
StructuredObject) so that the plan will fail the IsValid check and so not get 
pushed.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D68173

Files:
  lldb/include/lldb/Interpreter/ScriptInterpreter.h
  lldb/include/lldb/Target/ThreadPlanPython.h
  
lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
  lldb/scripts/Python/python-wrapper.swig
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
  lldb/source/Target/ThreadPlanPython.cpp
  lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Index: lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -95,6 +95,7 @@
 
 extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan(
     const char *python_class_name, const char *session_dictionary_name,
+    std::string &error_string,
     const lldb::ThreadPlanSP &thread_plan_sp) {
   return nullptr;
 }
Index: lldb/source/Target/ThreadPlanPython.cpp
===================================================================
--- lldb/source/Target/ThreadPlanPython.cpp
+++ lldb/source/Target/ThreadPlanPython.cpp
@@ -45,7 +45,9 @@
 
   if (!m_implementation_sp) {
     if (error)
-      error->Printf("Python thread plan does not have an implementation");
+      error->Printf("Error constructing Python ThreadPlan: %s",
+          m_error_str.empty() ? "<unknown error>"
+                                : m_error_str.c_str());
     return false;
   }
 
@@ -63,7 +65,7 @@
                                            .GetScriptInterpreter();
     if (script_interp) {
       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
-          m_class_name.c_str(), this->shared_from_this());
+          m_class_name.c_str(), m_error_str, this->shared_from_this());
     }
   }
 }
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -78,6 +78,7 @@
 
   StructuredData::ObjectSP
   CreateScriptedThreadPlan(const char *class_name,
+                           std::string &error_str,
                            lldb::ThreadPlanSP thread_plan) override;
 
   bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -97,6 +97,7 @@
 
 extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan(
     const char *python_class_name, const char *session_dictionary_name,
+    std::string &error_string,
     const lldb::ThreadPlanSP &thread_plan_sp);
 
 extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor,
@@ -1844,7 +1845,8 @@
 }
 
 StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
-    const char *class_name, lldb::ThreadPlanSP thread_plan_sp) {
+    const char *class_name, std::string &error_str, 
+    lldb::ThreadPlanSP thread_plan_sp) {
   if (class_name == nullptr || class_name[0] == '\0')
     return StructuredData::ObjectSP();
 
@@ -1864,10 +1866,11 @@
   {
     Locker py_lock(this,
                    Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
     ret_val = LLDBSwigPythonCreateScriptedThreadPlan(
         class_name, python_interpreter->m_dictionary_name.c_str(),
-        thread_plan_sp);
+        error_str, thread_plan_sp);
+    if (!ret_val)
+      return {};
   }
 
   return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
Index: lldb/scripts/Python/python-wrapper.swig
===================================================================
--- lldb/scripts/Python/python-wrapper.swig
+++ lldb/scripts/Python/python-wrapper.swig
@@ -250,6 +250,7 @@
 (
     const char *python_class_name,
     const char *session_dictionary_name,
+    std::string &error_string,
     const lldb::ThreadPlanSP& thread_plan_sp
 )
 {
@@ -267,8 +268,11 @@
     auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
     auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
 
-    if (!pfunc.IsAllocated())
+    if (!pfunc.IsAllocated()) {
+        error_string.append("could not find script class: ");
+        error_string.append(python_class_name);
         return nullptr;
+    }
 
     PythonObject tp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(tp_value));
 
Index: lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
@@ -26,6 +26,7 @@
 
     def setUp(self):
         TestBase.setUp(self)
+        self.main_source_file = lldb.SBFileSpec("main.c")
         self.runCmd("command script import Steps.py")
 
     def step_out_with_scripted_plan(self, name):
@@ -39,3 +40,19 @@
 
         frame = thread.GetFrameAtIndex(0)
         self.assertEqual("main", frame.GetFunctionName())
+
+    def test_misspelled_plan_name(self):
+        """Test that we get a useful error if we misspell the plan class name"""
+        self.build()
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file)
+        stop_id = process.GetStopID()
+        # Pass a non-existent class for the plan class:
+        err = thread.StepUsingScriptedThreadPlan("NoSuchModule.NoSuchPlan")
+        
+        # Make sure we got a good error:
+        self.assertTrue(err.Fail(), "We got a failure state")
+        msg = err.GetCString()
+        self.assertTrue("NoSuchModule.NoSuchPlan" in msg, "Mentioned missing class")
+        
+        # Make sure we didn't let the process run:
+        self.assertEqual(stop_id, process.GetStopID(), "Process didn't run")
Index: lldb/include/lldb/Target/ThreadPlanPython.h
===================================================================
--- lldb/include/lldb/Target/ThreadPlanPython.h
+++ lldb/include/lldb/Target/ThreadPlanPython.h
@@ -55,6 +55,7 @@
 
 private:
   std::string m_class_name;
+  std::string m_error_str;
   StructuredData::ObjectSP m_implementation_sp;
   bool m_did_push;
 
Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -208,6 +208,7 @@
 
   virtual StructuredData::ObjectSP
   CreateScriptedThreadPlan(const char *class_name,
+                           std::string &error_str,
                            lldb::ThreadPlanSP thread_plan_sp) {
     return StructuredData::ObjectSP();
   }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] D68173:... Jim Ingham via Phabricator via lldb-commits

Reply via email to