tammela updated this revision to Diff 305427.
tammela added a comment.

Clean up includes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91508/new/

https://reviews.llvm.org/D91508

Files:
  lldb/bindings/lua/lua-swigsafecast.swig
  lldb/bindings/lua/lua-wrapper.swig
  lldb/bindings/lua/lua.swig
  lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
  lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_oneline_callback.test
  lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp
  lldb/unittests/ScriptInterpreter/Lua/ScriptInterpreterTests.cpp

Index: lldb/unittests/ScriptInterpreter/Lua/ScriptInterpreterTests.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Lua/ScriptInterpreterTests.cpp
+++ lldb/unittests/ScriptInterpreter/Lua/ScriptInterpreterTests.cpp
@@ -43,6 +43,13 @@
 };
 } // namespace
 
+struct lua_State;
+extern "C" bool LLDBSwigLuaBreakpointCallbackFunction(
+    lua_State *L, void *baton, const lldb::StackFrameSP &sb_frame,
+    const lldb::BreakpointLocationSP &sb_bp_loc) {
+  return false;
+}
+
 TEST_F(ScriptInterpreterTest, Plugin) {
   EXPECT_EQ(ScriptInterpreterLua::GetPluginNameStatic(), "script-lua");
   EXPECT_EQ(ScriptInterpreterLua::GetPluginDescriptionStatic(),
Index: lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp
+++ lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp
@@ -26,3 +26,27 @@
   EXPECT_EQ(llvm::toString(std::move(error)),
             "[string \"buffer\"]:1: unexpected symbol near 'nil'\n");
 }
+
+TEST(LuaTest, RunCallbackValid) {
+  Lua lua;
+  LuaCallback callback = [](lua_State *L) -> int {
+    if (luaL_dostring(L, "foo = 1") != LUA_OK)
+      return lua_error(L);
+    return 0;
+  };
+  llvm::Error error = lua.Run(callback);
+  EXPECT_FALSE(static_cast<bool>(error));
+}
+
+TEST(LuaTest, RunCallbackInvalid) {
+  Lua lua;
+  LuaCallback callback = [](lua_State *L) -> int {
+    if (luaL_dostring(L, "nil = foo") != LUA_OK)
+      return lua_error(L);
+    return 0;
+  };
+  llvm::Error error = lua.Run(callback);
+  EXPECT_TRUE(static_cast<bool>(error));
+  EXPECT_EQ(llvm::toString(std::move(error)),
+            "[string \"nil = foo\"]:1: unexpected symbol near 'nil'\n");
+}
Index: lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_oneline_callback.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_oneline_callback.test
@@ -0,0 +1,5 @@
+# RUN: %lldb -s %s --script-language lua 2>&1 | FileCheck %s
+b main
+breakpoint command add -s lua -o 'print(1)'
+run
+# CHECK: 1
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -10,11 +10,20 @@
 #define liblldb_ScriptInterpreterLua_h_
 
 #include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-enumerations.h"
 
 namespace lldb_private {
 class Lua;
 class ScriptInterpreterLua : public ScriptInterpreter {
 public:
+  class CommandDataLua : public BreakpointOptions::CommandData {
+  public:
+    CommandDataLua() : BreakpointOptions::CommandData() {
+      interpreter = lldb::eScriptLanguageLua;
+    }
+  };
+
   ScriptInterpreterLua(Debugger &debugger);
 
   ~ScriptInterpreterLua() override;
@@ -41,6 +50,11 @@
 
   static const char *GetPluginDescriptionStatic();
 
+  static bool BreakpointCallbackFunction(void *baton,
+                                         StoppointCallbackContext *context,
+                                         lldb::user_id_t break_id,
+                                         lldb::user_id_t break_loc_id);
+
   // PluginInterface protocol
   lldb_private::ConstString GetPluginName() override;
 
@@ -51,6 +65,9 @@
   llvm::Error EnterSession(lldb::user_id_t debugger_id);
   llvm::Error LeaveSession();
 
+  Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+                                      const char *command_body_text) override;
+
 private:
   std::unique_ptr<Lua> m_lua;
   bool m_session_is_active = false;
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -8,18 +8,26 @@
 
 #include "ScriptInterpreterLua.h"
 #include "Lua.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/ExecutionContext.h"
 #include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/StringList.h"
 #include "lldb/Utility/Timer.h"
 #include "llvm/Support/FormatAdapters.h"
+#include <memory>
 
 using namespace lldb;
 using namespace lldb_private;
 
+extern "C" bool LLDBSwigLuaBreakpointCallbackFunction(
+    lua_State *L, void *baton, const lldb::StackFrameSP &sb_frame,
+    const lldb::BreakpointLocationSP &sb_bp_loc);
+
 LLDB_PLUGIN_DEFINE(ScriptInterpreterLua)
 
 class IOHandlerLuaInterpreter : public IOHandlerDelegate,
@@ -174,6 +182,68 @@
   return m_lua->Run(str);
 }
 
+bool ScriptInterpreterLua::BreakpointCallbackFunction(
+    void *baton, StoppointCallbackContext *context, user_id_t break_id,
+    user_id_t break_loc_id) {
+  assert(context);
+
+  ExecutionContext exe_ctx(context->exe_ctx_ref);
+
+  Target *target = exe_ctx.GetTargetPtr();
+  if (target == nullptr)
+    return true;
+
+  StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
+  BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
+  BreakpointLocationSP bp_loc_sp(breakpoint_sp->FindLocationByID(break_loc_id));
+  Debugger &debugger = target->GetDebugger();
+  ScriptInterpreterLua *lua_interpreter =
+      static_cast<ScriptInterpreterLua *>(debugger.GetScriptInterpreter());
+
+  Lua &lua = lua_interpreter->GetLua();
+  bool stop = true;
+  LuaCallback callback = [&](lua_State *L) -> int {
+    stop = LLDBSwigLuaBreakpointCallbackFunction(L, baton, stop_frame_sp,
+                                                 bp_loc_sp);
+    return 0;
+  };
+
+  llvm::handleAllErrors(lua.Run(callback), [&](const llvm::StringError &E) {
+    debugger.GetErrorStream() << E.message();
+    stop = true;
+  });
+
+  return stop;
+}
+
+Status ScriptInterpreterLua::SetBreakpointCommandCallback(
+    BreakpointOptions *bp_options, const char *command_body_text) {
+  Status error;
+  auto data_up = std::make_unique<CommandDataLua>();
+  LuaCallback callback = [&](lua_State *L) -> int {
+    StreamString sstr;
+    m_debugger.GetErrorStream() << data_up.get() << '\n';
+    lua_pushlightuserdata(L, data_up.get());
+    sstr.Printf("return function(frame, bp_loc, ...) %s end",
+                command_body_text);
+    if (luaL_dostring(L, sstr.GetData()) != LUA_OK)
+      return lua_error(L);
+    lua_settable(L, LUA_REGISTRYINDEX);
+    return 0;
+  };
+
+  error = m_lua->Run(callback);
+  if (error.Fail())
+    return error;
+
+  auto baton_sp =
+      std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
+  bp_options->SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
+                          baton_sp);
+
+  return error;
+}
+
 lldb::ScriptInterpreterSP
 ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
   return std::make_shared<ScriptInterpreterLua>(debugger);
Index: lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -15,6 +15,7 @@
 
 #include "lua.hpp"
 
+#include <functional>
 #include <mutex>
 
 namespace lldb_private {
@@ -23,12 +24,15 @@
 int luaopen_lldb(lua_State *L);
 }
 
+using LuaCallback = std::function<int(lua_State *L)>;
+
 class Lua {
 public:
   Lua();
   ~Lua();
 
   llvm::Error Run(llvm::StringRef buffer);
+  llvm::Error Run(LuaCallback &callback);
   llvm::Error LoadModule(llvm::StringRef filename);
   llvm::Error ChangeIO(FILE *out, FILE *err);
 
Index: lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -57,6 +57,26 @@
   return e;
 }
 
+static int runCallback(lua_State *L) {
+  LuaCallback *callback = static_cast<LuaCallback *>(lua_touserdata(L, -1));
+  return (*callback)(L);
+}
+
+llvm::Error Lua::Run(LuaCallback &callback) {
+  lua_pushcfunction(m_lua_state, runCallback);
+  lua_pushlightuserdata(m_lua_state, &callback);
+  int error = lua_pcall(m_lua_state, 1, 0, 0);
+  if (error == LUA_OK)
+    return llvm::Error::success();
+
+  llvm::Error e = llvm::make_error<llvm::StringError>(
+      llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
+      llvm::inconvertibleErrorCode());
+  // Pop error message from the stack.
+  lua_pop(m_lua_state, 1);
+  return e;
+}
+
 llvm::Error Lua::LoadModule(llvm::StringRef filename) {
   FileSpec file(filename);
   if (!FileSystem::Instance().Exists(file)) {
Index: lldb/bindings/lua/lua.swig
===================================================================
--- lldb/bindings/lua/lua.swig
+++ lldb/bindings/lua/lua.swig
@@ -14,8 +14,10 @@
 %include "headers.swig"
 
 %{
+#include "../bindings/lua/lua-swigsafecast.swig"
 using namespace lldb_private;
 using namespace lldb;
 %}
 
 %include "interfaces.swig"
+%include "lua-wrapper.swig"
Index: lldb/bindings/lua/lua-wrapper.swig
===================================================================
--- /dev/null
+++ lldb/bindings/lua/lua-wrapper.swig
@@ -0,0 +1,35 @@
+%header %{
+
+template <typename T>
+void
+SBTypeToSWIGWrapper (lua_State* L, T* obj);
+
+%}
+
+%wrapper %{
+
+SWIGEXPORT bool
+LLDBSwigLuaBreakpointCallbackFunction
+(
+   lua_State *L,
+   void* baton,
+   const lldb::StackFrameSP& frame_sp,
+   const lldb::BreakpointLocationSP& bp_loc_sp
+)
+{
+   lldb::SBFrame sb_frame (frame_sp);
+   lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
+
+   lua_pushlightuserdata(L, baton);
+   lua_gettable(L, LUA_REGISTRYINDEX);
+
+   SBTypeToSWIGWrapper(L, &sb_frame);
+   SBTypeToSWIGWrapper(L, &sb_bp_loc);
+
+   lua_call(L, 2, 1);
+
+   return lua_toboolean(L, -1);
+}
+
+
+%}
Index: lldb/bindings/lua/lua-swigsafecast.swig
===================================================================
--- /dev/null
+++ lldb/bindings/lua/lua-swigsafecast.swig
@@ -0,0 +1,17 @@
+template <typename SBClass>
+void
+SBTypeToSWIGWrapper (lua_State *L, SBClass* sb_object);
+
+template<>
+void
+SBTypeToSWIGWrapper (lua_State* L, lldb::SBFrame* frame_sb)
+{
+   SWIG_NewPointerObj(L, (void *) frame_sb, SWIGTYPE_p_lldb__SBFrame, 0);
+}
+
+template<>
+void
+SBTypeToSWIGWrapper (lua_State* L, lldb::SBBreakpointLocation* breakpoint_location_sb)
+{
+   SWIG_NewPointerObj(L, (void *) breakpoint_location_sb, SWIGTYPE_p_lldb__SBBreakpointLocation, 0);
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to