Skip to content

Commit f2d35f6

Browse files
author
jeffreytan81
committed
Add SBDebugger::AddNotificationCallback
1 parent 1a350e4 commit f2d35f6

File tree

13 files changed

+256
-11
lines changed

13 files changed

+256
-11
lines changed

lldb/bindings/python/python-swigsafecast.swig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,15 @@ 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+
141+
PythonObject SWIGBridge::ToSWIGWrapper(
142+
std::unique_ptr<lldb::SBExecutionContext> exe_ctx_sb) {
143+
return ToSWIGHelper(exe_ctx_sb.release(), SWIGTYPE_p_lldb__SBExecutionContext);
144+
}
145+
136146
} // namespace python
137147
} // 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::SBNotificationCallback
456+
%typemap(in) (lldb::SBNotificationCallback notification_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 = LLDBSwigPythonCallPythonSBNotificationCallback;
466+
$2 = $input;
467+
}
468+
469+
%typemap(typecheck) (lldb::SBNotificationCallback notification_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: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,46 @@ static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str,
10241024
}
10251025
}
10261026

1027+
// For NotificationCallback functions
1028+
static void LLDBSwigPythonCallPythonSBNotificationCallback(
1029+
lldb::NotificationType type, lldb::SBDebugger &debugger,
1030+
lldb::SBExecutionContext &exe_ctx, void *baton) {
1031+
1032+
if (baton != Py_None) {
1033+
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
1034+
1035+
// Convert debugger and exe_ctx to Python objects
1036+
PythonObject debugger_arg = SWIGBridge::ToSWIGWrapper(
1037+
std::make_unique<SBDebugger>(debugger)); // Wrap debugger reference
1038+
1039+
PythonObject exe_ctx_arg = SWIGBridge::ToSWIGWrapper(
1040+
std::make_unique<SBExecutionContext>(exe_ctx)); // Wrap ExecutionContext
1041+
1042+
// Create a tuple of arguments (type, debugger, exe_ctx)
1043+
PyObject *args = PyTuple_New(3);
1044+
1045+
// Add NotificationType as an integer to the tuple
1046+
PyTuple_SetItem(args, 0, PyLong_FromLong(static_cast<long>(type)));
1047+
1048+
// Add debugger and exe_ctx to the tuple
1049+
Py_INCREF(debugger_arg.get());
1050+
PyTuple_SetItem(args, 1, debugger_arg.get());
1051+
1052+
Py_INCREF(exe_ctx_arg.get());
1053+
PyTuple_SetItem(args, 2, exe_ctx_arg.get());
1054+
1055+
// Call the Python function with the tuple of arguments (type, debugger, exe_ctx)
1056+
PyObject *result = PyObject_CallFunction(
1057+
reinterpret_cast<PyObject *>(baton), const_cast<char *>("O"), args);
1058+
1059+
// Clean up
1060+
Py_XDECREF(result);
1061+
Py_DECREF(args); // Decrement reference count for args
1062+
1063+
SWIG_PYTHON_THREAD_END_BLOCK;
1064+
}
1065+
}
1066+
10271067
// For DebuggerTerminateCallback functions
10281068
static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id,
10291069
void *baton) {

lldb/include/lldb/API/SBDebugger.h

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

339+
/// Add a notification callback when notification type event happens. Return a
340+
/// token, which can be used to remove said callback. Multiple callbacks can
341+
/// be added by calling this function multiple times, and will be invoked in
342+
/// FIFO order.
343+
static lldb::callback_token_t
344+
AddNotificationCallback(lldb::NotificationType notification_type,
345+
lldb::SBNotificationCallback notification_callback,
346+
void *baton);
347+
/// Remove the specified callback. Return true if successful.
348+
static bool RemoveNotificationCallback(lldb::callback_token_t token);
349+
339350
/// Add a callback for when the debugger is destroyed. Return a token, which
340351
/// can be used to remove said callback. Multiple callbacks can be added by
341352
/// calling this function multiple times, and will be invoked in FIFO order.

lldb/include/lldb/API/SBDefines.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,10 @@ class LLDB_API SBUnixSignals;
138138
typedef bool (*SBBreakpointHitCallback)(void *baton, lldb::SBProcess &process,
139139
lldb::SBThread &thread,
140140
lldb::SBBreakpointLocation &location);
141-
141+
typedef void (*SBNotificationCallback)(lldb::NotificationType type,
142+
lldb::SBDebugger &,
143+
lldb::SBExecutionContext &exe_ctx,
144+
void *baton);
142145
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
143146
void *baton);
144147

lldb/include/lldb/API/SBExecutionContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class LLDB_API SBExecutionContext {
5858

5959
lldb_private::ExecutionContextRef *get() const;
6060

61+
friend class SBDebugger;
6162
SBExecutionContext(lldb::ExecutionContextRefSP exe_ctx_ref_sp);
6263

6364
private:

lldb/include/lldb/Core/Debugger.h

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

572+
/// Add a notification callback when notification type event happens. Return a
573+
/// token, which can be used to remove said callback. Multiple callbacks can
574+
/// be added by calling this function multiple times, and will be invoked in
575+
/// FIFO order.
576+
static lldb::callback_token_t AddNotificationCallback(
577+
lldb::NotificationType type,
578+
lldb_private::NotificationCallback notification_callback, void *baton,
579+
void *original_callback);
580+
581+
/// Remove the specified callback. Return true if successful.
582+
static bool RemoveNotificationCallback(lldb::callback_token_t token);
583+
572584
/// Add a callback for when the debugger is destroyed. Return a token, which
573585
/// can be used to remove said callback. Multiple callbacks can be added by
574586
/// calling this function multiple times, and will be invoked in FIFO order.
@@ -683,6 +695,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
683695

684696
void InstanceInitialize();
685697

698+
static void InvokeNotificationCallbacks(lldb::DebuggerSP debugger_sp,
699+
lldb::NotificationType notify_type);
700+
686701
// these should never be NULL
687702
lldb::FileSP m_input_file_sp;
688703
lldb::StreamFileSP m_output_stream_sp;
@@ -737,19 +752,35 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
737752
lldb::TargetSP m_dummy_target_sp;
738753
Diagnostics::CallbackID m_diagnostics_callback_id;
739754

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)
755+
template <typename T> struct CallbackInfo {
756+
CallbackInfo() {}
757+
CallbackInfo(lldb::callback_token_t token, T callback, void *baton)
747758
: token(token), callback(callback), baton(baton) {}
748759
lldb::callback_token_t token;
749-
lldb_private::DebuggerDestroyCallback callback;
760+
T callback;
750761
void *baton;
751762
};
752-
llvm::SmallVector<DestroyCallbackInfo, 2> m_destroy_callbacks;
763+
template <typename T>
764+
struct NotificationCallbackInfo : public CallbackInfo<T> {
765+
NotificationCallbackInfo() {}
766+
NotificationCallbackInfo(lldb::callback_token_t token,
767+
lldb::NotificationType type, T callback,
768+
void *baton, void *original_callback)
769+
: CallbackInfo<T>(token, callback, baton), type(type),
770+
original_callback(original_callback) {}
771+
lldb::NotificationType type;
772+
void *original_callback;
773+
};
774+
static std::mutex s_notification_callback_mutex;
775+
static lldb::callback_token_t s_notification_callback_next_token;
776+
static llvm::SmallVector<
777+
NotificationCallbackInfo<lldb_private::NotificationCallback>, 2>
778+
s_notification_callbacks;
779+
780+
std::mutex m_destroy_callback_mutex;
781+
lldb::callback_token_t m_destroy_callback_next_token = 0;
782+
llvm::SmallVector<CallbackInfo<lldb_private::DebuggerDestroyCallback>, 2>
783+
m_destroy_callbacks;
753784

754785
uint32_t m_interrupt_requested = 0; ///< Tracks interrupt requests
755786
std::mutex m_interrupt_mutex;

lldb/include/lldb/lldb-enumerations.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,12 @@ enum Severity {
13621362
eSeverityInfo, // Equivalent to Remark used in clang.
13631363
};
13641364

1365+
enum NotificationType {
1366+
eDebuggerWillBeCreated = (1 << 0),
1367+
eDebuggerWillBeDestroyed =
1368+
(1 << 1), // Call before debugger object is destroyed
1369+
};
1370+
13651371
} // namespace lldb
13661372

13671373
#endif // LLDB_LLDB_ENUMERATIONS_H

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

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

146+
typedef void (*NotificationCallback)(lldb::NotificationType type,
147+
lldb::DebuggerSP debugger,
148+
lldb::ExecutionContextRefSP exe_ctx,
149+
void *baton, void *original_callback);
146150
typedef void (*DebuggerDestroyCallback)(lldb::user_id_t debugger_id,
147151
void *baton);
148152
typedef bool (*CommandOverrideCallbackWithResult)(

lldb/source/API/SBDebugger.cpp

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

1706+
lldb::callback_token_t SBDebugger::AddNotificationCallback(
1707+
lldb::NotificationType type,
1708+
lldb::SBNotificationCallback notification_callback, void *baton) {
1709+
LLDB_INSTRUMENT_VA(type, notification_callback, baton);
1710+
1711+
NotificationCallback callback = [](lldb::NotificationType type,
1712+
lldb::DebuggerSP debugger,
1713+
lldb::ExecutionContextRefSP exe_ctx,
1714+
void *baton, void *original_callback) {
1715+
SBDebugger sb_debugger(debugger);
1716+
lldb::SBNotificationCallback original_callback_func =
1717+
(lldb::SBNotificationCallback)original_callback;
1718+
SBExecutionContext sb_exe_ctx(exe_ctx);
1719+
original_callback_func(type, sb_debugger, sb_exe_ctx, baton);
1720+
};
1721+
return Debugger::AddNotificationCallback(type, callback, baton,
1722+
(void *)notification_callback);
1723+
}
1724+
1725+
bool SBDebugger::RemoveNotificationCallback(lldb::callback_token_t token) {
1726+
LLDB_INSTRUMENT_VA(token);
1727+
return Debugger::RemoveNotificationCallback(token);
1728+
}
1729+
17061730
lldb::callback_token_t
17071731
SBDebugger::AddDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback,
17081732
void *baton) {

lldb/source/Core/Debugger.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ 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_notification_callback_mutex;
110+
lldb::callback_token_t Debugger::s_notification_callback_next_token = 0;
111+
llvm::SmallVector<
112+
Debugger::NotificationCallbackInfo<lldb_private::NotificationCallback>, 2>
113+
Debugger::s_notification_callbacks;
114+
109115
static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
110116
{
111117
Debugger::eStopDisassemblyTypeNever,
@@ -739,16 +745,29 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
739745
g_debugger_list_ptr->push_back(debugger_sp);
740746
}
741747
debugger_sp->InstanceInitialize();
748+
749+
InvokeNotificationCallbacks(debugger_sp, lldb::eDebuggerWillBeCreated);
742750
return debugger_sp;
743751
}
744752

753+
void Debugger::InvokeNotificationCallbacks(DebuggerSP debugger_sp,
754+
lldb::NotificationType notify_type) {
755+
std::lock_guard<std::mutex> guard(s_notification_callback_mutex);
756+
for (const auto &callback_info : s_notification_callbacks) {
757+
if ((callback_info.type & notify_type) == notify_type)
758+
callback_info.callback(notify_type, debugger_sp, nullptr,
759+
callback_info.baton,
760+
callback_info.original_callback);
761+
}
762+
}
763+
745764
void Debugger::HandleDestroyCallback() {
746765
const lldb::user_id_t user_id = GetID();
747766
// Invoke and remove all the callbacks in an FIFO order. Callbacks which are
748767
// added during this loop will be appended, invoked and then removed last.
749768
// Callbacks which are removed during this loop will not be invoked.
750769
while (true) {
751-
DestroyCallbackInfo callback_info;
770+
CallbackInfo<DebuggerDestroyCallback> callback_info;
752771
{
753772
std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
754773
if (m_destroy_callbacks.empty())
@@ -766,6 +785,7 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) {
766785
if (!debugger_sp)
767786
return;
768787

788+
InvokeNotificationCallbacks(debugger_sp, lldb::eDebuggerWillBeDestroyed);
769789
debugger_sp->HandleDestroyCallback();
770790
CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
771791

@@ -1447,6 +1467,29 @@ void Debugger::SetDestroyCallback(
14471467
m_destroy_callbacks.emplace_back(token, destroy_callback, baton);
14481468
}
14491469

1470+
lldb::callback_token_t Debugger::AddNotificationCallback(
1471+
lldb::NotificationType type,
1472+
lldb_private::NotificationCallback notification_callback, void *baton,
1473+
void *original_callback) {
1474+
std::lock_guard<std::mutex> guard(s_notification_callback_mutex);
1475+
const lldb::callback_token_t token = s_notification_callback_next_token++;
1476+
s_notification_callbacks.emplace_back(token, type, notification_callback,
1477+
baton, original_callback);
1478+
return token;
1479+
}
1480+
1481+
bool Debugger::RemoveNotificationCallback(lldb::callback_token_t token) {
1482+
std::lock_guard<std::mutex> guard(s_notification_callback_mutex);
1483+
for (auto it = s_notification_callbacks.begin();
1484+
it != s_notification_callbacks.end(); ++it) {
1485+
if (it->token == token) {
1486+
s_notification_callbacks.erase(it);
1487+
return true;
1488+
}
1489+
}
1490+
return false;
1491+
}
1492+
14501493
lldb::callback_token_t Debugger::AddDestroyCallback(
14511494
lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
14521495
std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class SBStructuredData;
3333
class SBFileSpec;
3434
class SBModuleSpec;
3535
class SBStringList;
36+
class SBDebugger;
37+
class SBExecutionContext;
3638
} // namespace lldb
3739

3840
namespace lldb_private {
@@ -111,6 +113,10 @@ class SWIGBridge {
111113
ToSWIGWrapper(std::unique_ptr<lldb::SBFileSpec> file_spec_sb);
112114
static PythonObject
113115
ToSWIGWrapper(std::unique_ptr<lldb::SBModuleSpec> module_spec_sb);
116+
static PythonObject
117+
ToSWIGWrapper(std::unique_ptr<lldb::SBDebugger> debugger_sb);
118+
static PythonObject
119+
ToSWIGWrapper(std::unique_ptr<lldb::SBExecutionContext> exe_ctx_sb);
114120

115121
static python::ScopedPythonObject<lldb::SBCommandReturnObject>
116122
ToSWIGWrapper(CommandReturnObject &cmd_retobj);

0 commit comments

Comments
 (0)