diff --git a/lldb/bindings/lua/lua-swigsafecast.swig b/lldb/bindings/lua/lua-swigsafecast.swig --- a/lldb/bindings/lua/lua-swigsafecast.swig +++ b/lldb/bindings/lua/lua-swigsafecast.swig @@ -13,3 +13,9 @@ { SWIG_NewPointerObj(L, breakpoint_location_sb, SWIGTYPE_p_lldb__SBBreakpointLocation, 0); } + +void +PushSBClass (lua_State* L, lldb::SBStructuredData* structured_data_sb) +{ + SWIG_NewPointerObj(L, structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0); +} diff --git a/lldb/bindings/lua/lua-wrapper.swig b/lldb/bindings/lua/lua-wrapper.swig --- a/lldb/bindings/lua/lua-wrapper.swig +++ b/lldb/bindings/lua/lua-wrapper.swig @@ -14,19 +14,32 @@ ( lua_State *L, lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp + lldb::BreakpointLocationSP bp_loc_sp, + StructuredDataImpl *extra_args_impl ) { lldb::SBFrame sb_frame(stop_frame_sp); lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); + int nargs = 2; + + auto extra_args = [&]() -> llvm::Optional { + if (extra_args_impl == nullptr) + return {}; + return lldb::SBStructuredData(extra_args_impl); + } (); // Push the Lua wrappers PushSBClass(L, &sb_frame); PushSBClass(L, &sb_bp_loc); + if (extra_args.hasValue()) { + PushSBClass(L, extra_args.getPointer()); + nargs++; + } + // 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) { + if (lua_pcall(L, nargs, 1, 0) != LUA_OK) { llvm::Error E = llvm::make_error( llvm::formatv("{0}\n", lua_tostring(L, -1)), llvm::inconvertibleErrorCode()); diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h --- a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h @@ -11,6 +11,7 @@ #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBFrame.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/lldb-types.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -34,7 +35,8 @@ llvm::Error RegisterBreakpointCallback(void *baton, const char *body); llvm::Expected CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp); + lldb::BreakpointLocationSP bp_loc_sp, + StructuredData::ObjectSP extra_args_sp); llvm::Error LoadModule(llvm::StringRef filename); llvm::Error LoadBuffer(llvm::StringRef buffer, bool pop_result = true); llvm::Error ChangeIO(FILE *out, FILE *err); diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp @@ -26,10 +26,9 @@ #pragma warning (disable : 4190) #endif -extern "C" llvm::Expected -LLDBSwigLuaBreakpointCallbackFunction(lua_State *L, - lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp); +extern "C" llvm::Expected LLDBSwigLuaBreakpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, + lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl); #if _MSC_VER #pragma warning (pop) @@ -99,11 +98,20 @@ llvm::Expected Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp) { + lldb::BreakpointLocationSP bp_loc_sp, + StructuredData::ObjectSP extra_args_sp) { + lua_pushlightuserdata(m_lua_state, baton); lua_gettable(m_lua_state, LUA_REGISTRYINDEX); + auto *extra_args_impl = [&]() -> StructuredDataImpl * { + if (extra_args_sp == nullptr) + return nullptr; + auto *extra_args_impl = new StructuredDataImpl(); + extra_args_impl->SetObjectSP(extra_args_sp); + return extra_args_impl; + }(); return LLDBSwigLuaBreakpointCallbackFunction(m_lua_state, stop_frame_sp, - bp_loc_sp); + bp_loc_sp, extra_args_impl); } llvm::Error Lua::LoadBuffer(llvm::StringRef buffer, bool pop_result) { diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h --- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h @@ -9,6 +9,7 @@ #ifndef liblldb_ScriptInterpreterLua_h_ #define liblldb_ScriptInterpreterLua_h_ +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" @@ -22,6 +23,11 @@ CommandDataLua() : BreakpointOptions::CommandData() { interpreter = lldb::eScriptLanguageLua; } + CommandDataLua(StructuredData::ObjectSP extra_args_sp) + : BreakpointOptions::CommandData(), m_extra_args_sp(extra_args_sp) { + interpreter = lldb::eScriptLanguageLua; + } + StructuredData::ObjectSP m_extra_args_sp; }; ScriptInterpreterLua(Debugger &debugger); @@ -72,9 +78,17 @@ Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, const char *command_body_text) override; + Status SetBreakpointCommandCallbackFunction( + BreakpointOptions *bp_options, const char *function_name, + StructuredData::ObjectSP extra_args_sp) override; + private: std::unique_ptr m_lua; bool m_session_is_active = false; + + Status RegisterBreakpointCallback(BreakpointOptions *bp_options, + const char *command_body_text, + StructuredData::ObjectSP extra_args_sp); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -265,8 +265,9 @@ debugger.GetScriptInterpreter(true, eScriptLanguageLua)); Lua &lua = lua_interpreter->GetLua(); - llvm::Expected BoolOrErr = - lua.CallBreakpointCallback(baton, stop_frame_sp, bp_loc_sp); + CommandDataLua *bp_option_data = static_cast(baton); + llvm::Expected BoolOrErr = lua.CallBreakpointCallback( + baton, stop_frame_sp, bp_loc_sp, bp_option_data->m_extra_args_sp); if (llvm::Error E = BoolOrErr.takeError()) { debugger.GetErrorStream() << toString(std::move(E)); return true; @@ -284,10 +285,25 @@ m_debugger.RunIOHandlerAsync(io_handler_sp); } +Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction( + BreakpointOptions *bp_options, const char *function_name, + StructuredData::ObjectSP extra_args_sp) { + const char *fmt_str = "return {0}(frame, bp_loc, ...)"; + std::string oneliner = llvm::formatv(fmt_str, function_name).str(); + return RegisterBreakpointCallback(bp_options, oneliner.c_str(), + extra_args_sp); +} + Status ScriptInterpreterLua::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { + return RegisterBreakpointCallback(bp_options, command_body_text, {}); +} + +Status ScriptInterpreterLua::RegisterBreakpointCallback( + BreakpointOptions *bp_options, const char *command_body_text, + StructuredData::ObjectSP extra_args_sp) { Status error; - auto data_up = std::make_unique(); + auto data_up = std::make_unique(extra_args_sp); error = m_lua->RegisterBreakpointCallback(data_up.get(), command_body_text); if (error.Fail()) return error; diff --git a/lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_function_callback.test b/lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_function_callback.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ScriptInterpreter/Lua/breakpoint_function_callback.test @@ -0,0 +1,21 @@ +# 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 +script +function abc(a, b, c, ...) +print(c) +end +quit +breakpoint command add -s lua -F abc +r +# CHECK: nil +breakpoint command add -s lua -F abc -k foo -v 123 +r +# CHECK: +breakpoint command add -s lua -o "abc(frame, bp_loc, ...)" +r +# CHECK: nil +breakpoint command add -s lua -F typo +r +# CHECK: attempt to call a nil value diff --git a/lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp b/lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp --- a/lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp +++ b/lldb/unittests/ScriptInterpreter/Lua/LuaTests.cpp @@ -24,10 +24,9 @@ #pragma warning (disable : 4190) #endif -extern "C" llvm::Expected -LLDBSwigLuaBreakpointCallbackFunction(lua_State *L, - lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp) { +extern "C" llvm::Expected LLDBSwigLuaBreakpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, + lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl) { return false; }