2013-09-25 10:37:32 +00:00
|
|
|
%header %{
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
class PyErr_Cleaner {
|
2013-09-25 10:37:32 +00:00
|
|
|
public:
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner(bool print = false) : m_print(print) {}
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
~PyErr_Cleaner() {
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
if (m_print && !PyErr_ExceptionMatches(PyExc_SystemExit))
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2013-09-25 10:37:32 +00:00
|
|
|
private:
|
2021-12-14 17:20:23 +01:00
|
|
|
bool m_print;
|
2013-09-25 10:37:32 +00:00
|
|
|
};
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
llvm::Expected<bool> lldb_private::LLDBSwigPythonBreakpointCallbackFunction(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::StackFrameSP &frame_sp,
|
|
|
|
|
const lldb::BreakpointLocationSP &bp_loc_sp,
|
|
|
|
|
const lldb_private::StructuredDataImpl &args_impl) {
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
|
|
lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
|
|
|
|
|
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
|
|
|
|
|
|
|
|
|
unsigned max_positional_args;
|
|
|
|
|
if (auto arg_info = pfunc.GetArgInfo())
|
|
|
|
|
max_positional_args = arg_info.get().max_positional_args;
|
|
|
|
|
else
|
|
|
|
|
return arg_info.takeError();
|
|
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
PythonObject frame_arg = ToSWIGWrapper(frame_sp);
|
2021-12-17 13:02:21 +01:00
|
|
|
PythonObject bp_loc_arg = ToSWIGWrapper(bp_loc_sp);
|
2021-12-14 17:20:23 +01:00
|
|
|
|
2021-12-17 13:02:21 +01:00
|
|
|
auto result =
|
|
|
|
|
max_positional_args < 4
|
|
|
|
|
? pfunc.Call(frame_arg, bp_loc_arg, dict)
|
|
|
|
|
: pfunc.Call(frame_arg, bp_loc_arg, ToSWIGWrapper(args_impl), dict);
|
2021-12-14 17:20:23 +01:00
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
return result.takeError();
|
|
|
|
|
|
|
|
|
|
// Only False counts as false!
|
|
|
|
|
return result.get().get() != Py_False;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-22 16:32:44 +01:00
|
|
|
// resolve a dotted Python name in the form
|
|
|
|
|
// foo.bar.baz.Foobar to an actual Python object
|
|
|
|
|
// if pmodule is NULL, the __main__ module will be used
|
|
|
|
|
// as the starting point for the search
|
2021-03-10 12:48:05 -08:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// This function is called by
|
|
|
|
|
// lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...) and is
|
|
|
|
|
// used when a script command is attached to a breakpoint for execution.
|
2021-11-22 16:32:44 +01:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// This function is called by
|
|
|
|
|
// lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...) and is
|
|
|
|
|
// used when a script command is attached to a watchpoint for execution.
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonWatchpointCallbackFunction(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::StackFrameSP &frame_sp, const lldb::WatchpointSP &wp_sp) {
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool stop_at_watchpoint = true;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return stop_at_watchpoint;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-17 13:02:21 +01:00
|
|
|
PythonObject result =
|
|
|
|
|
pfunc(ToSWIGWrapper(frame_sp), ToSWIGWrapper(wp_sp), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (result.get() == Py_False)
|
|
|
|
|
stop_at_watchpoint = false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return stop_at_watchpoint;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-11 00:44:06 -07:00
|
|
|
// This function is called by
|
|
|
|
|
// ScriptInterpreterPython::FormatterMatchingCallbackFunction and it's used when
|
|
|
|
|
// a data formatter provides the name of a callback to inspect a candidate type
|
|
|
|
|
// before considering a match.
|
|
|
|
|
bool lldb_private::LLDBSwigPythonFormatterCallbackFunction(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::TypeImplSP type_impl_sp) {
|
|
|
|
|
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
PythonObject result =
|
|
|
|
|
pfunc(ToSWIGWrapper(type_impl_sp), dict);
|
|
|
|
|
|
|
|
|
|
// Only if everything goes okay and the function returns True we'll consider
|
|
|
|
|
// it a match.
|
|
|
|
|
return result.get() == Py_True;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonCallTypeScript(
|
|
|
|
|
const char *python_function_name, const void *session_dictionary,
|
|
|
|
|
const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper,
|
|
|
|
|
const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval) {
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
retval.clear();
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!python_function_name || !session_dictionary)
|
|
|
|
|
return false;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *pfunc_impl = nullptr;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (pyfunct_wrapper && *pyfunct_wrapper &&
|
|
|
|
|
PyFunction_Check(*pyfunct_wrapper)) {
|
|
|
|
|
pfunc_impl = (PyObject *)(*pyfunct_wrapper);
|
|
|
|
|
if (pfunc_impl->ob_refcnt == 1) {
|
|
|
|
|
Py_XDECREF(pfunc_impl);
|
|
|
|
|
pfunc_impl = NULL;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *py_dict = (PyObject *)session_dictionary;
|
|
|
|
|
if (!PythonDictionary::Check(py_dict))
|
|
|
|
|
return true;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonDictionary dict(PyRefType::Borrowed, py_dict);
|
2013-12-26 07:21:41 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner pyerr_cleanup(true); // show Python errors
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl);
|
2015-11-12 16:23:16 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated()) {
|
|
|
|
|
pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-11-12 16:23:16 +00:00
|
|
|
if (!pfunc.IsAllocated())
|
2021-12-14 17:20:23 +01:00
|
|
|
return false;
|
2014-11-22 00:02:47 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (pyfunct_wrapper) {
|
|
|
|
|
*pyfunct_wrapper = pfunc.get();
|
|
|
|
|
Py_XINCREF(pfunc.get());
|
2019-10-19 07:05:39 +00:00
|
|
|
}
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2019-10-19 07:05:39 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result;
|
|
|
|
|
auto argc = pfunc.GetArgInfo();
|
|
|
|
|
if (!argc) {
|
|
|
|
|
llvm::consumeError(argc.takeError());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-10-19 07:05:39 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject value_arg = ToSWIGWrapper(valobj_sp);
|
2015-11-11 19:42:35 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (argc.get().max_positional_args < 3)
|
|
|
|
|
result = pfunc(value_arg, dict);
|
|
|
|
|
else
|
2021-12-17 13:02:21 +01:00
|
|
|
result = pfunc(value_arg, dict, ToSWIGWrapper(*options_sp));
|
2015-11-11 19:42:35 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
retval = result.Str().GetString().str();
|
|
|
|
|
|
|
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateSyntheticProvider(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::ValueObjectSP &valobj_sp) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-11-12 16:23:16 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
2015-11-12 16:23:16 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2015-11-12 16:23:16 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto sb_value = std::make_unique<lldb::SBValue>(valobj_sp);
|
|
|
|
|
sb_value->SetPreferSyntheticValue(false);
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject val_arg = ToSWIGWrapper(std::move(sb_value));
|
|
|
|
|
if (!val_arg.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result = pfunc(val_arg, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (result.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateCommandObject(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
2021-11-18 08:11:34 +01:00
|
|
|
lldb::DebuggerSP debugger_sp) {
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2015-03-13 02:20:41 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
return pfunc(ToSWIGWrapper(std::move(debugger_sp)), dict);
|
2015-03-13 02:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-11 23:04:24 -08:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateScriptedObject(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
2023-01-11 23:04:24 -08:00
|
|
|
lldb::ExecutionContextRefSP exe_ctx_sp,
|
2021-11-25 14:01:41 +01:00
|
|
|
const lldb_private::StructuredDataImpl &args_impl,
|
2021-12-14 17:20:23 +01:00
|
|
|
std::string &error_string) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-10-06 00:09:20 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated()) {
|
|
|
|
|
error_string.append("could not find script class: ");
|
|
|
|
|
error_string.append(python_class_name);
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
|
|
|
|
|
if (!arg_info) {
|
|
|
|
|
llvm::handleAllErrors(
|
|
|
|
|
arg_info.takeError(),
|
|
|
|
|
[&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
|
|
|
|
|
[&](const llvm::ErrorInfoBase &E) {
|
|
|
|
|
error_string.append(E.message());
|
|
|
|
|
});
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PythonObject result = {};
|
|
|
|
|
if (arg_info.get().max_positional_args == 2) {
|
2023-01-11 23:04:24 -08:00
|
|
|
result = pfunc(ToSWIGWrapper(exe_ctx_sp), ToSWIGWrapper(args_impl));
|
2021-12-14 17:20:23 +01:00
|
|
|
} else {
|
|
|
|
|
error_string.assign("wrong number of arguments in __init__, should be 2 "
|
|
|
|
|
"(not including self)");
|
|
|
|
|
}
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2021-10-06 00:09:20 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateScriptedThreadPlan(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
2021-11-25 14:01:41 +01:00
|
|
|
const lldb_private::StructuredDataImpl &args_impl,
|
2021-12-14 17:20:23 +01:00
|
|
|
std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2019-11-04 12:48:49 -08:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated()) {
|
|
|
|
|
error_string.append("could not find script class: ");
|
|
|
|
|
error_string.append(python_class_name);
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PythonObject tp_arg = ToSWIGWrapper(thread_plan_sp);
|
|
|
|
|
|
|
|
|
|
llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
|
|
|
|
|
if (!arg_info) {
|
|
|
|
|
llvm::handleAllErrors(
|
|
|
|
|
arg_info.takeError(),
|
|
|
|
|
[&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
|
|
|
|
|
[&](const llvm::ErrorInfoBase &E) {
|
|
|
|
|
error_string.append(E.message());
|
|
|
|
|
});
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PythonObject result = {};
|
|
|
|
|
auto args_sb = std::make_unique<lldb::SBStructuredData>(args_impl);
|
|
|
|
|
if (arg_info.get().max_positional_args == 2) {
|
|
|
|
|
if (args_sb->IsValid()) {
|
|
|
|
|
error_string.assign(
|
|
|
|
|
"args passed, but __init__ does not take an args dictionary");
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2019-10-03 22:50:18 +00:00
|
|
|
}
|
2021-12-14 17:20:23 +01:00
|
|
|
result = pfunc(tp_arg, dict);
|
|
|
|
|
} else if (arg_info.get().max_positional_args >= 3) {
|
|
|
|
|
result = pfunc(tp_arg, ToSWIGWrapper(std::move(args_sb)), dict);
|
|
|
|
|
} else {
|
|
|
|
|
error_string.assign("wrong number of arguments in __init__, should be 2 or "
|
|
|
|
|
"3 (not including self)");
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2019-10-03 22:50:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// FIXME: At this point we should check that the class we found supports all
|
|
|
|
|
// the methods that we need.
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2014-09-29 23:17:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSWIGPythonCallThreadPlan(
|
|
|
|
|
void *implementor, const char *method_name, lldb_private::Event *event,
|
|
|
|
|
bool &got_error) {
|
|
|
|
|
got_error = false;
|
2014-09-29 23:17:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(false);
|
|
|
|
|
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>(method_name);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result;
|
|
|
|
|
if (event != nullptr) {
|
2021-12-20 14:36:27 +01:00
|
|
|
ScopedPythonObject<SBEvent> event_arg = ToSWIGWrapper(event);
|
|
|
|
|
result = pfunc(event_arg.obj());
|
2021-12-14 17:20:23 +01:00
|
|
|
} else
|
|
|
|
|
result = pfunc();
|
2014-09-29 23:17:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (PyErr_Occurred()) {
|
2015-11-12 16:23:16 +00:00
|
|
|
got_error = true;
|
2021-12-14 17:20:23 +01:00
|
|
|
printf("Return value was neither false nor true for call to %s.\n",
|
|
|
|
|
method_name);
|
|
|
|
|
PyErr_Print();
|
2015-11-12 16:23:16 +00:00
|
|
|
return false;
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.get() == Py_True)
|
|
|
|
|
return true;
|
|
|
|
|
else if (result.get() == Py_False)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Somebody returned the wrong thing...
|
|
|
|
|
got_error = true;
|
|
|
|
|
printf("Wrong return value type for call to %s.\n", method_name);
|
|
|
|
|
return false;
|
2014-09-29 23:17:18 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateScriptedBreakpointResolver(
|
[lldb] Fix [some] leaks in python bindings
Using an lldb_private object in the bindings involves three steps
- wrapping the object in it's lldb::SB variant
- using swig to convert/wrap that to a PyObject
- wrapping *that* in a lldb_private::python::PythonObject
Our SBTypeToSWIGWrapper was only handling the middle part. This doesn't
just result in increased boilerplate in the callers, but is also a
functionality problem, as it's very hard to get the lifetime of of all
of these objects right. Most of the callers are creating the SB object
(step 1) on the stack, which means that we end up with dangling python
objects after the function terminates. Most of the time this isn't a
problem, because the python code does not need to persist the objects.
However, there are legitimate cases where they can do it (and even if
the use case is not completely legitimate, crashing is not the best
response to that).
For this reason, some of our code creates the SB object on the heap, but
it has another problem -- it never gets cleaned up.
This patch begins to add a new function (ToSWIGWrapper), which does all
of the three steps, while properly taking care of ownership. In the
first step, I have converted most of the leaky code (except for
SBStructuredData, which needs a bit more work).
Differential Revision: https://reviews.llvm.org/D114259
2021-11-18 21:27:27 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
2021-11-25 14:01:41 +01:00
|
|
|
const StructuredDataImpl &args_impl,
|
[lldb] Fix [some] leaks in python bindings
Using an lldb_private object in the bindings involves three steps
- wrapping the object in it's lldb::SB variant
- using swig to convert/wrap that to a PyObject
- wrapping *that* in a lldb_private::python::PythonObject
Our SBTypeToSWIGWrapper was only handling the middle part. This doesn't
just result in increased boilerplate in the callers, but is also a
functionality problem, as it's very hard to get the lifetime of of all
of these objects right. Most of the callers are creating the SB object
(step 1) on the stack, which means that we end up with dangling python
objects after the function terminates. Most of the time this isn't a
problem, because the python code does not need to persist the objects.
However, there are legitimate cases where they can do it (and even if
the use case is not completely legitimate, crashing is not the best
response to that).
For this reason, some of our code creates the SB object on the heap, but
it has another problem -- it never gets cleaned up.
This patch begins to add a new function (ToSWIGWrapper), which does all
of the three steps, while properly taking care of ownership. In the
first step, I have converted most of the leaky code (except for
SBStructuredData, which needs a bit more work).
Differential Revision: https://reviews.llvm.org/D114259
2021-11-18 21:27:27 +01:00
|
|
|
const lldb::BreakpointSP &breakpoint_sp) {
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result =
|
|
|
|
|
pfunc(ToSWIGWrapper(breakpoint_sp), ToSWIGWrapper(args_impl), dict);
|
|
|
|
|
// FIXME: At this point we should check that the class we found supports all
|
|
|
|
|
// the methods that we need.
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (result.IsAllocated()) {
|
|
|
|
|
// Check that __callback__ is defined:
|
|
|
|
|
auto callback_func = result.ResolveName<PythonCallable>("__callback__");
|
|
|
|
|
if (callback_func.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
unsigned int lldb_private::LLDBSwigPythonCallBreakpointResolver(
|
|
|
|
|
void *implementor, const char *method_name,
|
|
|
|
|
lldb_private::SymbolContext *sym_ctx) {
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(false);
|
|
|
|
|
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>(method_name);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return 0;
|
|
|
|
|
|
2021-12-17 13:02:21 +01:00
|
|
|
PythonObject result = sym_ctx ? pfunc(ToSWIGWrapper(*sym_ctx)) : pfunc();
|
2021-12-14 17:20:23 +01:00
|
|
|
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The callback will return a bool, but we're need to also return ints
|
|
|
|
|
// so we're squirrelling the bool through as an int... And if you return
|
|
|
|
|
// nothing, we'll continue.
|
|
|
|
|
if (strcmp(method_name, "__callback__") == 0) {
|
|
|
|
|
if (result.get() == Py_False)
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
long long ret_val = unwrapOrSetPythonException(As<long long>(result));
|
2020-04-23 04:35:30 +05:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-09-13 21:35:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return ret_val;
|
2018-09-13 21:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSwigPythonCreateScriptedStopHook(
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb::TargetSP target_sp, const char *python_class_name,
|
|
|
|
|
const char *session_dictionary_name, const StructuredDataImpl &args_impl,
|
|
|
|
|
Status &error) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0') {
|
|
|
|
|
error.SetErrorString("Empty class name.");
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
if (!session_dictionary_name) {
|
|
|
|
|
error.SetErrorString("No session dictionary");
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated()) {
|
|
|
|
|
error.SetErrorStringWithFormat("Could not find class: %s.",
|
|
|
|
|
python_class_name);
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PythonObject result =
|
|
|
|
|
pfunc(ToSWIGWrapper(target_sp), ToSWIGWrapper(args_impl), dict);
|
|
|
|
|
|
|
|
|
|
if (result.IsAllocated()) {
|
|
|
|
|
// Check that the handle_stop callback is defined:
|
|
|
|
|
auto callback_func = result.ResolveName<PythonCallable>("handle_stop");
|
|
|
|
|
if (callback_func.IsAllocated()) {
|
|
|
|
|
if (auto args_info = callback_func.GetArgInfo()) {
|
|
|
|
|
size_t num_args = (*args_info).max_positional_args;
|
|
|
|
|
if (num_args != 2) {
|
|
|
|
|
error.SetErrorStringWithFormat(
|
|
|
|
|
"Wrong number of args for "
|
2020-09-29 16:01:25 -07:00
|
|
|
"handle_stop callback, should be 2 (excluding self), got: %zu",
|
2020-09-28 10:28:29 -07:00
|
|
|
num_args);
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
} else
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2021-12-14 17:20:23 +01:00
|
|
|
} else {
|
|
|
|
|
error.SetErrorString("Couldn't get num arguments for handle_stop "
|
|
|
|
|
"callback.");
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2022-01-17 11:29:35 +01:00
|
|
|
return result;
|
2021-12-14 17:20:23 +01:00
|
|
|
} else {
|
|
|
|
|
error.SetErrorStringWithFormat("Class \"%s\" is missing the required "
|
|
|
|
|
"handle_stop callback.",
|
|
|
|
|
python_class_name);
|
2020-09-28 10:28:29 -07:00
|
|
|
}
|
2021-12-14 17:20:23 +01:00
|
|
|
}
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2020-09-28 10:28:29 -07:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonStopHookCallHandleStop(
|
|
|
|
|
void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp,
|
|
|
|
|
lldb::StreamSP stream) {
|
|
|
|
|
// handle_stop will return a bool with the meaning "should_stop"...
|
|
|
|
|
// If you return nothing we'll assume we are going to stop.
|
|
|
|
|
// Also any errors should return true, since we should stop on error.
|
2020-09-28 10:28:29 -07:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(false);
|
|
|
|
|
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>("handle_stop");
|
2020-09-28 10:28:29 -07:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return true;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-17 13:02:21 +01:00
|
|
|
auto *sb_stream = new lldb::SBStream();
|
|
|
|
|
PythonObject sb_stream_arg =
|
|
|
|
|
ToSWIGWrapper(std::unique_ptr<lldb::SBStream>(sb_stream));
|
|
|
|
|
PythonObject result =
|
|
|
|
|
pfunc(ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg);
|
2021-12-14 17:20:23 +01:00
|
|
|
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
stream->PutCString("Python error occurred handling stop-hook.");
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// Now add the result to the output stream. SBStream only
|
|
|
|
|
// makes an internally help StreamString which I can't interpose, so I
|
|
|
|
|
// have to copy it over here.
|
2021-12-17 13:02:21 +01:00
|
|
|
stream->PutCString(sb_stream->GetData());
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (result.get() == Py_False)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// wrapper that calls an optional instance member of an object taking no
|
|
|
|
|
// arguments
|
|
|
|
|
static PyObject *LLDBSwigPython_CallOptionalMember(
|
|
|
|
|
PyObject * implementor, char *callee_name,
|
|
|
|
|
PyObject *ret_if_not_found = Py_None, bool *was_found = NULL) {
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(false);
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>(callee_name);
|
2019-10-27 14:30:56 -07:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated()) {
|
|
|
|
|
if (was_found)
|
|
|
|
|
*was_found = false;
|
|
|
|
|
Py_XINCREF(ret_if_not_found);
|
|
|
|
|
return ret_if_not_found;
|
|
|
|
|
}
|
2020-04-23 04:35:30 +05:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (was_found)
|
|
|
|
|
*was_found = true;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result = pfunc();
|
|
|
|
|
return result.release();
|
|
|
|
|
}
|
2015-10-21 19:28:08 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
size_t lldb_private::LLDBSwigPython_CalculateNumChildren(PyObject * implementor,
|
|
|
|
|
uint32_t max) {
|
|
|
|
|
PythonObject self(PyRefType::Borrowed, implementor);
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>("num_children");
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
auto arg_info = pfunc.GetArgInfo();
|
|
|
|
|
if (!arg_info) {
|
|
|
|
|
llvm::consumeError(arg_info.takeError());
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t ret_val;
|
|
|
|
|
if (arg_info.get().max_positional_args < 1)
|
|
|
|
|
ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call()));
|
|
|
|
|
else
|
|
|
|
|
ret_val = unwrapOrSetPythonException(
|
|
|
|
|
As<long long>(pfunc.Call(PythonInteger(max))));
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (arg_info.get().max_positional_args < 1)
|
|
|
|
|
ret_val = std::min(ret_val, static_cast<size_t>(max));
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *lldb_private::LLDBSwigPython_GetChildAtIndex(PyObject * implementor,
|
|
|
|
|
uint32_t idx) {
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject self(PyRefType::Borrowed, implementor);
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>("get_child_at_index");
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return nullptr;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject result = pfunc(PythonInteger(idx));
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!result.IsAllocated())
|
|
|
|
|
return nullptr;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb::SBValue *sbvalue_ptr = nullptr;
|
|
|
|
|
if (SWIG_ConvertPtr(result.get(), (void **)&sbvalue_ptr,
|
|
|
|
|
SWIGTYPE_p_lldb__SBValue, 0) == -1)
|
|
|
|
|
return nullptr;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (sbvalue_ptr == nullptr)
|
|
|
|
|
return nullptr;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return result.release();
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
int lldb_private::LLDBSwigPython_GetIndexOfChildWithName(
|
|
|
|
|
PyObject * implementor, const char *child_name) {
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject self(PyRefType::Borrowed, implementor);
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>("get_child_index");
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return UINT32_MAX;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
llvm::Expected<PythonObject> result = pfunc.Call(PythonString(child_name));
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
long long retval =
|
|
|
|
|
unwrapOrSetPythonException(As<long long>(std::move(result)));
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Clear(); // FIXME print this? do something else
|
|
|
|
|
return UINT32_MAX;
|
|
|
|
|
}
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (retval >= 0)
|
|
|
|
|
return (uint32_t)retval;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return UINT32_MAX;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPython_UpdateSynthProviderInstance(PyObject *
|
|
|
|
|
implementor) {
|
|
|
|
|
bool ret_val = false;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
static char callee_name[] = "update";
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *py_return =
|
|
|
|
|
LLDBSwigPython_CallOptionalMember(implementor, callee_name);
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (py_return == Py_True)
|
|
|
|
|
ret_val = true;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
Py_XDECREF(py_return);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return ret_val;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPython_MightHaveChildrenSynthProviderInstance(
|
|
|
|
|
PyObject * implementor) {
|
|
|
|
|
bool ret_val = false;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
static char callee_name[] = "has_children";
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *py_return =
|
|
|
|
|
LLDBSwigPython_CallOptionalMember(implementor, callee_name, Py_True);
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (py_return == Py_True)
|
|
|
|
|
ret_val = true;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
Py_XDECREF(py_return);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return ret_val;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *lldb_private::LLDBSwigPython_GetValueSynthProviderInstance(
|
|
|
|
|
PyObject * implementor) {
|
|
|
|
|
PyObject *ret_val = nullptr;
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
static char callee_name[] = "get_value";
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *py_return =
|
|
|
|
|
LLDBSwigPython_CallOptionalMember(implementor, callee_name, Py_None);
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (py_return == Py_None || py_return == nullptr)
|
|
|
|
|
ret_val = nullptr;
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb::SBValue *sbvalue_ptr = NULL;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (SWIG_ConvertPtr(py_return, (void **)&sbvalue_ptr,
|
|
|
|
|
SWIGTYPE_p_lldb__SBValue, 0) == -1)
|
|
|
|
|
ret_val = nullptr;
|
|
|
|
|
else if (sbvalue_ptr == NULL)
|
|
|
|
|
ret_val = nullptr;
|
|
|
|
|
else
|
|
|
|
|
ret_val = py_return;
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
Py_XDECREF(py_return);
|
|
|
|
|
return ret_val;
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 18:27:36 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(PyObject * data) {
|
|
|
|
|
lldb::SBData *sb_ptr = nullptr;
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0);
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return sb_ptr;
|
2021-03-23 16:22:18 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-25 15:03:15 -07:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject * data) {
|
|
|
|
|
lldb::SBBreakpoint *sb_ptr = nullptr;
|
|
|
|
|
|
|
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBBreakpoint, 0);
|
|
|
|
|
|
|
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return sb_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-03 15:17:59 -08:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject * data) {
|
|
|
|
|
lldb::SBAttachInfo *sb_ptr = nullptr;
|
|
|
|
|
|
|
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBAttachInfo, 0);
|
|
|
|
|
|
|
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return sb_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject * data) {
|
|
|
|
|
lldb::SBLaunchInfo *sb_ptr = nullptr;
|
|
|
|
|
|
|
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBLaunchInfo, 0);
|
|
|
|
|
|
|
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return sb_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data) {
|
|
|
|
|
lldb::SBError *sb_ptr = nullptr;
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0);
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return sb_ptr;
|
2021-03-23 16:22:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) {
|
|
|
|
|
lldb::SBValue *sb_ptr = NULL;
|
2021-03-23 16:22:18 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
int valid_cast =
|
|
|
|
|
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0);
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return sb_ptr;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
void *lldb_private::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *
|
|
|
|
|
data) {
|
|
|
|
|
lldb::SBMemoryRegionInfo *sb_ptr = NULL;
|
[lldb/Plugins] Add memory region support in ScriptedProcess
This patch adds support for memory regions in Scripted Processes.
This is necessary to read the stack memory region in order to
reconstruct each stackframe of the program.
In order to do so, this patch makes some changes to the SBAPI, namely:
- Add a new constructor for `SBMemoryRegionInfo` that takes arguments
such as the memory region name, address range, permissions ...
This is used when reading memory at some address to compute the offset
in the binary blob provided by the user.
- Add a `GetMemoryRegionContainingAddress` method to `SBMemoryRegionInfoList`
to simplify the access to a specific memory region.
With these changes, lldb is now able to unwind the stack and reconstruct
each frame. On top of that, reloading the target module at offset 0 allows
lldb to symbolicate the `ScriptedProcess` using debug info, similarly to an
ordinary Process.
To test this, I wrote a simple program with multiple function calls, ran it in
lldb, stopped at a leaf function and read the registers values and copied
the stack memory into a binary file. These are then used in the python script.
Differential Revision: https://reviews.llvm.org/D108953
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
2021-10-08 12:25:04 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr,
|
|
|
|
|
SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0);
|
[lldb/Plugins] Add memory region support in ScriptedProcess
This patch adds support for memory regions in Scripted Processes.
This is necessary to read the stack memory region in order to
reconstruct each stackframe of the program.
In order to do so, this patch makes some changes to the SBAPI, namely:
- Add a new constructor for `SBMemoryRegionInfo` that takes arguments
such as the memory region name, address range, permissions ...
This is used when reading memory at some address to compute the offset
in the binary blob provided by the user.
- Add a `GetMemoryRegionContainingAddress` method to `SBMemoryRegionInfoList`
to simplify the access to a specific memory region.
With these changes, lldb is now able to unwind the stack and reconstruct
each frame. On top of that, reloading the target module at offset 0 allows
lldb to symbolicate the `ScriptedProcess` using debug info, similarly to an
ordinary Process.
To test this, I wrote a simple program with multiple function calls, ran it in
lldb, stopped at a leaf function and read the registers values and copied
the stack memory into a binary file. These are then used in the python script.
Differential Revision: https://reviews.llvm.org/D108953
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
2021-10-08 12:25:04 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (valid_cast == -1)
|
|
|
|
|
return NULL;
|
[lldb/Plugins] Add memory region support in ScriptedProcess
This patch adds support for memory regions in Scripted Processes.
This is necessary to read the stack memory region in order to
reconstruct each stackframe of the program.
In order to do so, this patch makes some changes to the SBAPI, namely:
- Add a new constructor for `SBMemoryRegionInfo` that takes arguments
such as the memory region name, address range, permissions ...
This is used when reading memory at some address to compute the offset
in the binary blob provided by the user.
- Add a `GetMemoryRegionContainingAddress` method to `SBMemoryRegionInfoList`
to simplify the access to a specific memory region.
With these changes, lldb is now able to unwind the stack and reconstruct
each frame. On top of that, reloading the target module at offset 0 allows
lldb to symbolicate the `ScriptedProcess` using debug info, similarly to an
ordinary Process.
To test this, I wrote a simple program with multiple function calls, ran it in
lldb, stopped at a leaf function and read the registers values and copied
the stack memory into a binary file. These are then used in the python script.
Differential Revision: https://reviews.llvm.org/D108953
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
2021-10-08 12:25:04 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return sb_ptr;
|
[lldb/Plugins] Add memory region support in ScriptedProcess
This patch adds support for memory regions in Scripted Processes.
This is necessary to read the stack memory region in order to
reconstruct each stackframe of the program.
In order to do so, this patch makes some changes to the SBAPI, namely:
- Add a new constructor for `SBMemoryRegionInfo` that takes arguments
such as the memory region name, address range, permissions ...
This is used when reading memory at some address to compute the offset
in the binary blob provided by the user.
- Add a `GetMemoryRegionContainingAddress` method to `SBMemoryRegionInfoList`
to simplify the access to a specific memory region.
With these changes, lldb is now able to unwind the stack and reconstruct
each frame. On top of that, reloading the target module at offset 0 allows
lldb to symbolicate the `ScriptedProcess` using debug info, similarly to an
ordinary Process.
To test this, I wrote a simple program with multiple function calls, ran it in
lldb, stopped at a leaf function and read the registers values and copied
the stack memory into a binary file. These are then used in the python script.
Differential Revision: https://reviews.llvm.org/D108953
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
2021-10-08 12:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonCallCommand(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
2021-11-18 08:11:34 +01:00
|
|
|
lldb::DebuggerSP debugger, const char *args,
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb_private::CommandReturnObject &cmd_retobj,
|
|
|
|
|
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {
|
|
|
|
|
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
|
|
|
|
|
|
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto argc = pfunc.GetArgInfo();
|
|
|
|
|
if (!argc) {
|
|
|
|
|
llvm::consumeError(argc.takeError());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-11-18 08:11:34 +01:00
|
|
|
PythonObject debugger_arg = ToSWIGWrapper(std::move(debugger));
|
2021-12-20 14:36:27 +01:00
|
|
|
auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj);
|
2021-12-14 17:20:23 +01:00
|
|
|
|
|
|
|
|
if (argc.get().max_positional_args < 5u)
|
2021-12-20 14:36:27 +01:00
|
|
|
pfunc(debugger_arg, PythonString(args), cmd_retobj_arg.obj(), dict);
|
2021-12-14 17:20:23 +01:00
|
|
|
else
|
2021-12-17 13:02:21 +01:00
|
|
|
pfunc(debugger_arg, PythonString(args),
|
2021-12-20 14:36:27 +01:00
|
|
|
ToSWIGWrapper(std::move(exe_ctx_ref_sp)), cmd_retobj_arg.obj(), dict);
|
2021-12-14 17:20:23 +01:00
|
|
|
|
|
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonCallCommandObject(
|
2021-11-18 08:11:34 +01:00
|
|
|
PyObject *implementor, lldb::DebuggerSP debugger, const char *args,
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb_private::CommandReturnObject &cmd_retobj,
|
|
|
|
|
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {
|
2015-03-13 02:20:41 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonObject self(PyRefType::Borrowed, implementor);
|
|
|
|
|
auto pfunc = self.ResolveName<PythonCallable>("__call__");
|
2015-03-13 02:20:41 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-13 02:20:41 +00:00
|
|
|
|
2021-12-20 14:36:27 +01:00
|
|
|
auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-17 13:02:21 +01:00
|
|
|
pfunc(ToSWIGWrapper(std::move(debugger)), PythonString(args),
|
2021-12-20 14:36:27 +01:00
|
|
|
ToSWIGWrapper(exe_ctx_ref_sp), cmd_retobj_arg.obj());
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return true;
|
2015-03-13 02:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSWIGPythonCreateOSPlugin(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::ProcessSP &process_sp) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
return pfunc(ToSWIGWrapper(process_sp));
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
PythonObject lldb_private::LLDBSWIGPython_CreateFrameRecognizer(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_class_name, const char *session_dictionary_name) {
|
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_class_name, dict);
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-01-17 11:29:35 +01:00
|
|
|
return PythonObject();
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2022-01-17 11:29:35 +01:00
|
|
|
return pfunc();
|
2018-10-31 04:00:22 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyObject *lldb_private::LLDBSwigPython_GetRecognizedArguments(
|
|
|
|
|
PyObject * implementor, const lldb::StackFrameSP &frame_sp) {
|
|
|
|
|
static char callee_name[] = "get_recognized_arguments";
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
PythonObject arg = ToSWIGWrapper(frame_sp);
|
2018-10-31 04:00:22 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PythonString str(callee_name);
|
|
|
|
|
PyObject *result =
|
2021-12-20 09:57:29 +01:00
|
|
|
PyObject_CallMethodObjArgs(implementor, str.get(), arg.get(), NULL);
|
2021-12-14 17:20:23 +01:00
|
|
|
return result;
|
2018-10-31 04:00:22 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
void *lldb_private::LLDBSWIGPython_GetDynamicSetting(
|
|
|
|
|
void *module, const char *setting, const lldb::TargetSP &target_sp) {
|
|
|
|
|
if (!module || !setting)
|
|
|
|
|
Py_RETURN_NONE;
|
2013-10-14 21:39:38 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
|
PythonObject py_module(PyRefType::Borrowed, (PyObject *)module);
|
|
|
|
|
auto pfunc = py_module.ResolveName<PythonCallable>("get_dynamic_setting");
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
Py_RETURN_NONE;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(target_sp), PythonString(setting));
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return result.release();
|
2013-10-14 21:39:38 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-22 16:32:44 +01:00
|
|
|
bool lldb_private::LLDBSWIGPythonRunScriptKeywordProcess(
|
[lldb] Fix [some] leaks in python bindings
Using an lldb_private object in the bindings involves three steps
- wrapping the object in it's lldb::SB variant
- using swig to convert/wrap that to a PyObject
- wrapping *that* in a lldb_private::python::PythonObject
Our SBTypeToSWIGWrapper was only handling the middle part. This doesn't
just result in increased boilerplate in the callers, but is also a
functionality problem, as it's very hard to get the lifetime of of all
of these objects right. Most of the callers are creating the SB object
(step 1) on the stack, which means that we end up with dangling python
objects after the function terminates. Most of the time this isn't a
problem, because the python code does not need to persist the objects.
However, there are legitimate cases where they can do it (and even if
the use case is not completely legitimate, crashing is not the best
response to that).
For this reason, some of our code creates the SB object on the heap, but
it has another problem -- it never gets cleaned up.
This patch begins to add a new function (ToSWIGWrapper), which does all
of the three steps, while properly taking care of ownership. In the
first step, I have converted most of the leaky code (except for
SBStructuredData, which needs a bit more work).
Differential Revision: https://reviews.llvm.org/D114259
2021-11-18 21:27:27 +01:00
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::ProcessSP &process, std::string &output) {
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
|
|
|
|
return false;
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(process), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
output = result.Str().GetString().str();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
std::optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordThread(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
2021-11-18 08:11:34 +01:00
|
|
|
lldb::ThreadSP thread) {
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-12-05 22:43:53 -08:00
|
|
|
return std::nullopt;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-12-05 22:43:53 -08:00
|
|
|
return std::nullopt;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(std::move(thread)), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
return result.Str().GetString().str();
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-22 16:32:44 +01:00
|
|
|
bool lldb_private::LLDBSWIGPythonRunScriptKeywordTarget(
|
[lldb] Fix [some] leaks in python bindings
Using an lldb_private object in the bindings involves three steps
- wrapping the object in it's lldb::SB variant
- using swig to convert/wrap that to a PyObject
- wrapping *that* in a lldb_private::python::PythonObject
Our SBTypeToSWIGWrapper was only handling the middle part. This doesn't
just result in increased boilerplate in the callers, but is also a
functionality problem, as it's very hard to get the lifetime of of all
of these objects right. Most of the callers are creating the SB object
(step 1) on the stack, which means that we end up with dangling python
objects after the function terminates. Most of the time this isn't a
problem, because the python code does not need to persist the objects.
However, there are legitimate cases where they can do it (and even if
the use case is not completely legitimate, crashing is not the best
response to that).
For this reason, some of our code creates the SB object on the heap, but
it has another problem -- it never gets cleaned up.
This patch begins to add a new function (ToSWIGWrapper), which does all
of the three steps, while properly taking care of ownership. In the
first step, I have converted most of the leaky code (except for
SBStructuredData, which needs a bit more work).
Differential Revision: https://reviews.llvm.org/D114259
2021-11-18 21:27:27 +01:00
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::TargetSP &target, std::string &output) {
|
2013-09-25 10:37:32 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(target), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
output = result.Str().GetString().str();
|
2015-11-13 01:24:25 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
std::optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordFrame(
|
2021-12-14 17:20:23 +01:00
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
2021-11-18 08:11:34 +01:00
|
|
|
lldb::StackFrameSP frame) {
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
2022-12-05 22:43:53 -08:00
|
|
|
return std::nullopt;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
2022-12-05 22:43:53 -08:00
|
|
|
return std::nullopt;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(std::move(frame)), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
return result.Str().GetString().str();
|
2014-10-28 21:07:00 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-22 16:32:44 +01:00
|
|
|
bool lldb_private::LLDBSWIGPythonRunScriptKeywordValue(
|
[lldb] Fix [some] leaks in python bindings
Using an lldb_private object in the bindings involves three steps
- wrapping the object in it's lldb::SB variant
- using swig to convert/wrap that to a PyObject
- wrapping *that* in a lldb_private::python::PythonObject
Our SBTypeToSWIGWrapper was only handling the middle part. This doesn't
just result in increased boilerplate in the callers, but is also a
functionality problem, as it's very hard to get the lifetime of of all
of these objects right. Most of the callers are creating the SB object
(step 1) on the stack, which means that we end up with dangling python
objects after the function terminates. Most of the time this isn't a
problem, because the python code does not need to persist the objects.
However, there are legitimate cases where they can do it (and even if
the use case is not completely legitimate, crashing is not the best
response to that).
For this reason, some of our code creates the SB object on the heap, but
it has another problem -- it never gets cleaned up.
This patch begins to add a new function (ToSWIGWrapper), which does all
of the three steps, while properly taking care of ownership. In the
first step, I have converted most of the leaky code (except for
SBStructuredData, which needs a bit more work).
Differential Revision: https://reviews.llvm.org/D114259
2021-11-18 21:27:27 +01:00
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::ValueObjectSP &value, std::string &output) {
|
2014-10-28 21:07:00 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' ||
|
|
|
|
|
!session_dictionary_name)
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return false;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto result = pfunc(ToSWIGWrapper(value), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
output = result.Str().GetString().str();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
bool lldb_private::LLDBSwigPythonCallModuleInit(
|
|
|
|
|
const char *python_module_name, const char *session_dictionary_name,
|
2021-11-18 08:11:34 +01:00
|
|
|
lldb::DebuggerSP debugger) {
|
2021-12-14 17:20:23 +01:00
|
|
|
std::string python_function_name_string = python_module_name;
|
|
|
|
|
python_function_name_string += ".__lldb_init_module";
|
|
|
|
|
const char *python_function_name = python_function_name_string.c_str();
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
|
|
|
|
session_dictionary_name);
|
|
|
|
|
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
|
|
|
|
python_function_name, dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
// This method is optional and need not exist. So if we don't find it,
|
|
|
|
|
// it's actually a success, not a failure.
|
|
|
|
|
if (!pfunc.IsAllocated())
|
|
|
|
|
return true;
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-11-18 08:11:34 +01:00
|
|
|
pfunc(ToSWIGWrapper(std::move(debugger)), dict);
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
return true;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
2015-03-14 08:06:56 +00:00
|
|
|
|
2021-12-14 17:20:23 +01:00
|
|
|
lldb::ValueObjectSP lldb_private::LLDBSWIGPython_GetValueObjectSPFromSBValue(
|
|
|
|
|
void *data) {
|
|
|
|
|
lldb::ValueObjectSP valobj_sp;
|
|
|
|
|
if (data) {
|
|
|
|
|
lldb::SBValue *sb_ptr = (lldb::SBValue *)data;
|
|
|
|
|
valobj_sp = sb_ptr->GetSP();
|
|
|
|
|
}
|
|
|
|
|
return valobj_sp;
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For the LogOutputCallback functions
|
2021-12-14 17:20:23 +01:00
|
|
|
static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str,
|
|
|
|
|
void *baton) {
|
|
|
|
|
if (baton != Py_None) {
|
|
|
|
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
|
|
|
PyObject *result = PyObject_CallFunction(
|
|
|
|
|
reinterpret_cast<PyObject *>(baton), const_cast<char *>("s"), str);
|
|
|
|
|
Py_XDECREF(result);
|
|
|
|
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
|
|
|
|
}
|
2013-09-25 10:37:32 +00:00
|
|
|
}
|
2023-02-03 17:09:09 -08:00
|
|
|
|
|
|
|
|
// For DebuggerTerminateCallback functions
|
|
|
|
|
static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id,
|
|
|
|
|
void *baton) {
|
|
|
|
|
if (baton != Py_None) {
|
|
|
|
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
|
|
|
PyObject *result = PyObject_CallFunction(
|
|
|
|
|
reinterpret_cast<PyObject *>(baton), const_cast<char *>("l"), debugger_id);
|
|
|
|
|
Py_XDECREF(result);
|
|
|
|
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-25 10:37:32 +00:00
|
|
|
%}
|