tammela updated this revision to Diff 308029. tammela marked 3 inline comments as done. tammela added a comment.
Addressing review comments 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
Index: lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp =================================================================== --- lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp +++ lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp @@ -13,6 +13,30 @@ extern "C" int luaopen_lldb(lua_State *L) { return 0; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" + +// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has +// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is +// incompatible with C +#if _MSC_VER +#pragma warning (push) +#pragma warning (disable : 4190) +#endif + +extern "C" llvm::Expected<bool> +LLDBSwigLuaBreakpointCallbackFunction(lua_State *L, + lldb::StackFrameSP &stop_frame_sp, + lldb::BreakpointLocationSP &bp_loc_sp) { + return false; +} + +#if _MSC_VER +#pragma warning (pop) +#endif + +#pragma clang diagnostic pop + TEST(LuaTest, RunValid) { Lua lua; llvm::Error error = lua.Run("foo = 1"); Index: lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_oneline_callback.test =================================================================== --- /dev/null +++ lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_oneline_callback.test @@ -0,0 +1,18 @@ +# REQUIRES: lua +# RUN: echo "int main() { return 0; }" | %clang_host -x c - -o %t +# RUN: %lldb -s %s --script-language lua %t 2>&1 | FileCheck %s +b main +breakpoint command add -s lua -o 'return false' +run +# CHECK: Process {{[0-9]+}} exited with status = 0 +breakpoint command add -s lua -o 'print(frame)' +run +# CHECK: frame #0 +# CHECK: Process {{[0-9]+}} exited with status = 0 +breakpoint command add -s lua -o "return true" +run +# CHECK: Process {{[0-9]+}} stopped +breakpoint command add -s lua -o 'error("my error message")' +run +# CHECK: my error message +# CHECK: Process {{[0-9]+}} stopped 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,14 +8,17 @@ #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/StringList.h" #include "lldb/Utility/Timer.h" #include "llvm/Support/FormatAdapters.h" +#include <memory> using namespace lldb; using namespace lldb_private; @@ -174,6 +177,49 @@ 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(true, eScriptLanguageLua)); + Lua &lua = lua_interpreter->GetLua(); + + llvm::Expected<bool> BoolOrErr = + lua.CallBreakpointCallback(baton, stop_frame_sp, bp_loc_sp); + if (llvm::Error E = BoolOrErr.takeError()) { + debugger.GetErrorStream() << toString(std::move(E)); + return true; + } + + return *BoolOrErr; +} + +Status ScriptInterpreterLua::SetBreakpointCommandCallback( + BreakpointOptions *bp_options, const char *command_body_text) { + Status error; + auto data_up = std::make_unique<CommandDataLua>(); + error = m_lua->RegisterBreakpointCallback(data_up.get(), command_body_text); + 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 @@ -9,6 +9,8 @@ #ifndef liblldb_Lua_h_ #define liblldb_Lua_h_ +#include "lldb/API/SBBreakpointLocation.h" +#include "lldb/API/SBFrame.h" #include "lldb/lldb-types.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -29,6 +31,10 @@ ~Lua(); llvm::Error Run(llvm::StringRef buffer); + llvm::Error RegisterBreakpointCallback(void *baton, const char *body); + llvm::Expected<bool> + CallBreakpointCallback(void *baton, lldb::StackFrameSP &stop_frame_sp, + lldb::BreakpointLocationSP &bp_loc_sp); 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 @@ -9,11 +9,34 @@ #include "Lua.h" #include "lldb/Host/FileSystem.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" using namespace lldb_private; using namespace lldb; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" + +// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has +// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is +// incompatible with C +#if _MSC_VER +#pragma warning (push) +#pragma warning (disable : 4190) +#endif + +extern "C" llvm::Expected<bool> +LLDBSwigLuaBreakpointCallbackFunction(lua_State *L, + lldb::StackFrameSP &stop_frame_sp, + lldb::BreakpointLocationSP &bp_loc_sp); + +#if _MSC_VER +#pragma warning (pop) +#endif + +#pragma clang diagnostic pop + static int lldb_print(lua_State *L) { int n = lua_gettop(L); lua_getglobal(L, "io"); @@ -57,6 +80,31 @@ return e; } +llvm::Error Lua::RegisterBreakpointCallback(void *baton, const char *body) { + lua_pushlightuserdata(m_lua_state, baton); + const char *fmt_str = "return function(frame, bp_loc, ...) {0} end"; + std::string func_str = llvm::formatv(fmt_str, body).str(); + if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) { + 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, 2); + return e; + } + lua_settable(m_lua_state, LUA_REGISTRYINDEX); + return llvm::Error::success(); +} + +llvm::Expected<bool> +Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP &stop_frame_sp, + lldb::BreakpointLocationSP &bp_loc_sp) { + lua_pushlightuserdata(m_lua_state, baton); + lua_gettable(m_lua_state, LUA_REGISTRYINDEX); + return LLDBSwigLuaBreakpointCallbackFunction(m_lua_state, stop_frame_sp, + bp_loc_sp); +} + 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,12 @@ %include "headers.swig" %{ +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" +#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,46 @@ +%header %{ + +template <typename T> +void +PushSBClass(lua_State* L, T* obj); + +%} + +%wrapper %{ + +// This function is called from Lua::CallBreakpointCallback +SWIGEXPORT llvm::Expected<bool> +LLDBSwigLuaBreakpointCallbackFunction +( + lua_State *L, + lldb::StackFrameSP &stop_frame_sp, + lldb::BreakpointLocationSP &bp_loc_sp +) +{ + lldb::SBFrame sb_frame(stop_frame_sp); + lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); + + // Push the Lua wrappers + PushSBClass(L, &sb_frame); + PushSBClass(L, &sb_bp_loc); + + // Call into the Lua callback passing 'sb_frame' and 'sb_bp_loc'. + // Expects a boolean return. + if (lua_pcall(L, 2, 1, 0) != LUA_OK) { + llvm::Error E = llvm::make_error<llvm::StringError>( + llvm::formatv("{0}\n", lua_tostring(L, -1)), + llvm::inconvertibleErrorCode()); + // Pop error message from the stack. + lua_pop(L, 1); + return std::move(E); + } + + // Boolean return from the callback + bool stop = lua_toboolean(L, -1); + lua_pop(L, 1); + + return stop; +} + + +%} Index: lldb/bindings/lua/lua-swigsafecast.swig =================================================================== --- /dev/null +++ lldb/bindings/lua/lua-swigsafecast.swig @@ -0,0 +1,15 @@ +template <typename SBClass> +void +PushSBClass (lua_State* L, SBClass* obj); + +void +PushSBClass (lua_State* L, lldb::SBFrame* frame_sb) +{ + SWIG_NewPointerObj(L, frame_sb, SWIGTYPE_p_lldb__SBFrame, 0); +} + +void +PushSBClass (lua_State* L, lldb::SBBreakpointLocation* breakpoint_location_sb) +{ + SWIG_NewPointerObj(L, 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