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

Differential Revision: https://reviews.llvm.org/D88123
This commit is contained in:
Jim Ingham
2020-09-22 15:55:18 -07:00
parent 58cdbf518b
commit b65966cff6
19 changed files with 907 additions and 131 deletions

View File

@@ -468,6 +468,123 @@ 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()) {
if ((*args_info).max_positional_args < 2) {
error.SetErrorStringWithFormat("Wrong number of args for "
"handle_stop callback, should be 2 (excluding self), got: %d",
(*args_info).max_positional_args);
} else
return result.release();
} else {
error.SetErrorString("Couldn't get num arguments for handle_stop "
"callback.");
}
return result.release();
}
else {
error.SetErrorStringWithFormat("Class \"%s\" is missing the required "
"handle_stop callback.");
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