mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
Add the ability to write target stop-hooks using the ScriptInterpreter.
Differential Revision: https://reviews.llvm.org/D88123
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user