From c0f8ca0e74f85241aafa8291f207ceb7e5dfe22b Mon Sep 17 00:00:00 2001 From: Enrico Granata Date: Mon, 14 Oct 2013 21:39:38 +0000 Subject: [PATCH] Add the capability for LLDB to query an arbitrary Python module (passed in as a file path) for target-specific settings This is implemented by means of a get_dynamic_setting(target, setting_name) function vended by the Python module, which can respond to arbitrary string names with dynamically constructed settings objects (most likely, some of those that PythonDataObjects supports) for LLDB to parse This needs to be hooked up to the debugger via some setting to allow users to specify which module will vend the information they want to supply llvm-svn: 192628 --- .../lldb/Interpreter/ScriptInterpreter.h | 24 ++++++- .../Interpreter/ScriptInterpreterPython.h | 15 +++- lldb/scripts/Python/python-wrapper.swig | 24 +++++++ .../Interpreter/ScriptInterpreterPython.cpp | 69 ++++++++++++++++++- 4 files changed, 126 insertions(+), 6 deletions(-) diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index b529b7b5f980..55e064df8504 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -145,8 +145,8 @@ public: const char* session_dictionary_name, lldb::StackFrameSP& frame, std::string& output); - + typedef void* (*SWIGPythonGDBPlugin_GetDynamicSetting) (void* module, const char* setting, const lldb::TargetSP& target_sp); typedef enum { @@ -163,7 +163,8 @@ public: eScriptReturnTypeFloat, eScriptReturnTypeDouble, eScriptReturnTypeChar, - eScriptReturnTypeCharStrOrNone + eScriptReturnTypeCharStrOrNone, + eScriptReturnTypeOpaqueObject } ScriptReturnType; ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang); @@ -337,6 +338,22 @@ public: { return lldb::ScriptInterpreterObjectSP(); } + + virtual lldb::ScriptInterpreterObjectSP + GDBRemotePlugin_LoadPluginModule (const FileSpec& file_spec, + lldb_private::Error& error) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + GDBRemotePlugin_GetDynamicSettings (lldb::ScriptInterpreterObjectSP gdbremote_plugin_module_sp, + Target* target, + const char* setting_name, + lldb_private::Error& error) + { + return lldb::ScriptInterpreterObjectSP(); + } virtual bool GenerateFunction(const char *signature, const StringList &input) @@ -474,7 +491,8 @@ public: LoadScriptingModule (const char* filename, bool can_reload, bool init_session, - lldb_private::Error& error) + lldb_private::Error& error, + lldb::ScriptInterpreterObjectSP* module_sp = nullptr) { error.SetErrorString("loading unimplemented"); return false; diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index 0a1ec10516e7..270f251e883f 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -98,6 +98,16 @@ public: lldb::tid_t tid, lldb::addr_t context); + virtual lldb::ScriptInterpreterObjectSP + GDBRemotePlugin_LoadPluginModule (const FileSpec& file_spec, + lldb_private::Error& error); + + virtual lldb::ScriptInterpreterObjectSP + GDBRemotePlugin_GetDynamicSettings (lldb::ScriptInterpreterObjectSP gdbremote_plugin_module_sp, + Target* target, + const char* setting_name, + lldb_private::Error& error); + virtual size_t CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor); @@ -200,7 +210,8 @@ public: LoadScriptingModule (const char* filename, bool can_reload, bool init_session, - lldb_private::Error& error); + lldb_private::Error& error, + lldb::ScriptInterpreterObjectSP* module_sp = nullptr); virtual lldb::ScriptInterpreterObjectSP MakeScriptObject (void* object); @@ -254,7 +265,7 @@ protected: void RestoreTerminalState (); - + private: class SynchronicityHandler diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index cd133cfa8a27..4ab27a9935e9 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -713,6 +713,30 @@ LLDBSWIGPythonCreateOSPlugin Py_RETURN_NONE; } +SWIGEXPORT void* +LLDBSWIGPython_GDBPluginGetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp) +{ + + if (!module || !setting) + Py_RETURN_NONE; + + lldb::SBTarget target_sb(target_sp); + + PyObject *pvalue = NULL; + + { + PyErr_Cleaner py_err_cleaner(true); + PyCallable pfunc = PyCallable::FindWithFunctionName("get_dynamic_setting",(PyObject *)module); + + if (!pfunc) + Py_RETURN_NONE; + + pvalue = pfunc(target_sb, setting); + } + + return pvalue; +} + SWIGEXPORT bool LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name, diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 73619371ba9d..f1c59a6f338f 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -62,6 +62,7 @@ static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyw static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL; static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL; static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL; +static ScriptInterpreter::SWIGPythonGDBPlugin_GetDynamicSetting g_swig_gdbremote_plugin_get = NULL; // these are the Pythonic implementations of the required callbacks // these are scripting-language specific, which is why they belong here @@ -155,6 +156,11 @@ LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name, lldb::StackFrameSP& frame, std::string& output); +extern "C" void* +LLDBSWIGPython_GDBPluginGetDynamicSetting (void* module, + const char* setting, + const lldb::TargetSP& target_sp); + static int _check_and_flush (FILE *stream) { @@ -1180,6 +1186,13 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, success = PyArg_Parse (py_return, format, (char *) ret_value); break; } + case eScriptReturnTypeOpaqueObject: + { + success = true; + Py_XINCREF(py_return); + *((PyObject**)ret_value) = py_return; + break; + } } Py_XDECREF (py_return); if (success) @@ -2067,6 +2080,47 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP return MakeScriptObject(py_return); } +lldb::ScriptInterpreterObjectSP +ScriptInterpreterPython::GDBRemotePlugin_LoadPluginModule (const FileSpec& file_spec, + lldb_private::Error& error) +{ + if (!file_spec.Exists()) + { + error.SetErrorString("no such file"); + return lldb::ScriptInterpreterObjectSP(); + } + + ScriptInterpreterObjectSP module_sp; + + if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp)) + return module_sp; + + return lldb::ScriptInterpreterObjectSP(); +} + +lldb::ScriptInterpreterObjectSP +ScriptInterpreterPython::GDBRemotePlugin_GetDynamicSettings (lldb::ScriptInterpreterObjectSP gdbremote_plugin_module_sp, + Target* target, + const char* setting_name, + lldb_private::Error& error) +{ + if (!gdbremote_plugin_module_sp || !target || !setting_name || !setting_name[0]) + return lldb::ScriptInterpreterObjectSP(); + + if (!g_swig_gdbremote_plugin_get) + return lldb::ScriptInterpreterObjectSP(); + + PyObject *reply_pyobj = nullptr; + + { + Locker py_lock(this); + TargetSP target_sp(target->shared_from_this()); + reply_pyobj = (PyObject*)g_swig_gdbremote_plugin_get(gdbremote_plugin_module_sp->GetObject(),setting_name,target_sp); + } + + return MakeScriptObject(reply_pyobj); +} + lldb::ScriptInterpreterObjectSP ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name, lldb::ValueObjectSP valobj) @@ -2751,7 +2805,8 @@ bool ScriptInterpreterPython::LoadScriptingModule (const char* pathname, bool can_reload, bool init_session, - lldb_private::Error& error) + lldb_private::Error& error, + lldb::ScriptInterpreterObjectSP* module_sp) { if (!pathname || !pathname[0]) { @@ -2916,6 +2971,17 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname, error.SetErrorString("calling __lldb_init_module failed"); return false; } + + if (module_sp) + { + // everything went just great, now set the module object + command_stream.Clear(); + command_stream.Printf("%s",basename.c_str()); + void* module_pyobj = nullptr; + if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj) + *module_sp = MakeScriptObject(module_pyobj); + } + return true; } } @@ -3070,6 +3136,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini g_swig_run_script_keyword_thread = LLDBSWIGPythonRunScriptKeywordThread; g_swig_run_script_keyword_target = LLDBSWIGPythonRunScriptKeywordTarget; g_swig_run_script_keyword_frame = LLDBSWIGPythonRunScriptKeywordFrame; + g_swig_gdbremote_plugin_get = LLDBSWIGPython_GDBPluginGetDynamicSetting; } void