Skip to content

Commit 4f11996

Browse files
author
jeffreytan81
committed
Add SBDebugger::AddCreateCallback API
1 parent 1a350e4 commit 4f11996

File tree

11 files changed

+174
-10
lines changed

11 files changed

+174
-10
lines changed

lldb/bindings/python/python-swigsafecast.swig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,10 @@ PythonObject SWIGBridge::ToSWIGWrapper(
133133
return ToSWIGHelper(module_spec_sb.release(), SWIGTYPE_p_lldb__SBModuleSpec);
134134
}
135135

136+
PythonObject SWIGBridge::ToSWIGWrapper(
137+
std::unique_ptr<lldb::SBDebugger> debugger_sb) {
138+
return ToSWIGHelper(debugger_sb.release(), SWIGTYPE_p_lldb__SBDebugger);
139+
}
140+
136141
} // namespace python
137142
} // namespace lldb_private

lldb/bindings/python/python-typemaps.swig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,25 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
452452
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
453453
}
454454

455+
// For lldb::SBDebuggerCreateCallback
456+
%typemap(in) (lldb::SBDebuggerCreateCallback create_callback, void *baton) {
457+
if (!($input == Py_None ||
458+
PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
459+
PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
460+
SWIG_fail;
461+
}
462+
463+
// Don't lose the callback reference
464+
Py_INCREF($input);
465+
$1 = LLDBSwigPythonCallPythonSBDebuggerCreateCallback;
466+
$2 = $input;
467+
}
468+
469+
%typemap(typecheck) (lldb::SBDebuggerCreateCallback create_callback, void *baton) {
470+
$1 = $input == Py_None;
471+
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
472+
}
473+
455474
// For lldb::SBDebuggerDestroyCallback
456475
%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
457476
if (!($input == Py_None ||

lldb/bindings/python/python-wrapper.swig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,26 @@ static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str,
10241024
}
10251025
}
10261026

1027+
// For DebuggerCreateCallback functions
1028+
static void LLDBSwigPythonCallPythonSBDebuggerCreateCallback(lldb::SBDebugger &debugger,
1029+
void *baton) {
1030+
if (baton != Py_None) {
1031+
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
1032+
PythonObject debugger_arg = SWIGBridge::ToSWIGWrapper(
1033+
std::make_unique<SBDebugger>(debugger));
1034+
1035+
// Create a tuple of arguments
1036+
PyObject *args = PyTuple_New(1);
1037+
PyTuple_SetItem(args, 0, debugger_arg.get());
1038+
1039+
// Call the Python function
1040+
PyObject *result = PyObject_CallFunction(
1041+
reinterpret_cast<PyObject *>(baton), const_cast<char *>("O"), args);
1042+
Py_XDECREF(result);
1043+
SWIG_PYTHON_THREAD_END_BLOCK;
1044+
}
1045+
}
1046+
10271047
// For DebuggerTerminateCallback functions
10281048
static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id,
10291049
void *baton) {

lldb/include/lldb/API/SBDebugger.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,16 @@ class LLDB_API SBDebugger {
336336
void SetDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback,
337337
void *baton);
338338

339+
/// Add a callback for when the debugger is created. Return a token, which
340+
/// can be used to remove said callback. Multiple callbacks can be added by
341+
/// calling this function multiple times, and will be invoked in FIFO order.
342+
static lldb::callback_token_t
343+
AddCreateCallback(lldb::SBDebuggerCreateCallback create_callback,
344+
void *baton);
345+
346+
/// Remove the specified callback. Return true if successful.
347+
static bool RemoveCreateCallback(lldb::callback_token_t token);
348+
339349
/// Add a callback for when the debugger is destroyed. Return a token, which
340350
/// can be used to remove said callback. Multiple callbacks can be added by
341351
/// calling this function multiple times, and will be invoked in FIFO order.

lldb/include/lldb/API/SBDefines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, lldb::SBProcess &process,
139139
lldb::SBThread &thread,
140140
lldb::SBBreakpointLocation &location);
141141

142+
typedef void (*SBDebuggerCreateCallback)(lldb::SBDebugger &debugger,
143+
void *baton);
142144
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
143145
void *baton);
144146

lldb/include/lldb/Core/Debugger.h

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,16 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
569569
SetDestroyCallback(lldb_private::DebuggerDestroyCallback destroy_callback,
570570
void *baton);
571571

572+
/// Add a callback for when the debugger is created. Return a token, which
573+
/// can be used to remove said callback. Multiple callbacks can be added by
574+
/// calling this function multiple times, and will be invoked in FIFO order.
575+
static lldb::callback_token_t
576+
AddCreateCallback(lldb_private::DebuggerCreateCallback create_callback,
577+
void *baton, void *original_callback);
578+
579+
/// Remove the specified callback. Return true if successful.
580+
static bool RemoveCreateCallback(lldb::callback_token_t token);
581+
572582
/// Add a callback for when the debugger is destroyed. Return a token, which
573583
/// can be used to remove said callback. Multiple callbacks can be added by
574584
/// calling this function multiple times, and will be invoked in FIFO order.
@@ -737,19 +747,32 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
737747
lldb::TargetSP m_dummy_target_sp;
738748
Diagnostics::CallbackID m_diagnostics_callback_id;
739749

740-
std::mutex m_destroy_callback_mutex;
741-
lldb::callback_token_t m_destroy_callback_next_token = 0;
742-
struct DestroyCallbackInfo {
743-
DestroyCallbackInfo() {}
744-
DestroyCallbackInfo(lldb::callback_token_t token,
745-
lldb_private::DebuggerDestroyCallback callback,
746-
void *baton)
750+
template <typename T> struct CallbackInfo {
751+
CallbackInfo() {}
752+
CallbackInfo(lldb::callback_token_t token, T callback, void *baton)
747753
: token(token), callback(callback), baton(baton) {}
748754
lldb::callback_token_t token;
749-
lldb_private::DebuggerDestroyCallback callback;
755+
T callback;
750756
void *baton;
751757
};
752-
llvm::SmallVector<DestroyCallbackInfo, 2> m_destroy_callbacks;
758+
template <typename T, typename ExtraT>
759+
struct CallbackInfoExtraData : public CallbackInfo<T> {
760+
CallbackInfoExtraData() {}
761+
CallbackInfoExtraData(lldb::callback_token_t token, T callback, void *baton,
762+
ExtraT extra_data)
763+
: CallbackInfo<T>(token, callback, baton), extra_data(extra_data) {}
764+
ExtraT extra_data;
765+
};
766+
static std::mutex s_create_callback_mutex;
767+
static lldb::callback_token_t s_create_callback_next_token;
768+
static llvm::SmallVector<
769+
CallbackInfoExtraData<lldb_private::DebuggerCreateCallback, void *>, 2>
770+
s_create_callbacks;
771+
772+
std::mutex m_destroy_callback_mutex;
773+
lldb::callback_token_t m_destroy_callback_next_token = 0;
774+
llvm::SmallVector<CallbackInfo<lldb_private::DebuggerDestroyCallback>, 2>
775+
m_destroy_callbacks;
753776

754777
uint32_t m_interrupt_requested = 0; ///< Tracks interrupt requests
755778
std::mutex m_interrupt_mutex;

lldb/include/lldb/lldb-private-types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ typedef struct type256 { uint64_t x[4]; } type256;
143143
using ValueObjectProviderTy =
144144
std::function<lldb::ValueObjectSP(ConstString, StackFrame *)>;
145145

146+
typedef void (*DebuggerCreateCallback)(lldb::DebuggerSP debugger, void *baton,
147+
void *original_callback);
146148
typedef void (*DebuggerDestroyCallback)(lldb::user_id_t debugger_id,
147149
void *baton);
148150
typedef bool (*CommandOverrideCallbackWithResult)(

lldb/source/API/SBDebugger.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,26 @@ void SBDebugger::SetDestroyCallback(
17031703
}
17041704
}
17051705

1706+
lldb::callback_token_t
1707+
SBDebugger::AddCreateCallback(lldb::SBDebuggerCreateCallback create_callback,
1708+
void *baton) {
1709+
LLDB_INSTRUMENT_VA(create_callback, baton);
1710+
1711+
DebuggerCreateCallback callback = [](lldb::DebuggerSP debugger, void *baton,
1712+
void *original_callback) {
1713+
SBDebugger sb_debugger(debugger);
1714+
lldb::SBDebuggerCreateCallback original_callback_func =
1715+
(lldb::SBDebuggerCreateCallback)original_callback;
1716+
original_callback_func(sb_debugger, baton);
1717+
};
1718+
return Debugger::AddCreateCallback(callback, baton, (void *)create_callback);
1719+
}
1720+
1721+
bool SBDebugger::RemoveCreateCallback(lldb::callback_token_t token) {
1722+
LLDB_INSTRUMENT_VA(token);
1723+
return Debugger::RemoveCreateCallback(token);
1724+
}
1725+
17061726
lldb::callback_token_t
17071727
SBDebugger::AddDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback,
17081728
void *baton) {

lldb/source/Core/Debugger.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ static Debugger::DebuggerList *g_debugger_list_ptr =
106106
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
107107
static llvm::DefaultThreadPool *g_thread_pool = nullptr;
108108

109+
std::mutex Debugger::s_create_callback_mutex;
110+
lldb::callback_token_t Debugger::s_create_callback_next_token = 0;
111+
llvm::SmallVector<Debugger::CallbackInfoExtraData<
112+
lldb_private::DebuggerCreateCallback, void *>,
113+
2>
114+
Debugger::s_create_callbacks;
115+
109116
static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
110117
{
111118
Debugger::eStopDisassemblyTypeNever,
@@ -739,6 +746,15 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
739746
g_debugger_list_ptr->push_back(debugger_sp);
740747
}
741748
debugger_sp->InstanceInitialize();
749+
750+
// Invoke all debugger create callbacks.
751+
{
752+
std::lock_guard<std::mutex> guard(s_create_callback_mutex);
753+
for (const auto &callback_info : s_create_callbacks) {
754+
callback_info.callback(debugger_sp, callback_info.baton,
755+
callback_info.extra_data);
756+
}
757+
}
742758
return debugger_sp;
743759
}
744760

@@ -748,7 +764,7 @@ void Debugger::HandleDestroyCallback() {
748764
// added during this loop will be appended, invoked and then removed last.
749765
// Callbacks which are removed during this loop will not be invoked.
750766
while (true) {
751-
DestroyCallbackInfo callback_info;
767+
CallbackInfo<DebuggerDestroyCallback> callback_info;
752768
{
753769
std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
754770
if (m_destroy_callbacks.empty())
@@ -1447,6 +1463,28 @@ void Debugger::SetDestroyCallback(
14471463
m_destroy_callbacks.emplace_back(token, destroy_callback, baton);
14481464
}
14491465

1466+
lldb::callback_token_t Debugger::AddCreateCallback(
1467+
lldb_private::DebuggerCreateCallback create_callback, void *baton,
1468+
void *original_callback) {
1469+
std::lock_guard<std::mutex> guard(s_create_callback_mutex);
1470+
const lldb::callback_token_t token = s_create_callback_next_token++;
1471+
s_create_callbacks.emplace_back(token, create_callback, baton,
1472+
original_callback);
1473+
return token;
1474+
}
1475+
1476+
bool Debugger::RemoveCreateCallback(lldb::callback_token_t token) {
1477+
std::lock_guard<std::mutex> guard(s_create_callback_mutex);
1478+
for (auto it = s_create_callbacks.begin(); it != s_create_callbacks.end();
1479+
++it) {
1480+
if (it->token == token) {
1481+
s_create_callbacks.erase(it);
1482+
return true;
1483+
}
1484+
}
1485+
return false;
1486+
}
1487+
14501488
lldb::callback_token_t Debugger::AddDestroyCallback(
14511489
lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
14521490
std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);

lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class SBStructuredData;
3333
class SBFileSpec;
3434
class SBModuleSpec;
3535
class SBStringList;
36+
class SBDebugger;
3637
} // namespace lldb
3738

3839
namespace lldb_private {
@@ -111,6 +112,8 @@ class SWIGBridge {
111112
ToSWIGWrapper(std::unique_ptr<lldb::SBFileSpec> file_spec_sb);
112113
static PythonObject
113114
ToSWIGWrapper(std::unique_ptr<lldb::SBModuleSpec> module_spec_sb);
115+
static PythonObject
116+
ToSWIGWrapper(std::unique_ptr<lldb::SBDebugger> debugger_sb);
114117

115118
static python::ScopedPythonObject<lldb::SBCommandReturnObject>
116119
ToSWIGWrapper(CommandReturnObject &cmd_retobj);

lldb/test/API/python_api/debugger/TestDebuggerAPI.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,25 @@ def remove_bar(dbg_id):
286286
('remove bar ret', False), # remove_bar should fail, because it's already invoked and removed
287287
('foo called', original_dbg_id), # foo should be called
288288
])
289+
290+
def test_AddRemoveDebuggerCreateCallback(self):
291+
"""
292+
Test SBDebugger::AddCreateCallback and SBDebugger::RemoveCreateCallback
293+
"""
294+
created_debuggers = []
295+
def debugger_create_callback(debugger):
296+
created_debuggers.append(debugger)
297+
298+
create_callback_token = lldb.SBDebugger.AddCreateCallback(debugger_create_callback)
299+
debugger1 = lldb.SBDebugger.Create()
300+
debugger2 = lldb.SBDebugger.Create()
301+
302+
lldb.SBDebugger.RemoveCreateCallback(create_callback_token)
303+
debugger3 = lldb.SBDebugger.Create()
304+
305+
self.assertNotEqual(debugger1.GetID(), debugger2.GetID())
306+
self.assertNotEqual(debugger1.GetID(), debugger3.GetID())
307+
308+
self.assertEqual(len(created_debuggers), 2)
309+
self.assertEqual(debugger1.GetID(), created_debuggers[0].GetID())
310+
self.assertEqual(debugger2.GetID(), created_debuggers[1].GetID())

0 commit comments

Comments
 (0)