Revert "Revert "Add the ability to write target stop-hooks using the ScriptInterpreter.""

This reverts commit f775fe5964.

I fixed a return type error in the original patch that was causing a test failure.
Also added a REQUIRES: python to the shell test so we'll skip this for
people who build lldb w/o Python.
Also added another test for the error printing.
This commit is contained in:
Jim Ingham
2020-09-28 10:28:29 -07:00
parent 962a247aeb
commit 1b1d981598
19 changed files with 942 additions and 131 deletions

View File

@@ -468,6 +468,127 @@ LLDBSwigPythonCallBreakpointResolver
return ret_val;
}
SWIGEXPORT void *
LLDBSwigPythonCreateScriptedStopHook
(
lldb::TargetSP target_sp,
const char *python_class_name,
const char *session_dictionary_name,
lldb_private::StructuredDataImpl *args_impl,
Status &error
)
{
if (python_class_name == NULL || python_class_name[0] == '\0') {
error.SetErrorString("Empty class name.");
Py_RETURN_NONE;
}
if (!session_dictionary_name) {
error.SetErrorString("No session dictionary");
Py_RETURN_NONE;
}
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);
return nullptr;
}
lldb::SBTarget *target_val
= new lldb::SBTarget(target_sp);
PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_val));
lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
PythonObject result = pfunc(target_arg, args_arg, 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 "
"handle_stop callback, should be 2 (excluding self), got: %d",
num_args);
Py_RETURN_NONE;
} else
return result.release();
} else {
error.SetErrorString("Couldn't get num arguments for handle_stop "
"callback.");
Py_RETURN_NONE;
}
return result.release();
}
else {
error.SetErrorStringWithFormat("Class \"%s\" is missing the required "
"handle_stop callback.",
python_class_name);
result.release();
}
}
Py_RETURN_NONE;
}
SWIGEXPORT bool
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.
PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
auto pfunc = self.ResolveName<PythonCallable>("handle_stop");
if (!pfunc.IsAllocated())
return true;
PythonObject result;
lldb::SBExecutionContext sb_exc_ctx(exc_ctx_sp);
PythonObject exc_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_exc_ctx));
lldb::SBStream sb_stream;
PythonObject sb_stream_arg(PyRefType::Owned,
SBTypeToSWIGWrapper(sb_stream));
result = pfunc(exc_ctx_arg, sb_stream_arg);
if (PyErr_Occurred())
{
stream->PutCString("Python error occurred handling stop-hook.");
PyErr_Print();
PyErr_Clear();
return true;
}
// 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.
stream->PutCString(sb_stream.GetData());
if (result.get() == Py_False)
return false;
else
return true;
}
// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember