[Lldb-commits] [lldb] a69bbe0 - [LLDB][breakpoints] ArgInfo::count -> ArgInfo::max_positional_args

Lawrence D'Anna via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 29 15:03:16 PDT 2019


Author: Lawrence D'Anna
Date: 2019-10-29T15:03:02-07:00
New Revision: a69bbe02a2352271e8b14542073f177e24c499c1

URL: https://github.com/llvm/llvm-project/commit/a69bbe02a2352271e8b14542073f177e24c499c1
DIFF: https://github.com/llvm/llvm-project/commit/a69bbe02a2352271e8b14542073f177e24c499c1.diff

LOG: [LLDB][breakpoints] ArgInfo::count -> ArgInfo::max_positional_args

Summary:
Move breakpoints from the old, bad ArgInfo::count to the new, better
ArgInfo::max_positional_args.   Soon ArgInfo::count will be no more.

It looks like this functionality is already well tested by
`TestBreakpointCommandsFromPython.py`, so there's no need to write
additional tests for it.

Reviewers: labath, jingham, JDevlieghere

Reviewed By: labath

Subscribers: lldb-commits

Tags: #lldb

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

Added: 
    

Modified: 
    lldb/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py
    lldb/scripts/Python/python-wrapper.swig
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
    lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 69af88091a40..b32962b80355 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -315,8 +315,7 @@ class ScriptInterpreter : public PluginInterface {
 
   Status SetBreakpointCommandCallbackFunction(
       std::vector<BreakpointOptions *> &bp_options_vec,
-      const char *function_name, 
-      StructuredData::ObjectSP extra_args_sp);
+      const char *function_name, StructuredData::ObjectSP extra_args_sp);
 
   /// Set a script function as the callback for the breakpoint.
   virtual Status
@@ -472,9 +471,9 @@ class ScriptInterpreter : public PluginInterface {
   const char *GetScriptInterpreterPtyName();
 
   int GetMasterFileDescriptor();
-  
-  virtual llvm::Expected<size_t> 
-  GetNumFixedArgumentsForCallable(const llvm::StringRef &callable_name) { 
+
+  virtual llvm::Expected<unsigned>
+  GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
     return llvm::createStringError(
     llvm::inconvertibleErrorCode(), "Unimplemented function");
   }

diff  --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py
index ccb61d79c403..15a31201c565 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py
@@ -132,7 +132,7 @@ def do_set_python_command_from_python(self):
         # Now finish, and make sure the return value is correct.
         threads = lldbutil.get_threads_stopped_at_breakpoint(
             self.process, body_bkpt)
-        self.assertTrue(len(threads) == 1, "Stopped at inner breakpoint.")
+        self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.")
         self.thread = threads[0]
 
         self.assertEquals("callback was here", side_effect.callback)

diff  --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig
index 5e9a2ba1367c..71a958acb72c 100644
--- a/lldb/scripts/Python/python-wrapper.swig
+++ b/lldb/scripts/Python/python-wrapper.swig
@@ -39,7 +39,7 @@ private:
 // This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...)
 // and is used when a script command is attached to a breakpoint for execution.
 
-SWIGEXPORT bool
+SWIGEXPORT llvm::Expected<bool>
 LLDBSwigPythonBreakpointCallbackFunction
 (
     const char *python_function_name,
@@ -49,38 +49,40 @@ LLDBSwigPythonBreakpointCallbackFunction
     lldb_private::StructuredDataImpl *args_impl
 )
 {
+    using namespace llvm;
+
     lldb::SBFrame sb_frame (frame_sp);
     lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
 
-    bool stop_at_breakpoint = true;
-
     PyErr_Cleaner py_err_cleaner(true);
     auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
     auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
 
-    if (!pfunc.IsAllocated())
-        return stop_at_breakpoint;
+    unsigned max_positional_args;
+    if (auto arg_info = pfunc.GetArgInfo())
+        max_positional_args = arg_info.get().max_positional_args;
+    else
+        return arg_info.takeError();
 
     PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
     PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc));
 
-    PythonObject result;
-    // If the called function doesn't take extra_args, drop them here:
-    auto arg_info = pfunc.GetNumArguments();
-    if (arg_info.count == 3)
-      result = pfunc(frame_arg, bp_loc_arg, dict);
-    else if (arg_info.count == 4) {
-        lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
-        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
-        result = pfunc(frame_arg, bp_loc_arg, args_arg, dict);      
-    } else {
-      return stop_at_breakpoint;
-    }
+    auto result = [&] () -> Expected<PythonObject> {
+        // If the called function doesn't take extra_args, drop them here:
+        if (max_positional_args < 4) {
+            return pfunc.Call(frame_arg, bp_loc_arg, dict);
+        } else {
+            lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
+            PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
+            return pfunc.Call(frame_arg, bp_loc_arg, args_arg, dict);
+        }
+    } ();
 
-    if (result.get() == Py_False)
-        stop_at_breakpoint = false;
+    if (!result)
+        return result.takeError();
 
-    return stop_at_breakpoint;
+    // Only False counts as false!
+    return result.get().get() != Py_False;
 }
 
 // This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...)

diff  --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 15c3e241fce7..15843feae57c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -72,11 +72,16 @@ extern "C" void init_lldb(void);
 // These prototypes are the Pythonic implementations of the required callbacks.
 // Although these are scripting-language specific, their definition depends on
 // the public API.
-extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+
+extern "C" llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
     const char *python_function_name, const char *session_dictionary_name,
     const lldb::StackFrameSP &sb_frame,
-    const lldb::BreakpointLocationSP &sb_bp_loc,
-    StructuredDataImpl *args_impl);
+    const lldb::BreakpointLocationSP &sb_bp_loc, StructuredDataImpl *args_impl);
+
+#pragma clang diagnostic pop
 
 extern "C" bool LLDBSwigPythonWatchpointCallbackFunction(
     const char *python_function_name, const char *session_dictionary_name,
@@ -782,10 +787,9 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
   return m_sys_module_dict;
 }
 
-llvm::Expected<size_t>
-ScriptInterpreterPythonImpl::GetNumFixedArgumentsForCallable(
-    const llvm::StringRef &callable_name)
-{
+llvm::Expected<unsigned>
+ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(
+    const llvm::StringRef &callable_name) {
   if (callable_name.empty()) {
     return llvm::createStringError(
         llvm::inconvertibleErrorCode(),
@@ -796,16 +800,15 @@ ScriptInterpreterPythonImpl::GetNumFixedArgumentsForCallable(
                  Locker::NoSTDIN);
   auto dict = PythonModule::MainModule()
       .ResolveName<PythonDictionary>(m_dictionary_name);
-  auto pfunc 
-     = PythonObject::ResolveNameWithDictionary<PythonCallable>(callable_name, 
-                                                               dict);
+  auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
+      callable_name, dict);
   if (!pfunc.IsAllocated()) {
     return llvm::createStringError(
         llvm::inconvertibleErrorCode(),
         "can't find callable: %s", callable_name.str().c_str());
   }
   PythonCallable::ArgInfo arg_info = pfunc.GetNumArguments();
-  return arg_info.count;
+  return arg_info.max_positional_args;
 }
 
 static std::string GenerateUniqueName(const char *base_name_wanted,
@@ -1232,22 +1235,22 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
   // For now just cons up a oneliner that calls the provided function.
   std::string oneliner("return ");
   oneliner += function_name;
-  
-  llvm::Expected<size_t> maybe_args 
-      = GetNumFixedArgumentsForCallable(function_name);
+
+  llvm::Expected<unsigned> maybe_args =
+      GetMaxPositionalArgumentsForCallable(function_name);
   if (!maybe_args) {
-    error.SetErrorStringWithFormat("could not get num args: %s", 
+    error.SetErrorStringWithFormat(
+        "could not get num args: %s",
         llvm::toString(maybe_args.takeError()).c_str());
     return error;
   }
-  size_t num_args = *maybe_args;
-  
+  size_t max_args = *maybe_args;
+
   bool uses_extra_args = false;
-  if (num_args == 4) {
+  if (max_args >= 4) {
     uses_extra_args = true;
     oneliner += "(frame, bp_loc, extra_args, internal_dict)";
-  }
-  else if (num_args == 3) {
+  } else if (max_args >= 3) {
     if (extra_args_sp) {
       error.SetErrorString("cannot pass extra_args to a three argument callback"
                           );
@@ -1257,12 +1260,12 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
     oneliner += "(frame, bp_loc, internal_dict)";
   } else {
     error.SetErrorStringWithFormat("expected 3 or 4 argument "
-                                   "function, %s has %zu",
-                                   function_name, num_args);
+                                   "function, %s can only take %zu",
+                                   function_name, max_args);
     return error;
   }
-  
-  SetBreakpointCommandCallback(bp_options, oneliner.c_str(), extra_args_sp, 
+
+  SetBreakpointCommandCallback(bp_options, oneliner.c_str(), extra_args_sp,
                                uses_extra_args);
   return error;
 }
@@ -1840,8 +1843,7 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread(
 
 StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
     const char *class_name, StructuredDataImpl *args_data,
-    std::string &error_str, 
-    lldb::ThreadPlanSP thread_plan_sp) {
+    std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
   if (class_name == nullptr || class_name[0] == '\0')
     return StructuredData::ObjectSP();
 
@@ -2145,7 +2147,7 @@ Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
 
   std::string auto_generated_function_name(GenerateUniqueName(
       "lldb_autogen_python_bp_callback_func_", num_created_functions));
-  if (has_extra_args) 
+  if (has_extra_args)
     sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
                 auto_generated_function_name.c_str());
   else
@@ -2267,11 +2269,26 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
           Locker py_lock(python_interpreter, Locker::AcquireLock |
                                                  Locker::InitSession |
                                                  Locker::NoSTDIN);
-          ret_val = LLDBSwigPythonBreakpointCallbackFunction(
-              python_function_name,
-              python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
-              bp_loc_sp,
-              bp_option_data->m_extra_args_up.get());
+          Expected<bool> maybe_ret_val =
+              LLDBSwigPythonBreakpointCallbackFunction(
+                  python_function_name,
+                  python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
+                  bp_loc_sp, bp_option_data->m_extra_args_up.get());
+
+          if (!maybe_ret_val) {
+
+            llvm::handleAllErrors(
+                maybe_ret_val.takeError(),
+                [&](PythonException &E) {
+                  debugger.GetErrorStream() << E.ReadBacktrace();
+                },
+                [&](const llvm::ErrorInfoBase &E) {
+                  debugger.GetErrorStream() << E.message();
+                });
+
+          } else {
+            ret_val = maybe_ret_val.get();
+          }
         }
         return ret_val;
       }

diff  --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index e480bc3af991..79830495568e 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -256,11 +256,10 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
       BreakpointOptions *bp_options,
       std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
 
-  Status SetBreakpointCommandCallback(
-      BreakpointOptions *bp_options, 
-       const char *command_body_text,
-       StructuredData::ObjectSP extra_args_sp,
-       bool uses_extra_args);
+  Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+                                      const char *command_body_text,
+                                      StructuredData::ObjectSP extra_args_sp,
+                                      bool uses_extra_args);
 
   /// Set a one-liner as the callback for the watchpoint.
   void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
@@ -378,10 +377,9 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   python::PythonDictionary &GetSessionDictionary();
 
   python::PythonDictionary &GetSysModuleDictionary();
-  
-  llvm::Expected<size_t> 
-  GetNumFixedArgumentsForCallable(const llvm::StringRef &callable_name) 
-      override;
+
+  llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
+      const llvm::StringRef &callable_name) override;
 
   bool GetEmbeddedInterpreterModuleObjects();
 

diff  --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 66b5ff84b043..2ac631eba424 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -59,7 +59,7 @@ extern "C" void init_lldb(void) {}
 #define LLDBSwigPyInit init_lldb
 #endif
 
-extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
+extern "C" llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
     const char *python_function_name, const char *session_dictionary_name,
     const lldb::StackFrameSP &sb_frame,
     const lldb::BreakpointLocationSP &sb_bp_loc,


        


More information about the lldb-commits mailing list