[lldb] Introduce StackFrameRecognizer [take 2]

This patch introduces a concept of "frame recognizer" and "recognized frame". This should be an extensible mechanism that retrieves information about special frames based on ABI, arguments or other special properties of that frame, even without source code. A few examples where that could be useful could be 1) objc_exception_throw, where we'd like to get the current exception, 2) terminate_with_reason and extracting the current terminate string, 3) recognizing Objective-C frames and automatically extracting the receiver+selector, or perhaps all arguments (based on selector).

Differential Revision: https://reviews.llvm.org/D44603

llvm-svn: 345686
This commit is contained in:
Kuba Mracek
2018-10-31 00:36:20 +00:00
parent 3e27306565
commit 8fddd98185
24 changed files with 1162 additions and 16 deletions

View File

@@ -27,6 +27,7 @@
#include <string>
#include "lldb/API/SBValue.h"
#include "lldb/API/SBFrame.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
@@ -91,6 +92,10 @@ static ScriptInterpreterPython::SWIGPythonCallModuleInit
g_swig_call_module_init = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateOSPlugin
g_swig_create_os_plugin = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateFrameRecognizer
g_swig_create_frame_recognizer = nullptr;
static ScriptInterpreterPython::SWIGPythonGetRecognizedArguments
g_swig_get_recognized_arguments = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process
g_swig_run_script_keyword_process = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread
@@ -1498,6 +1503,61 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
return true;
}
StructuredData::GenericSP ScriptInterpreterPython::CreateFrameRecognizer(
const char *class_name) {
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::GenericSP();
void *ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
ret_val =
g_swig_create_frame_recognizer(class_name, m_dictionary_name.c_str());
}
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
}
lldb::ValueObjectListSP ScriptInterpreterPython::GetRecognizedArguments(
const StructuredData::ObjectSP &os_plugin_object_sp,
lldb::StackFrameSP frame_sp) {
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
if (!os_plugin_object_sp) return ValueObjectListSP();
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic) return nullptr;
PythonObject implementor(PyRefType::Borrowed,
(PyObject *)generic->GetValue());
if (!implementor.IsAllocated()) return ValueObjectListSP();
PythonObject py_return(
PyRefType::Owned,
(PyObject *)g_swig_get_recognized_arguments(implementor.get(), frame_sp));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
}
if (py_return.get()) {
PythonList result_list(PyRefType::Borrowed, py_return.get());
ValueObjectListSP result = ValueObjectListSP(new ValueObjectList());
for (int i = 0; i < result_list.GetSize(); i++) {
PyObject *item = result_list.GetItemAtIndex(i).get();
lldb::SBValue *sb_value_ptr =
(lldb::SBValue *)g_swig_cast_to_sbvalue(item);
if (sb_value_ptr->IsValid()) result->Append(sb_value_ptr->GetSP());
}
return result;
}
return ValueObjectListSP();
}
StructuredData::GenericSP ScriptInterpreterPython::OSPlugin_CreatePluginObject(
const char *class_name, lldb::ProcessSP process_sp) {
if (class_name == nullptr || class_name[0] == '\0')
@@ -3185,6 +3245,8 @@ void ScriptInterpreterPython::InitializeInterpreter(
SWIGPythonCallCommandObject swig_call_command_object,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
SWIGPythonCreateFrameRecognizer swig_create_frame_recognizer,
SWIGPythonGetRecognizedArguments swig_get_recognized_arguments,
SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
@@ -3213,6 +3275,8 @@ void ScriptInterpreterPython::InitializeInterpreter(
g_swig_call_command_object = swig_call_command_object;
g_swig_call_module_init = swig_call_module_init;
g_swig_create_os_plugin = swig_create_os_plugin;
g_swig_create_frame_recognizer = swig_create_frame_recognizer;
g_swig_get_recognized_arguments = swig_get_recognized_arguments;
g_swig_run_script_keyword_process = swig_run_script_keyword_process;
g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
g_swig_run_script_keyword_target = swig_run_script_keyword_target;