Skip to content

Commit f03dbdb

Browse files
committed
[lldb][LocateModuleCallback] Implement API, Python interface
RFC https://discourse.llvm.org/t/rfc-python-callback-for-target-get-module/71580 Use SWIG for the locate module callback the same as other Python callbacks. TestLocateModuleCallback.py verifies the functionalities. Differential Revision: https://reviews.llvm.org/D153735
1 parent 1a4bc11 commit f03dbdb

6 files changed

Lines changed: 494 additions & 0 deletions

File tree

lldb/bindings/python/python-typemaps.swig

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,3 +576,54 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
576576
return NULL;
577577
}
578578
}
579+
580+
// For lldb::SBPlatformLocateModuleCallback
581+
%typemap(in) (lldb::SBPlatformLocateModuleCallback callback,
582+
void *callback_baton) {
583+
if (!($input == Py_None ||
584+
PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
585+
PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
586+
SWIG_fail;
587+
}
588+
589+
if ($input == Py_None) {
590+
$1 = nullptr;
591+
$2 = nullptr;
592+
} else {
593+
PythonCallable callable = Retain<PythonCallable>($input);
594+
if (!callable.IsValid()) {
595+
PyErr_SetString(PyExc_TypeError, "Need a valid callable object");
596+
SWIG_fail;
597+
}
598+
599+
llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo();
600+
if (!arg_info) {
601+
PyErr_SetString(PyExc_TypeError,
602+
("Could not get arguments: " +
603+
llvm::toString(arg_info.takeError())).c_str());
604+
SWIG_fail;
605+
}
606+
607+
if (arg_info.get().max_positional_args != 3) {
608+
PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object");
609+
SWIG_fail;
610+
}
611+
612+
// NOTE: When this is called multiple times, this will leak the Python
613+
// callable object as other callbacks, because this does not call Py_DECREF
614+
// the object. But it should be almost zero impact since this method is
615+
// expected to be called only once.
616+
617+
// Don't lose the callback reference
618+
Py_INCREF($input);
619+
620+
$1 = LLDBSwigPythonCallLocateModuleCallback;
621+
$2 = $input;
622+
}
623+
}
624+
625+
%typemap(typecheck) (lldb::SBPlatformLocateModuleCallback callback,
626+
void *callback_baton) {
627+
$1 = $input == Py_None;
628+
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
629+
}

lldb/bindings/python/python-wrapper.swig

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,4 +1118,54 @@ static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t
11181118
SWIG_PYTHON_THREAD_END_BLOCK;
11191119
}
11201120
}
1121+
1122+
static SBError LLDBSwigPythonCallLocateModuleCallback(
1123+
void *callback_baton, const SBModuleSpec &module_spec_sb,
1124+
SBFileSpec &module_file_spec_sb, SBFileSpec &symbol_file_spec_sb) {
1125+
SWIG_Python_Thread_Block swig_thread_block;
1126+
1127+
PyErr_Cleaner py_err_cleaner(true);
1128+
PythonObject module_spec_arg = SWIGBridge::ToSWIGWrapper(
1129+
std::move(std::make_unique<SBModuleSpec>(module_spec_sb)));
1130+
PythonObject module_file_spec_arg = SWIGBridge::ToSWIGWrapper(
1131+
std::move(std::make_unique<SBFileSpec>(module_file_spec_sb)));
1132+
PythonObject symbol_file_spec_arg = SWIGBridge::ToSWIGWrapper(
1133+
std::move(std::make_unique<SBFileSpec>(symbol_file_spec_sb)));
1134+
1135+
PythonCallable callable =
1136+
Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton));
1137+
if (!callable.IsValid()) {
1138+
return SBError("The callback callable is not valid.");
1139+
}
1140+
1141+
PythonObject result = callable(module_spec_arg, module_file_spec_arg,
1142+
symbol_file_spec_arg);
1143+
1144+
if (!result.IsAllocated())
1145+
return SBError("No result.");
1146+
lldb::SBError *sb_error_ptr = nullptr;
1147+
if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr,
1148+
SWIGTYPE_p_lldb__SBError, 0) == -1) {
1149+
return SBError("Result is not SBError.");
1150+
}
1151+
1152+
if (sb_error_ptr->Success()) {
1153+
lldb::SBFileSpec *sb_module_file_spec_ptr = nullptr;
1154+
if (SWIG_ConvertPtr(module_file_spec_arg.get(),
1155+
(void **)&sb_module_file_spec_ptr,
1156+
SWIGTYPE_p_lldb__SBFileSpec, 0) == -1)
1157+
return SBError("module_file_spec is not SBFileSpec.");
1158+
1159+
lldb::SBFileSpec *sb_symbol_file_spec_ptr = nullptr;
1160+
if (SWIG_ConvertPtr(symbol_file_spec_arg.get(),
1161+
(void **)&sb_symbol_file_spec_ptr,
1162+
SWIGTYPE_p_lldb__SBFileSpec, 0) == -1)
1163+
return SBError("symbol_file_spec is not SBFileSpec.");
1164+
1165+
module_file_spec_sb = *sb_module_file_spec_ptr;
1166+
symbol_file_spec_sb = *sb_symbol_file_spec_ptr;
1167+
}
1168+
1169+
return *sb_error_ptr;
1170+
}
11211171
%}

lldb/include/lldb/API/SBDefines.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
126126
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
127127
void *baton);
128128

129+
typedef SBError (*SBPlatformLocateModuleCallback)(
130+
void *baton, const SBModuleSpec &module_spec, SBFileSpec &module_file_spec,
131+
SBFileSpec &symbol_file_spec);
132+
129133
typedef void *ScriptedObject;
130134
}
131135

lldb/include/lldb/API/SBPlatform.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ class LLDB_API SBPlatform {
169169
/// environment.
170170
SBEnvironment GetEnvironment();
171171

172+
/// Set a callback as an implementation for locating module in order to
173+
/// implement own module cache system. For example, to leverage distributed
174+
/// build system, to bypass pulling files from remote platform, or to search
175+
/// symbol files from symbol servers. The target will call this callback to
176+
/// get a module file and a symbol file, and it will fallback to the LLDB
177+
/// implementation when this callback failed or returned non-existent file.
178+
/// This callback can set either module_file_spec or symbol_file_spec, or both
179+
/// module_file_spec and symbol_file_spec. The callback will be cleared if
180+
/// nullptr or None is set.
181+
SBError SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback,
182+
void *callback_baton);
183+
172184
protected:
173185
friend class SBDebugger;
174186
friend class SBTarget;

lldb/source/API/SBPlatform.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lldb/API/SBError.h"
1212
#include "lldb/API/SBFileSpec.h"
1313
#include "lldb/API/SBLaunchInfo.h"
14+
#include "lldb/API/SBModuleSpec.h"
1415
#include "lldb/API/SBPlatform.h"
1516
#include "lldb/API/SBUnixSignals.h"
1617
#include "lldb/Host/File.h"
@@ -655,3 +656,41 @@ SBEnvironment SBPlatform::GetEnvironment() {
655656

656657
return SBEnvironment();
657658
}
659+
660+
SBError SBPlatform::SetLocateModuleCallback(
661+
lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) {
662+
LLDB_INSTRUMENT_VA(this, callback, callback_baton);
663+
PlatformSP platform_sp(GetSP());
664+
if (!platform_sp)
665+
return SBError("invalid platform");
666+
667+
if (!callback) {
668+
// Clear the callback.
669+
platform_sp->SetLocateModuleCallback(nullptr);
670+
return SBError();
671+
}
672+
673+
// Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly
674+
// because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to
675+
// convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback
676+
// arguments.
677+
platform_sp->SetLocateModuleCallback(
678+
[callback, callback_baton](const ModuleSpec &module_spec,
679+
FileSpec &module_file_spec,
680+
FileSpec &symbol_file_spec) {
681+
SBModuleSpec module_spec_sb(module_spec);
682+
SBFileSpec module_file_spec_sb;
683+
SBFileSpec symbol_file_spec_sb;
684+
685+
SBError error = callback(callback_baton, module_spec_sb,
686+
module_file_spec_sb, symbol_file_spec_sb);
687+
688+
if (error.Success()) {
689+
module_file_spec = module_file_spec_sb.ref();
690+
symbol_file_spec = symbol_file_spec_sb.ref();
691+
}
692+
693+
return error.ref();
694+
});
695+
return SBError();
696+
}

0 commit comments

Comments
 (0)