siger-young created this revision.
siger-young added reviewers: JDevlieghere, tammela.
siger-young requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
This commit supports registerubg breakpoint callback when using
liblldb in Lua. (able to `SetScriptCallback(function(a, b, ...) end)`)
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D115926
Files:
lldb/bindings/interface/SBBreakpoint.i
lldb/bindings/lua/lua-typemaps.swig
lldb/bindings/lua/lua-wrapper.swig
lldb/include/lldb/API/SBBreakpoint.h
lldb/include/lldb/API/SBBreakpointOptionCommon.h
lldb/include/lldb/API/SBDefines.h
lldb/source/API/SBBreakpoint.cpp
lldb/source/API/SBBreakpointName.cpp
lldb/source/API/SBBreakpointOptionCommon.cpp
lldb/source/API/SBBreakpointOptionCommon.h
lldb/test/API/lua_api/TestBreakpointAPI.lua
Index: lldb/test/API/lua_api/TestBreakpointAPI.lua
===================================================================
--- lldb/test/API/lua_api/TestBreakpointAPI.lua
+++ lldb/test/API/lua_api/TestBreakpointAPI.lua
@@ -49,4 +49,20 @@
assertEquals(var_argc_value, 3)
end
+function _T:TestBreakpointRealCallback()
+ local target = self:create_target()
+ local breakpoint = target:BreakpointCreateByLocation('main.c', 31)
+ assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
+ local flag = false
+ local i = 1
+ breakpoint:SetScriptCallback(function(frame)
+ flag = true
+ assertEquals(frame:FindVariable('i'):GetValueAsSigned(), i)
+ i = i + 1
+ return false
+ end)
+ target:LaunchSimple(nil, nil, nil)
+ assertTrue(flag)
+end
+
os.exit(_T:run())
Index: lldb/source/API/SBBreakpointOptionCommon.h
===================================================================
--- lldb/source/API/SBBreakpointOptionCommon.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===-- SBBreakpointOptionCommon.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_API_SBBREAKPOINTOPTIONCOMMON_H
-#define LLDB_SOURCE_API_SBBREAKPOINTOPTIONCOMMON_H
-
-#include "lldb/API/SBDefines.h"
-#include "lldb/Utility/Baton.h"
-
-namespace lldb
-{
-struct CallbackData {
- SBBreakpointHitCallback callback;
- void *callback_baton;
-};
-
-class SBBreakpointCallbackBaton : public lldb_private::TypedBaton<CallbackData> {
-public:
- SBBreakpointCallbackBaton(SBBreakpointHitCallback callback,
- void *baton);
-
- ~SBBreakpointCallbackBaton() override;
-
- static bool PrivateBreakpointHitCallback(void *baton,
- lldb_private::StoppointCallbackContext *ctx,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-};
-
-} // namespace lldb
-#endif // LLDB_SOURCE_API_SBBREAKPOINTOPTIONCOMMON_H
Index: lldb/source/API/SBBreakpointOptionCommon.cpp
===================================================================
--- lldb/source/API/SBBreakpointOptionCommon.cpp
+++ lldb/source/API/SBBreakpointOptionCommon.cpp
@@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/API/SBBreakpointName.h"
+#include "lldb/API/SBBreakpointOptionCommon.h"
#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBBreakpointName.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBProcess.h"
@@ -31,13 +32,15 @@
#include "lldb/lldb-enumerations.h"
-#include "SBBreakpointOptionCommon.h"
-
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
+SBBreakpointCallbackBaton::SBBreakpointCallbackBaton(
+ std::unique_ptr<CallbackData> Data)
+ : TypedBaton(std::move(Data)) {}
+
SBBreakpointCallbackBaton::SBBreakpointCallbackBaton(SBBreakpointHitCallback
callback,
void *baton)
@@ -52,26 +55,18 @@
lldb::user_id_t break_loc_id)
{
ExecutionContext exe_ctx(ctx->exe_ctx_ref);
+ SBFrame sb_frame(exe_ctx.GetFrameSP());
BreakpointSP bp_sp(
exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
if (baton && bp_sp) {
CallbackData *data = (CallbackData *)baton;
lldb_private::Breakpoint *bp = bp_sp.get();
- if (bp && data->callback) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process) {
- SBProcess sb_process(process->shared_from_this());
- SBThread sb_thread;
- SBBreakpointLocation sb_location;
- assert(bp_sp);
- sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id));
- Thread *thread = exe_ctx.GetThreadPtr();
- if (thread)
- sb_thread.SetThread(thread->shared_from_this());
- return data->callback(data->callback_baton, sb_process, sb_thread,
- sb_location);
- }
+ if (bp && data->callback) {
+ SBBreakpointLocation sb_bp_loc;
+ assert(bp_sp);
+ sb_bp_loc.SetLocation(bp_sp->FindLocationByID(break_loc_id));
+ return data->callback(data->callback_baton, sb_frame, sb_bp_loc);
}
}
return true; // Return true if we should stop at this breakpoint
Index: lldb/source/API/SBBreakpointName.cpp
===================================================================
--- lldb/source/API/SBBreakpointName.cpp
+++ lldb/source/API/SBBreakpointName.cpp
@@ -8,6 +8,7 @@
#include "lldb/API/SBBreakpointName.h"
#include "SBReproducerPrivate.h"
+#include "lldb/API/SBBreakpointOptionCommon.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"
@@ -25,8 +26,6 @@
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Stream.h"
-#include "SBBreakpointOptionCommon.h"
-
using namespace lldb;
using namespace lldb_private;
Index: lldb/source/API/SBBreakpoint.cpp
===================================================================
--- lldb/source/API/SBBreakpoint.cpp
+++ lldb/source/API/SBBreakpoint.cpp
@@ -9,6 +9,7 @@
#include "lldb/API/SBBreakpoint.h"
#include "SBReproducerPrivate.h"
#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBBreakpointOptionCommon.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBProcess.h"
@@ -36,8 +37,6 @@
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Stream.h"
-#include "SBBreakpointOptionCommon.h"
-
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/STLExtras.h"
@@ -616,6 +615,21 @@
}
}
+void SBBreakpoint::SetScriptCallback(const SBBreakpointCallbackBatonSP &baton_sp) {
+ LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallback,
+ (const SBBreakpointCallbackBatonSP &), baton_sp);
+
+ BreakpointSP bkpt_sp = GetSP();
+
+ if (bkpt_sp) {
+ std::lock_guard<std::recursive_mutex> guard(
+ bkpt_sp->GetTarget().GetAPIMutex());
+ bkpt_sp->SetCallback(
+ SBBreakpointCallbackBaton ::PrivateBreakpointHitCallback, baton_sp,
+ false);
+ }
+}
+
void SBBreakpoint::SetScriptCallbackFunction(
const char *callback_function_name) {
LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
@@ -1045,6 +1059,8 @@
(lldb::SBAddress &));
LLDB_REGISTER_METHOD(lldb::SBStructuredData, SBBreakpoint,
SerializeToStructuredData, ());
+ LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallback,
+ (const SBBreakpointCallbackBatonSP &));
LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
(const char *));
LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackFunction,
Index: lldb/include/lldb/API/SBDefines.h
===================================================================
--- lldb/include/lldb/API/SBDefines.h
+++ lldb/include/lldb/API/SBDefines.h
@@ -94,9 +94,8 @@
class LLDB_API SBWatchpoint;
class LLDB_API SBUnixSignals;
-typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
- SBThread &thread,
- lldb::SBBreakpointLocation &location);
+typedef bool (*SBBreakpointHitCallback)(void *baton, SBFrame &sb_frame,
+ SBBreakpointLocation &sb_bp_loc);
}
#endif // LLDB_API_SBDEFINES_H
Index: lldb/include/lldb/API/SBBreakpointOptionCommon.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/API/SBBreakpointOptionCommon.h
@@ -0,0 +1,40 @@
+//===-- SBBreakpointOptionCommon.h ------------------------------------------*-
+//C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBBREAKPOINTOPTIONCOMMON_H
+#define LLDB_API_SBBREAKPOINTOPTIONCOMMON_H
+
+#include "lldb/API/SBDefines.h"
+#include "lldb/Utility/Baton.h"
+
+namespace lldb {
+struct CallbackData {
+ SBBreakpointHitCallback callback;
+ void *callback_baton;
+
+ virtual ~CallbackData() = default;
+};
+
+class SBBreakpointCallbackBaton
+ : public lldb_private::TypedBaton<CallbackData> {
+public:
+ explicit SBBreakpointCallbackBaton(std::unique_ptr<CallbackData> Data);
+ SBBreakpointCallbackBaton(SBBreakpointHitCallback callback, void *baton);
+
+ ~SBBreakpointCallbackBaton() override;
+
+ static bool PrivateBreakpointHitCallback(
+ void *baton, lldb_private::StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+};
+
+typedef std::shared_ptr<SBBreakpointCallbackBaton> SBBreakpointCallbackBatonSP;
+
+} // namespace lldb
+#endif // LLDB_API_SBBREAKPOINTOPTIONCOMMON_H
Index: lldb/include/lldb/API/SBBreakpoint.h
===================================================================
--- lldb/include/lldb/API/SBBreakpoint.h
+++ lldb/include/lldb/API/SBBreakpoint.h
@@ -9,6 +9,7 @@
#ifndef LLDB_API_SBBREAKPOINT_H
#define LLDB_API_SBBREAKPOINT_H
+#include "lldb/API/SBBreakpointOptionCommon.h"
#include "lldb/API/SBDefines.h"
class SBBreakpointListImpl;
@@ -94,6 +95,8 @@
void SetCallback(SBBreakpointHitCallback callback, void *baton);
+ void SetScriptCallback(const SBBreakpointCallbackBatonSP &baton_sp);
+
void SetScriptCallbackFunction(const char *callback_function_name);
SBError SetScriptCallbackFunction(const char *callback_function_name,
Index: lldb/bindings/lua/lua-wrapper.swig
===================================================================
--- lldb/bindings/lua/lua-wrapper.swig
+++ lldb/bindings/lua/lua-wrapper.swig
@@ -98,4 +98,52 @@
return luaL_error(L, "You cannot close a file handle used by lldb.");
}
+// These are external callback wrappers.
+
+bool SBBreakpointHitCallbackLua(
+ void *baton,
+ SBFrame &sb_frame,
+ SBBreakpointLocation &sb_bp_loc
+);
+
+struct CallbackDataLua : public CallbackData {
+public:
+ CallbackDataLua(lua_State *l) : L(l) {
+ callback = SBBreakpointHitCallbackLua;
+ callback_baton = (void *) this;
+ }
+ lua_State *L;
+};
+
+
+bool SBBreakpointHitCallbackLua(
+ void *baton,
+ SBFrame &sb_frame,
+ SBBreakpointLocation &sb_bp_loc
+)
+{
+ auto data = (CallbackDataLua *) baton;
+
+ lua_State *L = data->L;
+ lua_pushlightuserdata(L, data);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ int nargs = 2;
+
+ // Push the Lua wrappers
+ PushSBClass(L, &sb_frame);
+ PushSBClass(L, &sb_bp_loc);
+
+ // Call into the Lua callback passing 'sb_frame' and 'sb_wp'.
+ if (lua_pcall(L, nargs, 1, 0) != LUA_OK) {
+ luaL_error(L, "%s", lua_tostring(L, -1));
+ return true;
+ }
+
+ // Boolean return from the callback
+ bool stop = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+
+ return stop;
+}
+
%}
Index: lldb/bindings/lua/lua-typemaps.swig
===================================================================
--- lldb/bindings/lua/lua-typemaps.swig
+++ lldb/bindings/lua/lua-typemaps.swig
@@ -314,3 +314,29 @@
}
//===----------------------------------------------------------------------===//
+
+// Typemap for closure callback in external scripting environment
+
+%typemap(arginit) const SBBreakpointCallbackBatonSP &baton_sp {
+ // We could `SBBreakpointCallbackBatonSP baton_sp;` inside "%typemap(in)"
+ // but SWIG puts "%typemap(in)" part and the real call in 2 *different* scopes
+ // so the smart pointer destructs earlier than it is used by the call.
+ $1 = new SBBreakpointCallbackBatonSP();
+}
+
+%typemap(in) const SBBreakpointCallbackBatonSP &baton_sp {
+ if (lua_isfunction(L, $input)) {
+ auto data_up = std::make_unique<CallbackDataLua>(L);
+ lua_pushlightuserdata(L, data_up.get());
+ lua_pushvalue(L, $input);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ *$1 = std::make_shared<SBBreakpointCallbackBaton>(std::move(data_up));
+ }
+ else {
+ return luaL_error(L, "Expect a Lua function.");
+ }
+}
+
+%typemap(freearg) const SBBreakpointCallbackBatonSP &baton_sp {
+ free($1);
+}
Index: lldb/bindings/interface/SBBreakpoint.i
===================================================================
--- lldb/bindings/interface/SBBreakpoint.i
+++ lldb/bindings/interface/SBBreakpoint.i
@@ -177,6 +177,11 @@
const char *
GetQueueName () const;
+ %feature("docstring", "
+ Set a specific closure to be called when the breakpoint is hit.") SetScriptCallback;
+ void
+ SetScriptCallback (const SBBreakpointCallbackBatonSP &baton_sp);
+
%feature("docstring", "
Set the name of the script function to be called when the breakpoint is hit.") SetScriptCallbackFunction;
void
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits