diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBCommandInterpreter.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectCommands.cpp | 73 | ||||
-rw-r--r-- | lldb/source/Host/common/FileSpec.cpp | 31 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreter.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 133 |
5 files changed, 232 insertions, 21 deletions
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 8a15423c324..ec2653d909e 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -358,6 +358,13 @@ extern "C" bool LLDBSwigPythonCallCommand lldb_private::CommandReturnObject& cmd_retobj ); +extern "C" bool LLDBSwigPythonCallModuleInit +( + const std::string python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger +); + extern "C" void init_lldb(void); @@ -377,6 +384,7 @@ SBCommandInterpreter::InitializeSWIG () LLDBSwigPython_GetIndexOfChildWithName, LLDBSWIGPython_CastPyObjectToSBValue, LLDBSwigPython_UpdateSynthProviderInstance, - LLDBSwigPythonCallCommand); + LLDBSwigPythonCallCommand, + LLDBSwigPythonCallModuleInit); } } diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index da0af986247..ba81f28ef2e 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1220,6 +1220,78 @@ public: }; +//------------------------------------------------------------------------- +// CommandObjectCommandsScriptImport +//------------------------------------------------------------------------- + +class CommandObjectCommandsScriptImport : public CommandObject +{ +public: + CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : + CommandObject (interpreter, + "command script import", + "Import a scripting module in LLDB.", + NULL) + { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; + + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypePath; + cmd_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg1); + } + + ~CommandObjectCommandsScriptImport () + { + } + + bool + Execute + ( + Args& args, + CommandReturnObject &result + ) + { + + if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) + { + result.AppendError ("only scripting language supported for module importing is currently Python"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + size_t argc = args.GetArgumentCount(); + + if (argc != 1) + { + result.AppendError ("'command script import' requires one argument"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + std::string path = args.GetArgumentAtIndex(0); + Error error; + + if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), + error)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + + return result.Succeeded(); + } +}; //------------------------------------------------------------------------- // CommandObjectCommandsScriptAdd @@ -1684,6 +1756,7 @@ public: LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); + LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); } ~CommandObjectMultiwordCommandsScript () diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 5e034db6571..35e12ebdb57 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -699,10 +699,39 @@ FileSpec::GetPath(char *path, size_t path_max_len) const return ::snprintf (path, path_max_len, "%s", filename); } } - path[0] = '\0'; + if (path) + path[0] = '\0'; return 0; } +ConstString +FileSpec::GetFileNameExtension () const +{ + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + char* dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return ConstString(); + + return ConstString(dot_pos+1); +} + +ConstString +FileSpec::GetFileNameStrippingExtension () const +{ + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + char* dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return m_filename; + + return ConstString(filename, dot_pos-filename); +} + //------------------------------------------------------------------ // Returns a shared pointer to a data buffer that contains all or // part of the contents of a file. The data is memory mapped and diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 27bbb67605e..e125d657c33 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -100,7 +100,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command) + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, python_swig_breakpoint_callback, @@ -111,7 +112,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call python_swig_get_index_child, python_swig_cast_to_sbvalue, python_swig_update_provider, - python_swig_call_command); + python_swig_call_command, + python_swig_call_mod_init); } void diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 634f76d60f6..f1f4a3255a3 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -42,6 +42,7 @@ static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_chi static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL; static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL; static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL; +static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL; static int _check_and_flush (FILE *stream) @@ -199,6 +200,10 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete PyRun_SimpleString (run_string.GetData()); run_string.Clear(); + run_string.Printf ("run_one_line (%s, 'import os')", m_dictionary_name.c_str()); + PyRun_SimpleString (run_string.GetData()); + + run_string.Clear(); run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %d')", m_dictionary_name.c_str(), interpreter.GetDebugger().GetID()); PyRun_SimpleString (run_string.GetData()); @@ -702,7 +707,7 @@ ScriptInterpreterPython::ExecuteInterpreterLoop () bool ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ReturnType return_type, + ScriptInterpreter::ScriptReturnType return_type, void *ret_value) { @@ -783,85 +788,85 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, { switch (return_type) { - case eCharPtr: // "char *" + case eScriptReturnTypeCharPtr: // "char *" { const char format[3] = "s#"; success = PyArg_Parse (py_return, format, (char **) ret_value); break; } - case eCharStrOrNone: // char* or NULL if py_return == Py_None + case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None { const char format[3] = "z"; success = PyArg_Parse (py_return, format, (char **) ret_value); break; } - case eBool: + case eScriptReturnTypeBool: { const char format[2] = "b"; success = PyArg_Parse (py_return, format, (bool *) ret_value); break; } - case eShortInt: + case eScriptReturnTypeShortInt: { const char format[2] = "h"; success = PyArg_Parse (py_return, format, (short *) ret_value); break; } - case eShortIntUnsigned: + case eScriptReturnTypeShortIntUnsigned: { const char format[2] = "H"; success = PyArg_Parse (py_return, format, (unsigned short *) ret_value); break; } - case eInt: + case eScriptReturnTypeInt: { const char format[2] = "i"; success = PyArg_Parse (py_return, format, (int *) ret_value); break; } - case eIntUnsigned: + case eScriptReturnTypeIntUnsigned: { const char format[2] = "I"; success = PyArg_Parse (py_return, format, (unsigned int *) ret_value); break; } - case eLongInt: + case eScriptReturnTypeLongInt: { const char format[2] = "l"; success = PyArg_Parse (py_return, format, (long *) ret_value); break; } - case eLongIntUnsigned: + case eScriptReturnTypeLongIntUnsigned: { const char format[2] = "k"; success = PyArg_Parse (py_return, format, (unsigned long *) ret_value); break; } - case eLongLong: + case eScriptReturnTypeLongLong: { const char format[2] = "L"; success = PyArg_Parse (py_return, format, (long long *) ret_value); break; } - case eLongLongUnsigned: + case eScriptReturnTypeLongLongUnsigned: { const char format[2] = "K"; success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value); break; } - case eFloat: + case eScriptReturnTypeFloat: { const char format[2] = "f"; success = PyArg_Parse (py_return, format, (float *) ret_value); break; } - case eDouble: + case eScriptReturnTypeDouble: { const char format[2] = "d"; success = PyArg_Parse (py_return, format, (double *) ret_value); break; } - case eChar: + case eScriptReturnTypeChar: { const char format[2] = "c"; success = PyArg_Parse (py_return, format, (char *) ret_value); @@ -1825,6 +1830,98 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) } bool +ScriptInterpreterPython::LoadScriptingModule (const char* pathname, + lldb_private::Error& error) +{ + if (!pathname || !pathname[0]) + { + error.SetErrorString("invalid pathname"); + return false; + } + + if (!g_swig_call_module_init) + { + error.SetErrorString("internal helper function missing"); + return false; + } + + ScriptInterpreterPython *python_interpreter = this; + + lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().GetSP(); + + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + + { + Locker py_lock(python_interpreter, tmp_fh); + + FileSpec target_file(pathname, true); + + // TODO: would we want to reject any other value? + if (target_file.GetFileType() == FileSpec::eFileTypeInvalid || + target_file.GetFileType() == FileSpec::eFileTypeUnknown) + { + error.SetErrorString("invalid pathname"); + return false; + } + + const char* directory = target_file.GetDirectory().GetCString(); + std::string basename(target_file.GetFilename().GetCString()); + + // now make sure that Python has "directory" in the search path + StreamString command_stream; + command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.append('%s');\n\n", + directory, + directory); + bool syspath_retval = python_interpreter->ExecuteMultipleLines(command_stream.GetData()); + if (!syspath_retval) + { + error.SetErrorString("Python sys.path handling failed"); + return false; + } + + // strip .py or .pyc extension + ConstString extension = target_file.GetFileNameExtension(); + if (::strcmp(extension.GetCString(), "py") == 0) + basename.resize(basename.length()-3); + else if(::strcmp(extension.GetCString(), "pyc") == 0) + basename.resize(basename.length()-4); + + // check if the module is already import-ed + command_stream.Clear(); + command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); + int refcount = 0; + // this call will fail if the module does not exist (because the parameter to it is not a string + // but an actual Python module object, which is non-existant if the module was not imported before) + if (python_interpreter->ExecuteOneLineWithReturn(command_stream.GetData(), + ScriptInterpreterPython::eScriptReturnTypeInt, &refcount) && refcount > 0) + { + error.SetErrorString("module already imported"); + return false; + } + + // now actually do the import + command_stream.Clear(); + command_stream.Printf("import %s",basename.c_str()); + bool import_retval = python_interpreter->ExecuteOneLine(command_stream.GetData(), NULL); + if (!import_retval) + { + error.SetErrorString("Python import statement failed"); + return false; + } + + // call __lldb_module_init(debugger,dict) + if (!g_swig_call_module_init (basename, + python_interpreter->m_dictionary_name.c_str(), + debugger_sp)) + { + error.SetErrorString("calling __lldb_module_init failed"); + return false; + } + return true; + } +} + +bool ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, lldb_private::CommandReturnObject& cmd_retobj, @@ -1886,7 +1983,7 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item) char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully if (ExecuteOneLineWithReturn (command.c_str(), - ScriptInterpreter::eCharStrOrNone, + ScriptInterpreter::eScriptReturnTypeCharStrOrNone, &result_ptr) && result_ptr) { return std::string(result_ptr); @@ -1905,7 +2002,8 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command) + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init) { g_swig_init_callback = python_swig_init_callback; g_swig_breakpoint_callback = python_swig_breakpoint_callback; @@ -1917,6 +2015,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue; g_swig_update_provider = python_swig_update_provider; g_swig_call_command = python_swig_call_command; + g_swig_call_module_init = python_swig_call_mod_init; } void |