diff options
Diffstat (limited to 'source/Interpreter')
-rw-r--r-- | source/Interpreter/Args.cpp | 47 | ||||
-rw-r--r-- | source/Interpreter/CommandInterpreter.cpp | 121 | ||||
-rw-r--r-- | source/Interpreter/CommandObject.cpp | 6 | ||||
-rw-r--r-- | source/Interpreter/CommandObjectScript.h | 14 | ||||
-rw-r--r-- | source/Interpreter/OptionGroupValueObjectDisplay.cpp | 2 | ||||
-rw-r--r-- | source/Interpreter/OptionValueLanguage.cpp | 29 | ||||
-rw-r--r-- | source/Interpreter/OptionValueProperties.cpp | 9 | ||||
-rw-r--r-- | source/Interpreter/Property.cpp | 4 | ||||
-rw-r--r-- | source/Interpreter/PythonDataObjects.cpp | 524 | ||||
-rw-r--r-- | source/Interpreter/ScriptInterpreterNone.cpp | 42 | ||||
-rw-r--r-- | source/Interpreter/ScriptInterpreterPython.cpp | 3194 | ||||
-rw-r--r-- | source/Interpreter/embedded_interpreter.py | 15 |
12 files changed, 145 insertions, 3862 deletions
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index 2258c26e6c39..81e6b0aa1dbc 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -371,7 +371,7 @@ char ** Args::GetArgumentVector() { if (!m_argv.empty()) - return (char **)&m_argv[0]; + return const_cast<char **>(&m_argv[0]); return nullptr; } @@ -379,7 +379,7 @@ const char ** Args::GetConstArgumentVector() const { if (!m_argv.empty()) - return (const char **)&m_argv[0]; + return const_cast<const char **>(&m_argv[0]); return nullptr; } @@ -575,7 +575,8 @@ Args::ParseOptions (Options &options) } } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); int val; while (1) { @@ -719,7 +720,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add else { // Since the compiler can't handle things like "main + 12" we should - // try to do this for now. The compliler doesn't like adding offsets + // try to do this for now. The compiler doesn't like adding offsets // to function pointer types. static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); RegularExpression::Match regex_match(3); @@ -1189,7 +1190,8 @@ Args::ParseAliasOptions (Options &options, } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); int val; while (1) { @@ -1366,7 +1368,8 @@ Args::ParseArgsForCompletion } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); OptionParser::EnableError(false); int val; @@ -1387,7 +1390,7 @@ Args::ParseArgsForCompletion int long_options_index = -1; val = OptionParser::Parse (dummy_vec.size() - 1, - (char *const *) &dummy_vec.front(), + const_cast<char *const *>(&dummy_vec.front()), sstr.GetData(), long_options, &long_options_index); @@ -1668,3 +1671,33 @@ Args::ExpandEscapedCharacters (const char *src, std::string &dst) } } +std::string +Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char) +{ + const char* chars_to_escape = nullptr; + switch (quote_char) + { + case '\0': + chars_to_escape = " \t\\'\"`"; + break; + case '\'': + chars_to_escape = ""; + break; + case '"': + chars_to_escape = "$\"`\\"; + break; + default: + assert(false && "Unhandled quote character"); + } + + std::string res; + res.reserve(arg.size()); + for (char c : arg) + { + if (::strchr(chars_to_escape, c)) + res.push_back('\\'); + res.push_back(c); + } + return res; +} + diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 1da541b8c00f..b7cc607e8070 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -41,9 +41,9 @@ #include "../Commands/CommandObjectWatchpoint.h" #include "../Commands/CommandObjectLanguage.h" - #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" @@ -62,8 +62,6 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" -#include "lldb/Interpreter/ScriptInterpreterNone.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Target/Process.h" @@ -87,6 +85,7 @@ g_properties[] = { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, + { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." }, { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr } }; @@ -94,7 +93,8 @@ enum { ePropertyExpandRegexAliases = 0, ePropertyPromptOnQuit = 1, - ePropertyStopCmdSourceOnError = 2 + ePropertyStopCmdSourceOnError = 2, + eSpaceReplPrompts = 3 }; ConstString & @@ -104,29 +104,23 @@ CommandInterpreter::GetStaticBroadcasterClass () return class_name; } -CommandInterpreter::CommandInterpreter -( - Debugger &debugger, - ScriptLanguage script_language, - bool synchronous_execution -) : - Broadcaster (&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), - Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), - IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand), - m_debugger (debugger), - m_synchronous_execution (synchronous_execution), - m_skip_lldbinit_files (false), - m_skip_app_init_files (false), - m_script_interpreter_ap (), - m_command_io_handler_sp (), - m_comment_char ('#'), - m_batch_command_mode (false), - m_truncation_warning(eNoTruncation), - m_command_source_depth (0), - m_num_errors(0), - m_quit_requested(false), - m_stopped_for_crash(false) - +CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution) + : Broadcaster(&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), + Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), + IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), + m_debugger(debugger), + m_synchronous_execution(synchronous_execution), + m_skip_lldbinit_files(false), + m_skip_app_init_files(false), + m_script_interpreter_sp(), + m_command_io_handler_sp(), + m_comment_char('#'), + m_batch_command_mode(false), + m_truncation_warning(eNoTruncation), + m_command_source_depth(0), + m_num_errors(0), + m_quit_requested(false), + m_stopped_for_crash(false) { debugger.SetScriptLanguage (script_language); SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); @@ -175,6 +169,13 @@ CommandInterpreter::GetStopCmdSourceOnError () const return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); } +bool +CommandInterpreter::GetSpaceReplPrompts () const +{ + const uint32_t idx = eSpaceReplPrompts; + return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); +} + void CommandInterpreter::Initialize () { @@ -360,11 +361,19 @@ CommandInterpreter::Initialize () #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); #else + #if defined(__APPLE__) + std::string shell_option; + shell_option.append("--shell-expand-args"); + shell_option.append(" true"); + shell_option.append(" --"); + ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); + #else std::string shell_option; shell_option.append("--shell="); shell_option.append(HostInfo::GetDefaultShell().GetPath()); shell_option.append(" --"); ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); + #endif #endif AddAlias ("r", cmd_obj_sp); AddAlias ("run", cmd_obj_sp); @@ -392,9 +401,9 @@ void CommandInterpreter::Clear() { m_command_io_handler_sp.reset(); - - if (m_script_interpreter_ap) - m_script_interpreter_ap->Clear(); + + if (m_script_interpreter_sp) + m_script_interpreter_sp->Clear(); } const char * @@ -511,8 +520,7 @@ CommandInterpreter::LoadCommandDictionary () char buffer[1024]; int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); assert (num_printed < 1024); - // Quiet unused variable warning for release builds. - (void) num_printed; + UNUSED_IF_ASSERT_DISABLED(num_printed); success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); if (!success) break; @@ -2011,7 +2019,7 @@ CommandInterpreter::HandleCompletion (const char *current_line, matches); if (num_command_matches <= 0) - return num_command_matches; + return num_command_matches; if (num_args == 0) { @@ -2030,18 +2038,18 @@ CommandInterpreter::HandleCompletion (const char *current_line, std::string common_prefix; matches.LongestCommonPrefix (common_prefix); const size_t partial_name_len = command_partial_str.size(); + common_prefix.erase (0, partial_name_len); // If we matched a unique single command, add a space... // Only do this if the completer told us this was a complete word, however... if (num_command_matches == 1 && word_complete) { char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); + common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); if (quote_char != '\0') common_prefix.push_back(quote_char); - common_prefix.push_back(' '); } - common_prefix.erase (0, partial_name_len); matches.InsertStringAtIndex(0, common_prefix.c_str()); } return num_command_matches; @@ -2709,48 +2717,19 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, } ScriptInterpreter * -CommandInterpreter::GetScriptInterpreter (bool can_create) +CommandInterpreter::GetScriptInterpreter(bool can_create) { - if (m_script_interpreter_ap.get() != nullptr) - return m_script_interpreter_ap.get(); - + if (m_script_interpreter_sp) + return m_script_interpreter_sp.get(); + if (!can_create) return nullptr; - - // <rdar://problem/11751427> - // we need to protect the initialization of the script interpreter - // otherwise we could end up with two threads both trying to create - // their instance of it, and for some languages (e.g. Python) - // this is a bulletproof recipe for disaster! - // this needs to be a function-level static because multiple Debugger instances living in the same process - // still need to be isolated and not try to initialize Python concurrently - static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive); - Mutex::Locker interpreter_lock(g_interpreter_mutex); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("Initializing the ScriptInterpreter now\n"); - + lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); - switch (script_lang) - { - case eScriptLanguagePython: -#ifndef LLDB_DISABLE_PYTHON - m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this)); - break; -#else - // Fall through to the None case when python is disabled -#endif - case eScriptLanguageNone: - m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this)); - break; - }; - - return m_script_interpreter_ap.get(); + m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); + return m_script_interpreter_sp.get(); } - - bool CommandInterpreter::GetSynchronous () { diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index c0efd9e33c08..616d3e38acbb 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -28,6 +28,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Language.h" + #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -395,7 +397,7 @@ CommandObject::HandleCompletion StringList &matches ) { - // Default implmentation of WantsCompletion() is !WantsRawCommandString(). + // Default implementation of WantsCompletion() is !WantsRawCommandString(). // Subclasses who want raw command string but desire, for example, // argument completion should override WantsCompletion() to return true, // instead. @@ -848,7 +850,7 @@ LanguageTypeHelpTextCallback () StreamString sstr; sstr << "One of the following languages:\n"; - LanguageRuntime::PrintAllLanguages(sstr, " ", "\n"); + Language::PrintAllLanguages(sstr, " ", "\n"); sstr.Flush(); diff --git a/source/Interpreter/CommandObjectScript.h b/source/Interpreter/CommandObjectScript.h index fd55fc44a46a..5365aaac4cbe 100644 --- a/source/Interpreter/CommandObjectScript.h +++ b/source/Interpreter/CommandObjectScript.h @@ -25,18 +25,16 @@ namespace lldb_private { class CommandObjectScript : public CommandObjectRaw { public: + CommandObjectScript(CommandInterpreter &interpreter, + lldb::ScriptLanguage script_lang); - CommandObjectScript (CommandInterpreter &interpreter, - lldb::ScriptLanguage script_lang); - - virtual - ~CommandObjectScript (); + ~CommandObjectScript() override; protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result); + bool + DoExecute(const char *command, CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectScript_h_ +#endif // liblldb_CommandObjectScript_h_ diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index e5a5c004b2da..bbd966859c34 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -162,7 +162,7 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl lldb::TypeSummaryImplSP summary_sp) { DumpValueObjectOptions options; - options.SetMaximumPointerDepth(ptr_depth); + options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Always,ptr_depth} ); if (use_objc) options.SetShowSummary(false); else diff --git a/source/Interpreter/OptionValueLanguage.cpp b/source/Interpreter/OptionValueLanguage.cpp index fd46553dabde..dd7173c3dc74 100644 --- a/source/Interpreter/OptionValueLanguage.cpp +++ b/source/Interpreter/OptionValueLanguage.cpp @@ -16,7 +16,7 @@ #include "lldb/Core/Stream.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; @@ -30,7 +30,7 @@ OptionValueLanguage::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, u { if (dump_mask & eDumpOptionType) strm.PutCString (" = "); - strm.PutCString (LanguageRuntime::GetNameForLanguageType(m_current_value)); + strm.PutCString (Language::GetNameForLanguageType(m_current_value)); } } @@ -47,9 +47,28 @@ OptionValueLanguage::SetValueFromString (llvm::StringRef value, VarSetOperationT case eVarSetOperationReplace: case eVarSetOperationAssign: { - LanguageType new_type = LanguageRuntime::GetLanguageTypeFromString(value.data()); - m_value_was_set = true; - m_current_value = new_type; + ConstString lang_name(value.trim()); + std::set<lldb::LanguageType> languages_for_types; + std::set<lldb::LanguageType> languages_for_expressions; + Language::GetLanguagesSupportingTypeSystems(languages_for_types, languages_for_expressions); + + LanguageType new_type = Language::GetLanguageTypeFromString(lang_name.GetCString()); + if (new_type && languages_for_types.count(new_type)) + { + m_value_was_set = true; + m_current_value = new_type; + } + else + { + StreamString error_strm; + error_strm.Printf("invalid language type '%s', ", value.str().c_str()); + error_strm.Printf("valid values are:\n"); + for (lldb::LanguageType language : languages_for_types) + { + error_strm.Printf("%s%s%s", " ", Language::GetNameForLanguageType(language), "\n"); + } + error.SetErrorString(error_strm.GetData()); + } } break; diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp index e8d870a99cf8..a3c28f70270f 100644 --- a/source/Interpreter/OptionValueProperties.cpp +++ b/source/Interpreter/OptionValueProperties.cpp @@ -311,6 +311,15 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionConte return nullptr; } +OptionValueLanguage * +OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const +{ + const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); + if (property) + return property->GetValue()->GetAsLanguage(); + return nullptr; +} + bool OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp index 077fcbc54cc3..b9fe28620a4f 100644 --- a/source/Interpreter/Property.cpp +++ b/source/Interpreter/Property.cpp @@ -17,7 +17,7 @@ #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValues.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; @@ -129,7 +129,7 @@ Property::Property (const PropertyDefinition &definition) : { LanguageType new_lang = eLanguageTypeUnknown; if (definition.default_cstr_value) - LanguageRuntime::GetLanguageTypeFromString(definition.default_cstr_value); + Language::GetLanguageTypeFromString(definition.default_cstr_value); else new_lang = (LanguageType)definition.default_uint_value; m_value_sp.reset (new OptionValueLanguage(new_lang)); diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp deleted file mode 100644 index a581a0b3601a..000000000000 --- a/source/Interpreter/PythonDataObjects.cpp +++ /dev/null @@ -1,524 +0,0 @@ -//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// In order to guarantee correct working with Python, Python.h *MUST* be -// the *FIRST* header file included here. -#ifdef LLDB_DISABLE_PYTHON - -// Python is disabled in this build - -#else - -#include "lldb/lldb-python.h" - -#include <stdio.h> - -#include "lldb/Core/Stream.h" -#include "lldb/Host/File.h" -#include "lldb/Interpreter/PythonDataObjects.h" -#include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" - -using namespace lldb_private; -using namespace lldb; - -void -StructuredPythonObject::Dump(Stream &s) const -{ - s << "Python Obj: 0x" << GetValue(); -} - -//---------------------------------------------------------------------- -// PythonObject -//---------------------------------------------------------------------- - -void -PythonObject::Dump (Stream &strm) const -{ - if (m_py_obj) - { - FILE *file = ::tmpfile(); - if (file) - { - ::PyObject_Print (m_py_obj, file, 0); - const long length = ftell (file); - if (length) - { - ::rewind(file); - std::vector<char> file_contents (length,'\0'); - const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); - if (length_read > 0) - strm.Write (file_contents.data(), length_read); - } - ::fclose (file); - } - } - else - strm.PutCString ("NULL"); -} - -PyObjectType -PythonObject::GetObjectType() const -{ - if (IsNULLOrNone()) - return PyObjectType::None; - - if (PyList_Check(m_py_obj)) - return PyObjectType::List; - if (PyDict_Check(m_py_obj)) - return PyObjectType::Dictionary; - if (PyString_Check(m_py_obj)) - return PyObjectType::String; - if (PyInt_Check(m_py_obj) || PyLong_Check(m_py_obj)) - return PyObjectType::Integer; - return PyObjectType::Unknown; -} - -PythonString -PythonObject::Repr () -{ - if (!m_py_obj) - return PythonString (); - PyObject *repr = PyObject_Repr(m_py_obj); - if (!repr) - return PythonString (); - return PythonString(repr); -} - -PythonString -PythonObject::Str () -{ - if (!m_py_obj) - return PythonString (); - PyObject *str = PyObject_Str(m_py_obj); - if (!str) - return PythonString (); - return PythonString(str); -} - -bool -PythonObject::IsNULLOrNone () const -{ - return ((m_py_obj == nullptr) || (m_py_obj == Py_None)); -} - -StructuredData::ObjectSP -PythonObject::CreateStructuredObject() const -{ - switch (GetObjectType()) - { - case PyObjectType::Dictionary: - return PythonDictionary(m_py_obj).CreateStructuredDictionary(); - case PyObjectType::Integer: - return PythonInteger(m_py_obj).CreateStructuredInteger(); - case PyObjectType::List: - return PythonList(m_py_obj).CreateStructuredArray(); - case PyObjectType::String: - return PythonString(m_py_obj).CreateStructuredString(); - case PyObjectType::None: - return StructuredData::ObjectSP(); - default: - return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); - } -} - -//---------------------------------------------------------------------- -// PythonString -//---------------------------------------------------------------------- - -PythonString::PythonString (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString (llvm::StringRef string) : - PythonObject(PyString_FromStringAndSize(string.data(), string.size())) -{ -} - -PythonString::PythonString(const char *string) : - PythonObject(PyString_FromString(string)) -{ -} - -PythonString::PythonString () : - PythonObject() -{ -} - -PythonString::~PythonString () -{ -} - -bool -PythonString::Reset (PyObject *py_obj) -{ - if (py_obj && PyString_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -llvm::StringRef -PythonString::GetString() const -{ - if (m_py_obj) - return llvm::StringRef(PyString_AsString(m_py_obj), GetSize()); - return llvm::StringRef(); -} - -size_t -PythonString::GetSize() const -{ - if (m_py_obj) - return PyString_Size(m_py_obj); - return 0; -} - -void -PythonString::SetString (llvm::StringRef string) -{ - PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size())); -} - -StructuredData::StringSP -PythonString::CreateStructuredString() const -{ - StructuredData::StringSP result(new StructuredData::String); - result->SetValue(GetString()); - return result; -} - -//---------------------------------------------------------------------- -// PythonInteger -//---------------------------------------------------------------------- - -PythonInteger::PythonInteger (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger (int64_t value) : - PythonObject() -{ - SetInteger (value); -} - - -PythonInteger::~PythonInteger () -{ -} - -bool -PythonInteger::Reset (PyObject *py_obj) -{ - if (py_obj) - { - if (PyInt_Check (py_obj) || PyLong_Check(py_obj)) - return PythonObject::Reset(py_obj); - } - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -int64_t -PythonInteger::GetInteger() const -{ - if (m_py_obj) - { - if (PyInt_Check(m_py_obj)) - return PyInt_AsLong(m_py_obj); - else if (PyLong_Check(m_py_obj)) - return PyLong_AsLongLong(m_py_obj); - } - return UINT64_MAX; -} - -void -PythonInteger::SetInteger (int64_t value) -{ - PythonObject::Reset(PyLong_FromLongLong(value)); -} - -StructuredData::IntegerSP -PythonInteger::CreateStructuredInteger() const -{ - StructuredData::IntegerSP result(new StructuredData::Integer); - result->SetValue(GetInteger()); - return result; -} - -//---------------------------------------------------------------------- -// PythonList -//---------------------------------------------------------------------- - -PythonList::PythonList (bool create_empty) : - PythonObject(create_empty ? PyList_New(0) : nullptr) -{ -} - -PythonList::PythonList (uint32_t count) : - PythonObject(PyList_New(count)) -{ -} - -PythonList::PythonList (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a list -} - - -PythonList::PythonList (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list -} - -PythonList::~PythonList () -{ -} - -bool -PythonList::Reset (PyObject *py_obj) -{ - if (py_obj && PyList_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -uint32_t -PythonList::GetSize() const -{ - if (m_py_obj) - return PyList_GET_SIZE(m_py_obj); - return 0; -} - -PythonObject -PythonList::GetItemAtIndex(uint32_t index) const -{ - if (m_py_obj) - return PythonObject(PyList_GetItem(m_py_obj, index)); - return PythonObject(); -} - -void -PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object) -{ - if (m_py_obj && object) - PyList_SetItem(m_py_obj, index, object.get()); -} - -void -PythonList::AppendItem (const PythonObject &object) -{ - if (m_py_obj && object) - PyList_Append(m_py_obj, object.get()); -} - -StructuredData::ArraySP -PythonList::CreateStructuredArray() const -{ - StructuredData::ArraySP result(new StructuredData::Array); - uint32_t count = GetSize(); - for (uint32_t i = 0; i < count; ++i) - { - PythonObject obj = GetItemAtIndex(i); - result->AddItem(obj.CreateStructuredObject()); - } - return result; -} - -//---------------------------------------------------------------------- -// PythonDictionary -//---------------------------------------------------------------------- - -PythonDictionary::PythonDictionary (bool create_empty) : -PythonObject(create_empty ? PyDict_New() : nullptr) -{ -} - -PythonDictionary::PythonDictionary (PyObject *py_obj) : - PythonObject(py_obj) -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a dictionary -} - - -PythonDictionary::PythonDictionary (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary -} - -PythonDictionary::~PythonDictionary () -{ -} - -bool -PythonDictionary::Reset (PyObject *py_obj) -{ - if (py_obj && PyDict_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -uint32_t -PythonDictionary::GetSize() const -{ - if (m_py_obj) - return PyDict_Size(m_py_obj); - return 0; -} - -PythonObject -PythonDictionary::GetItemForKey (const char *key) const -{ - if (key && key[0]) - { - PythonString python_key(key); - return GetItemForKey(python_key); - } - return PythonObject(); -} - - -PythonObject -PythonDictionary::GetItemForKey (const PythonString &key) const -{ - if (m_py_obj && key) - return PythonObject(PyDict_GetItem(m_py_obj, key.get())); - return PythonObject(); -} - - -const char * -PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const -{ - if (m_py_obj && key) - { - PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get()); - if (py_obj && PyString_Check(py_obj)) - return PyString_AsString(py_obj); - } - return fail_value; -} - -int64_t -PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const -{ - if (m_py_obj && key) - { - PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get()); - if (py_obj) - { - if (PyInt_Check(py_obj)) - return PyInt_AsLong(py_obj); - - if (PyLong_Check(py_obj)) - return PyLong_AsLong(py_obj); - } - } - return fail_value; -} - -PythonList -PythonDictionary::GetKeys () const -{ - if (m_py_obj) - return PythonList(PyDict_Keys(m_py_obj)); - return PythonList(true); -} - -PythonString -PythonDictionary::GetKeyAtPosition (uint32_t pos) const -{ - PyObject *key, *value; - Py_ssize_t pos_iter = 0; - - if (m_py_obj) - { - while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) - { - if (pos-- == 0) - return PythonString(key); - } - } - return PythonString(); -} - -PythonObject -PythonDictionary::GetValueAtPosition (uint32_t pos) const -{ - PyObject *key, *value; - Py_ssize_t pos_iter = 0; - - if (!m_py_obj) - return PythonObject(); - - while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) { - if (pos-- == 0) - return PythonObject(value); - } - return PythonObject(); -} - -void -PythonDictionary::SetItemForKey (const PythonString &key, PyObject *value) -{ - if (m_py_obj && key && value) - PyDict_SetItem(m_py_obj, key.get(), value); -} - -void -PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value) -{ - if (m_py_obj && key && value) - PyDict_SetItem(m_py_obj, key.get(), value.get()); -} - -StructuredData::DictionarySP -PythonDictionary::CreateStructuredDictionary() const -{ - StructuredData::DictionarySP result(new StructuredData::Dictionary); - PythonList keys(GetKeys()); - uint32_t num_keys = keys.GetSize(); - for (uint32_t i = 0; i < num_keys; ++i) - { - PythonObject key = keys.GetItemAtIndex(i); - PythonString key_str = key.Str(); - PythonObject value = GetItemForKey(key); - StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); - result->AddItem(key_str.GetString(), structured_value); - } - return result; -} - -#endif diff --git a/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp deleted file mode 100644 index 909a1161c9c1..000000000000 --- a/source/Interpreter/ScriptInterpreterNone.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Interpreter/ScriptInterpreterNone.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/StringList.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Interpreter/CommandInterpreter.h" - -using namespace lldb; -using namespace lldb_private; - -ScriptInterpreterNone::ScriptInterpreterNone (CommandInterpreter &interpreter) : - ScriptInterpreter (interpreter, eScriptLanguageNone) -{ -} - -ScriptInterpreterNone::~ScriptInterpreterNone () -{ -} - -bool -ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&) -{ - m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n"); - return false; -} - -void -ScriptInterpreterNone::ExecuteInterpreterLoop () -{ - m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n"); -} - - diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp deleted file mode 100644 index 8f60793550c3..000000000000 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ /dev/null @@ -1,3194 +0,0 @@ -//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// In order to guarantee correct working with Python, Python.h *MUST* be -// the *FIRST* header file included here. -#ifdef LLDB_DISABLE_PYTHON - -// Python is disabled in this build - -#else - -#include "lldb/lldb-python.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" - -#include <stdlib.h> -#include <stdio.h> - -#include <string> - -#include "lldb/API/SBValue.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Breakpoint/WatchpointOptions.h" -#include "lldb/Core/Communication.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Timer.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/DataFormatters/TypeSummary.h" -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/PythonDataObjects.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlan.h" - -#if defined(_WIN32) -#include "lldb/Host/windows/ConnectionGenericFileWindows.h" -#endif - -#include "llvm/ADT/StringRef.h" - -using namespace lldb; -using namespace lldb_private; - -static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr; -static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; -static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; -static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr; -static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; -static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; -static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; -static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; -static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; -static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr; -static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr; -static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; -static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; -static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; - -static bool g_initialized = false; - -static std::string -ReadPythonBacktrace (PyObject* py_backtrace); - -ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter, - uint16_t on_entry, - uint16_t on_leave, - FILE *in, - FILE *out, - FILE *err) : - ScriptInterpreterLocker (), - m_teardown_session( (on_leave & TearDownSession) == TearDownSession ), - m_python_interpreter(py_interpreter) -{ - DoAcquireLock(); - if ((on_entry & InitSession) == InitSession) - { - if (DoInitSession(on_entry, in, out, err) == false) - { - // Don't teardown the session if we didn't init it. - m_teardown_session = false; - } - } -} - -bool -ScriptInterpreterPython::Locker::DoAcquireLock() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - m_GILState = PyGILState_Ensure(); - if (log) - log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); - - // we need to save the thread state when we first start the command - // because we might decide to interrupt it while some action is taking - // place outside of Python (e.g. printing to screen, waiting for the network, ...) - // in that case, _PyThreadState_Current will be NULL - and we would be unable - // to set the asynchronous exception - not a desirable situation - m_python_interpreter->SetThreadState (_PyThreadState_Current); - m_python_interpreter->IncrementLockCount(); - return true; -} - -bool -ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err) -{ - if (!m_python_interpreter) - return false; - return m_python_interpreter->EnterSession (on_entry_flags, in, out, err); -} - -bool -ScriptInterpreterPython::Locker::DoFreeLock() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); - PyGILState_Release(m_GILState); - m_python_interpreter->DecrementLockCount(); - return true; -} - -bool -ScriptInterpreterPython::Locker::DoTearDownSession() -{ - if (!m_python_interpreter) - return false; - m_python_interpreter->LeaveSession (); - return true; -} - -ScriptInterpreterPython::Locker::~Locker() -{ - if (m_teardown_session) - DoTearDownSession(); - DoFreeLock(); -} - - -ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) : - ScriptInterpreter (interpreter, eScriptLanguagePython), - IOHandlerDelegateMultiline("DONE"), - m_saved_stdin (), - m_saved_stdout (), - m_saved_stderr (), - m_main_module (), - m_lldb_module (), - m_session_dict (false), // Don't create an empty dictionary, leave it invalid - m_sys_module_dict (false), // Don't create an empty dictionary, leave it invalid - m_run_one_line_function (), - m_run_one_line_str_global (), - m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()), - m_terminal_state (), - m_active_io_handler (eIOHandlerNone), - m_session_is_active (false), - m_pty_slave_is_open (false), - m_valid_session (true), - m_lock_count (0), - m_command_thread_state (nullptr) -{ - assert(g_initialized && "ScriptInterpreterPython created but initialize has not been called!"); - - m_dictionary_name.append("_dict"); - StreamString run_string; - run_string.Printf ("%s = dict()", m_dictionary_name.c_str()); - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); - PyRun_SimpleString (run_string.GetData()); - - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - - // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set - // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task - run_string.Clear(); - run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(), - interpreter.GetDebugger().GetID()); - PyRun_SimpleString (run_string.GetData()); -} - -ScriptInterpreterPython::~ScriptInterpreterPython () -{ -} - -void -ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler) -{ - const char *instructions = nullptr; - - switch (m_active_io_handler) - { - case eIOHandlerNone: - break; - case eIOHandlerBreakpoint: - instructions = R"(Enter your Python command(s). Type 'DONE' to end. -def function (frame, bp_loc, internal_dict): - """frame: the lldb.SBFrame for the location at which you stopped - bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information - internal_dict: an LLDB support object not to be used""" -)"; - break; - case eIOHandlerWatchpoint: - instructions = "Enter your Python command(s). Type 'DONE' to end.\n"; - break; - } - - if (instructions) - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(instructions); - output_sp->Flush(); - } - } -} - -void -ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data) -{ - io_handler.SetIsDone(true); - bool batch_mode = m_interpreter.GetBatchCommandMode(); - - switch (m_active_io_handler) - { - case eIOHandlerNone: - break; - case eIOHandlerBreakpoint: - { - std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); - for (auto bp_options : *bp_options_vec) - { - if (!bp_options) - continue; - - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - if (data_ap.get()) - { - data_ap->user_source.SplitIntoLines(data); - - if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success()) - { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); - } - else if (!batch_mode) - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - if (error_sp) - { - error_sp->Printf ("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); - } - } - } - } - m_active_io_handler = eIOHandlerNone; - } - break; - case eIOHandlerWatchpoint: - { - WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); - std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); - if (data_ap.get()) - { - data_ap->user_source.SplitIntoLines(data); - - if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) - { - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); - } - else if (!batch_mode) - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - if (error_sp) - { - error_sp->Printf ("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); - } - } - } - m_active_io_handler = eIOHandlerNone; - } - break; - } -} - - -void -ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) -{ -} - -void -ScriptInterpreterPython::SaveTerminalState (int fd) -{ - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state - // on the input file handle. - m_terminal_state.Save (fd, false); -} - -void -ScriptInterpreterPython::RestoreTerminalState () -{ - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state - // on the input file handle. - m_terminal_state.Restore(); -} - -void -ScriptInterpreterPython::LeaveSession () -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - if (log) - log->PutCString("ScriptInterpreterPython::LeaveSession()"); - - // checking that we have a valid thread state - since we use our own threading and locking - // in some (rare) cases during cleanup Python may end up believing we have no thread state - // and PyImport_AddModule will crash if that is the case - since that seems to only happen - // when destroying the SBDebugger, we can make do without clearing up stdout and stderr - - // rdar://problem/11292882 - // When the current thread state is NULL, PyThreadState_Get() issues a fatal error. - if (PyThreadState_GetDict()) - { - PythonDictionary &sys_module_dict = GetSysModuleDictionary (); - if (sys_module_dict) - { - if (m_saved_stdin) - { - sys_module_dict.SetItemForKey("stdin", m_saved_stdin); - m_saved_stdin.Reset (); - } - if (m_saved_stdout) - { - sys_module_dict.SetItemForKey("stdout", m_saved_stdout); - m_saved_stdout.Reset (); - } - if (m_saved_stderr) - { - sys_module_dict.SetItemForKey("stderr", m_saved_stderr); - m_saved_stderr.Reset (); - } - } - } - - m_session_is_active = false; -} - -static PyObject * -PyFile_FromFile_Const(FILE *fp, const char *name, const char *mode, int (*close)(FILE *)) -{ - // Read through the Python source, doesn't seem to modify these strings - return PyFile_FromFile(fp, const_cast<char*>(name), const_cast<char*>(mode), close); -} - -bool -ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, - FILE *in, - FILE *out, - FILE *err) -{ - // If we have already entered the session, without having officially 'left' it, then there is no need to - // 'enter' it again. - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - if (m_session_is_active) - { - if (log) - log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags); - return false; - } - - if (log) - log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags); - - - m_session_is_active = true; - - StreamString run_string; - - if (on_entry_flags & Locker::InitGlobals) - { - run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); - run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); - run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()"); - run_string.PutCString ("; lldb.process = lldb.target.GetProcess()"); - run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()"); - run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()"); - run_string.PutCString ("')"); - } - else - { - // If we aren't initing the globals, we should still always set the debugger (since that is always unique.) - run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); - run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); - run_string.PutCString ("')"); - } - - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - PythonDictionary &sys_module_dict = GetSysModuleDictionary (); - if (sys_module_dict) - { - lldb::StreamFileSP in_sp; - lldb::StreamFileSP out_sp; - lldb::StreamFileSP err_sp; - if (in == nullptr || out == nullptr || err == nullptr) - m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); - - m_saved_stdin.Reset(); - - if ((on_entry_flags & Locker::NoSTDIN) == 0) - { - // STDIN is enabled - if (in == nullptr && in_sp) - in = in_sp->GetFile().GetStream(); - if (in) - { - m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); - // This call can deadlock your process if the file is locked - PyObject *new_file = PyFile_FromFile_Const (in, "", "r", nullptr); - sys_module_dict.SetItemForKey ("stdin", new_file); - Py_DECREF (new_file); - } - } - - if (out == nullptr && out_sp) - out = out_sp->GetFile().GetStream(); - if (out) - { - m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout")); - - PyObject *new_file = PyFile_FromFile_Const (out, "", "w", nullptr); - sys_module_dict.SetItemForKey ("stdout", new_file); - Py_DECREF (new_file); - } - else - m_saved_stdout.Reset(); - - if (err == nullptr && err_sp) - err = err_sp->GetFile().GetStream(); - if (err) - { - m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr")); - - PyObject *new_file = PyFile_FromFile_Const (err, "", "w", nullptr); - sys_module_dict.SetItemForKey ("stderr", new_file); - Py_DECREF (new_file); - } - else - m_saved_stderr.Reset(); - } - - if (PyErr_Occurred()) - PyErr_Clear (); - - return true; -} - -PythonObject & -ScriptInterpreterPython::GetMainModule () -{ - if (!m_main_module) - m_main_module.Reset(PyImport_AddModule ("__main__")); - return m_main_module; -} - -PythonDictionary & -ScriptInterpreterPython::GetSessionDictionary () -{ - if (!m_session_dict) - { - PythonObject &main_module = GetMainModule (); - if (main_module) - { - PythonDictionary main_dict(PyModule_GetDict (main_module.get())); - if (main_dict) - { - m_session_dict = main_dict.GetItemForKey(m_dictionary_name.c_str()); - } - } - } - return m_session_dict; -} - -PythonDictionary & -ScriptInterpreterPython::GetSysModuleDictionary () -{ - if (!m_sys_module_dict) - { - PyObject *sys_module = PyImport_AddModule ("sys"); - if (sys_module) - m_sys_module_dict.Reset(PyModule_GetDict (sys_module)); - } - return m_sys_module_dict; -} - -static std::string -GenerateUniqueName (const char* base_name_wanted, - uint32_t& functions_counter, - const void* name_token = nullptr) -{ - StreamString sstr; - - if (!base_name_wanted) - return std::string(); - - if (!name_token) - sstr.Printf ("%s_%d", base_name_wanted, functions_counter++); - else - sstr.Printf ("%s_%p", base_name_wanted, name_token); - - return sstr.GetString(); -} - -bool -ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects () -{ - if (!m_run_one_line_function) - { - PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter"); - if (module != nullptr) - { - PythonDictionary module_dict (PyModule_GetDict (module)); - if (module_dict) - { - m_run_one_line_function = module_dict.GetItemForKey("run_one_line"); - m_run_one_line_str_global = module_dict.GetItemForKey("g_run_one_line_str"); - } - } - } - return (bool)m_run_one_line_function; -} - -static void -ReadThreadBytesReceived(void *baton, const void *src, size_t src_len) -{ - if (src && src_len) - { - Stream *strm = (Stream *)baton; - strm->Write(src, src_len); - strm->Flush(); - } -} - -bool -ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options) -{ - if (!m_valid_session) - return false; - - if (command && command[0]) - { - // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through - // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside - // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated - // method to pass the command string directly down to Python. - Debugger &debugger = m_interpreter.GetDebugger(); - - StreamFileSP input_file_sp; - StreamFileSP output_file_sp; - StreamFileSP error_file_sp; - Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); - bool join_read_thread = false; - if (options.GetEnableIO()) - { - if (result) - { - input_file_sp = debugger.GetInputFile(); - // Set output to a temporary file so we can forward the results on to the result object - - Pipe pipe; - Error pipe_result = pipe.CreateNew(false); - if (pipe_result.Success()) - { -#if defined(_WIN32) - lldb::file_t read_file = pipe.GetReadNativeHandle(); - pipe.ReleaseReadFileDescriptor(); - std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true)); -#else - std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); -#endif - if (conn_ap->IsConnected()) - { - output_comm.SetConnection(conn_ap.release()); - output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream()); - output_comm.StartReadThread(); - join_read_thread = true; - FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w"); - output_file_sp.reset(new StreamFile(outfile_handle, true)); - error_file_sp = output_file_sp; - if (outfile_handle) - ::setbuf (outfile_handle, nullptr); - - result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream()); - result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream()); - } - } - } - if (!input_file_sp || !output_file_sp || !error_file_sp) - debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); - } - else - { - input_file_sp.reset (new StreamFile ()); - input_file_sp->GetFile().Open("/dev/null", File::eOpenOptionRead); - output_file_sp.reset (new StreamFile ()); - output_file_sp->GetFile().Open("/dev/null", File::eOpenOptionWrite); - error_file_sp = output_file_sp; - } - - FILE *in_file = input_file_sp->GetFile().GetStream(); - FILE *out_file = output_file_sp->GetFile().GetStream(); - FILE *err_file = error_file_sp->GetFile().GetStream(); - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | - ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN), - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession, - in_file, - out_file, - err_file); - - bool success = false; - - // Find the correct script interpreter dictionary in the main module. - PythonDictionary &session_dict = GetSessionDictionary (); - if (session_dict) - { - if (GetEmbeddedInterpreterModuleObjects ()) - { - PyObject *pfunc = m_run_one_line_function.get(); - - if (pfunc && PyCallable_Check (pfunc)) - { - PythonObject pargs (Py_BuildValue("(Os)", session_dict.get(), command)); - if (pargs) - { - PythonObject return_value(PyObject_CallObject (pfunc, pargs.get())); - if (return_value) - success = true; - else if (options.GetMaskoutErrors() && PyErr_Occurred ()) - { - PyErr_Print(); - PyErr_Clear(); - } - } - } - } - } - - // Flush our output and error file handles - ::fflush (out_file); - if (out_file != err_file) - ::fflush (err_file); - - if (join_read_thread) - { - // Close the write end of the pipe since we are done with our - // one line script. This should cause the read thread that - // output_comm is using to exit - output_file_sp->GetFile().Close(); - // The close above should cause this thread to exit when it gets - // to the end of file, so let it get all its data - output_comm.JoinReadThread(); - // Now we can close the read end of the pipe - output_comm.Disconnect(); - } - - - if (success) - return true; - - // The one-liner failed. Append the error message. - if (result) - result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command); - return false; - } - - if (result) - result->AppendError ("empty command passed to python\n"); - return false; -} - - -class IOHandlerPythonInterpreter : - public IOHandler -{ -public: - - IOHandlerPythonInterpreter (Debugger &debugger, - ScriptInterpreterPython *python) : - IOHandler (debugger, IOHandler::Type::PythonInterpreter), - m_python(python) - { - - } - - ~IOHandlerPythonInterpreter() override - { - - } - - ConstString - GetControlSequence (char ch) override - { - if (ch == 'd') - return ConstString("quit()\n"); - return ConstString(); - } - - void - Run () override - { - if (m_python) - { - int stdin_fd = GetInputFD(); - if (stdin_fd >= 0) - { - Terminal terminal(stdin_fd); - TerminalState terminal_state; - const bool is_a_tty = terminal.IsATerminal(); - - if (is_a_tty) - { - terminal_state.Save (stdin_fd, false); - terminal.SetCanonical(false); - terminal.SetEcho(true); - } - - ScriptInterpreterPython::Locker locker (m_python, - ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - ScriptInterpreterPython::Locker::InitGlobals, - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession); - - // The following call drops into the embedded interpreter loop and stays there until the - // user chooses to exit from the Python interpreter. - // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before - // a system call that can hang, and lock it when the syscall has returned. - - // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and - // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want - // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off, - // and things could hang (it's happened before). - - StreamString run_string; - run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ()); - PyRun_SimpleString (run_string.GetData()); - - if (is_a_tty) - terminal_state.Restore(); - } - } - SetIsDone(true); - } - - void - Cancel () override - { - - } - - bool - Interrupt () override - { - return m_python->Interrupt(); - } - - void - GotEOF() override - { - - } -protected: - ScriptInterpreterPython *m_python; -}; - - -void -ScriptInterpreterPython::ExecuteInterpreterLoop () -{ - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - Debugger &debugger = GetCommandInterpreter().GetDebugger(); - - // At the moment, the only time the debugger does not have an input file handle is when this is called - // directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to - // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't - // do it. - - if (!debugger.GetInputFile()->GetFile().IsValid()) - return; - - IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this)); - if (io_handler_sp) - { - debugger.PushIOHandler(io_handler_sp); - } -} - -bool -ScriptInterpreterPython::Interrupt() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - - if (IsExecutingPython()) - { - PyThreadState* state = _PyThreadState_Current; - if (!state) - state = GetThreadState(); - if (state) - { - long tid = state->thread_id; - _PyThreadState_Current = state; - int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); - return true; - } - } - if (log) - log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt"); - return false; - -} -bool -ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ScriptReturnType return_type, - void *ret_value, - const ExecuteScriptOptions &options) -{ - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - - PyObject *py_return = nullptr; - PythonObject &main_module = GetMainModule (); - PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = nullptr; - bool ret_success = false; - int success; - - PythonDictionary locals = GetSessionDictionary (); - - if (!locals) - { - locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str()); - } - - if (!locals) - locals = globals; - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - PyErr_Clear(); - - if (in_string != nullptr) - { - { // scope for PythonInputReaderManager - //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get()); - if (py_return == nullptr) - { - py_error = PyErr_Occurred (); - if (py_error != nullptr) - PyErr_Clear (); - - py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get()); - } - } - - if (py_return != nullptr) - { - switch (return_type) - { - case eScriptReturnTypeCharPtr: // "char *" - { - const char format[3] = "s#"; - success = PyArg_Parse (py_return, format, (char **) ret_value); - break; - } - 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 eScriptReturnTypeBool: - { - const char format[2] = "b"; - success = PyArg_Parse (py_return, format, (bool *) ret_value); - break; - } - case eScriptReturnTypeShortInt: - { - const char format[2] = "h"; - success = PyArg_Parse (py_return, format, (short *) ret_value); - break; - } - case eScriptReturnTypeShortIntUnsigned: - { - const char format[2] = "H"; - success = PyArg_Parse (py_return, format, (unsigned short *) ret_value); - break; - } - case eScriptReturnTypeInt: - { - const char format[2] = "i"; - success = PyArg_Parse (py_return, format, (int *) ret_value); - break; - } - case eScriptReturnTypeIntUnsigned: - { - const char format[2] = "I"; - success = PyArg_Parse (py_return, format, (unsigned int *) ret_value); - break; - } - case eScriptReturnTypeLongInt: - { - const char format[2] = "l"; - success = PyArg_Parse (py_return, format, (long *) ret_value); - break; - } - case eScriptReturnTypeLongIntUnsigned: - { - const char format[2] = "k"; - success = PyArg_Parse (py_return, format, (unsigned long *) ret_value); - break; - } - case eScriptReturnTypeLongLong: - { - const char format[2] = "L"; - success = PyArg_Parse (py_return, format, (long long *) ret_value); - break; - } - case eScriptReturnTypeLongLongUnsigned: - { - const char format[2] = "K"; - success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value); - break; - } - case eScriptReturnTypeFloat: - { - const char format[2] = "f"; - success = PyArg_Parse (py_return, format, (float *) ret_value); - break; - } - case eScriptReturnTypeDouble: - { - const char format[2] = "d"; - success = PyArg_Parse (py_return, format, (double *) ret_value); - break; - } - case eScriptReturnTypeChar: - { - const char format[2] = "c"; - 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) - ret_success = true; - else - ret_success = false; - } - } - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - { - ret_success = false; - if (options.GetMaskoutErrors()) - { - if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError)) - PyErr_Print (); - PyErr_Clear(); - } - } - - return ret_success; -} - -Error -ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options) -{ - Error error; - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - - PythonObject return_value; - PythonObject &main_module = GetMainModule (); - PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = nullptr; - - PythonDictionary locals = GetSessionDictionary (); - - if (!locals) - { - locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str()); - } - - if (!locals) - { - locals = globals; - } - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - PyErr_Clear(); - - if (in_string != nullptr) - { - struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input); - if (compiled_node) - { - PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py"); - if (compiled_code) - { - return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get())); - } - } - } - - py_error = PyErr_Occurred (); - if (py_error != nullptr) - { -// puts(in_string); -// _PyObject_Dump (py_error); -// PyErr_Print(); -// success = false; - - PyObject *type = nullptr; - PyObject *value = nullptr; - PyObject *traceback = nullptr; - PyErr_Fetch (&type,&value,&traceback); - - // get the backtrace - std::string bt = ReadPythonBacktrace(traceback); - - if (value && value != Py_None) - error.SetErrorStringWithFormat("%s\n%s", PyString_AsString(PyObject_Str(value)),bt.c_str()); - else - error.SetErrorStringWithFormat("%s",bt.c_str()); - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - if (options.GetMaskoutErrors()) - { - PyErr_Clear(); - } - } - - return error; -} - - -void -ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, - CommandReturnObject &result) -{ - m_active_io_handler = eIOHandlerBreakpoint; - m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec); -} - -void -ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result) -{ - m_active_io_handler = eIOHandlerWatchpoint; - m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options); -} - -void -ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, - const char *function_name) -{ - // For now just cons up a oneliner that calls the provided function. - std::string oneliner("return "); - oneliner += function_name; - oneliner += "(frame, bp_loc, internal_dict)"; - m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, - oneliner.c_str()); -} - -// Set a Python one-liner as the callback for the breakpoint. -Error -ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *command_body_text) -{ - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - - // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will - // wrap the body in an auto-generated function, and return the function name in script_source. That is what - // the callback will actually invoke. - - data_ap->user_source.SplitIntoLines(command_body_text); - Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source); - if (error.Success()) - { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); - return error; - } - else - return error; -} - -// Set a Python one-liner as the callback for the watchpoint. -void -ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options, - const char *oneliner) -{ - std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); - - // It's necessary to set both user_source and script_source to the oneliner. - // The former is used to generate callback description (as in watchpoint command list) - // while the latter is used for Python to interpret during the actual callback. - - data_ap->user_source.AppendString (oneliner); - data_ap->script_source.assign (oneliner); - - if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) - { - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); - } - - return; -} - -Error -ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) -{ - // Convert StringList to one long, newline delimited, const char *. - std::string function_def_string(function_def.CopyList()); - - Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); - return error; -} - -Error -ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) -{ - Error error; - int num_lines = input.GetSize (); - if (num_lines == 0) - { - error.SetErrorString ("No input data."); - return error; - } - - if (!signature || *signature == 0) - { - error.SetErrorString("No output function name."); - return error; - } - - StreamString sstr; - StringList auto_generated_function; - auto_generated_function.AppendString (signature); - auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary - auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict - auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict - auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the - // global dictionary. - - // Wrap everything up inside the function, increasing the indentation. - - auto_generated_function.AppendString(" if True:"); - for (int i = 0; i < num_lines; ++i) - { - sstr.Clear (); - sstr.Printf (" %s", input.GetStringAtIndex (i)); - auto_generated_function.AppendString (sstr.GetData()); - } - auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict - auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values - auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict - auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict - - // Verify that the results are valid Python. - - error = ExportFunctionDefinitionToInterpreter (auto_generated_function); - - return error; -} - -bool -ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the - // ValueObject as parameter to the function. - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); - sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(), user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - -bool -ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions)); - - sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(),user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - - -bool -ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token) -{ - static uint32_t num_created_classes = 0; - user_input.RemoveBlankLines (); - int num_lines = user_input.GetSize (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - // Wrap all user input into a Python class - - std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token)); - - StringList auto_generated_class; - - // Create the function name & definition string. - - sstr.Printf ("class %s:", auto_generated_class_name.c_str()); - auto_generated_class.AppendString (sstr.GetData()); - - // Wrap everything up inside the class, increasing the indentation. - // we don't need to play any fancy indentation tricks here because there is no - // surrounding code whose indentation we need to honor - for (int i = 0; i < num_lines; ++i) - { - sstr.Clear (); - sstr.Printf (" %s", user_input.GetStringAtIndex (i)); - auto_generated_class.AppendString (sstr.GetData()); - } - - - // Verify that the results are valid Python. - // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported) - // (TODO: rename that method to ExportDefinitionToInterpreter) - if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success()) - return false; - - // Store the name of the auto-generated class - - output.assign(auto_generated_class_name); - return true; -} - -StructuredData::GenericSP -ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!process_sp) - return StructuredData::GenericSP(); - - void* ret_val; - - { - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = g_swig_create_os_plugin (class_name, - m_dictionary_name.c_str(), - process_sp); - } - - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) -{ - Locker py_lock(this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_register_info"; - - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::DictionarySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonDictionary result_dict(py_return); - return result_dict.CreateStructuredDictionary(); -} - -StructuredData::ArraySP -ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) -{ - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_thread_info"; - - if (!os_plugin_object_sp) - return StructuredData::ArraySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::ArraySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::ArraySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::ArraySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonList ResultList(py_return); - return ResultList.CreateStructuredArray(); -} - -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to -// as the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template <typename T> -const char *GetPythonValueFormatString(T t) -{ - assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type."); - return nullptr; -} -template <> const char *GetPythonValueFormatString (char *) { return "s"; } -template <> const char *GetPythonValueFormatString (char) { return "b"; } -template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; } -template <> const char *GetPythonValueFormatString (short) { return "h"; } -template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; } -template <> const char *GetPythonValueFormatString (int) { return "i"; } -template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString (long) { return "l"; } -template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; } -template <> const char *GetPythonValueFormatString (long long) { return "L"; } -template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; } -template <> const char *GetPythonValueFormatString (float t) { return "f"; } -template <> const char *GetPythonValueFormatString (double t) { return "d"; } - -StructuredData::StringSP -ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) -{ - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_register_data"; - static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid)); - - if (!os_plugin_object_sp) - return StructuredData::StringSP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::StringSP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::StringSP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::StringSP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - PythonString result_string(py_return); - return result_string.CreateStructuredString(); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) -{ - Locker py_lock(this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "create_thread"; - std::string param_format; - param_format += GetPythonValueFormatString(tid); - param_format += GetPythonValueFormatString(context); - - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::DictionarySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, ¶m_format[0], tid, context); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonDictionary result_dict(py_return); - return result_dict.CreateStructuredDictionary(); -} - -StructuredData::ObjectSP -ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::ObjectSP(); - - if (!thread_plan_sp.get()) - return StructuredData::ObjectSP(); - - Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter); - - if (!script_interpreter) - return StructuredData::ObjectSP(); - - void* ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - - ret_val = g_swig_thread_plan_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - thread_plan_sp); - } - - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); -} - -bool -ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) -{ - bool explains_stop = true; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error); - if (script_error) - return true; - } - return explains_stop; -} - -bool -ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) -{ - bool should_stop = true; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error); - if (script_error) - return true; - } - return should_stop; -} - -lldb::StateType -ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) -{ - bool should_step = false; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error); - if (script_error) - should_step = true; - } - if (should_step) - return lldb::eStateStepping; - else - return lldb::eStateRunning; -} - -StructuredData::ObjectSP -ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) -{ - if (!file_spec.Exists()) - { - error.SetErrorString("no such file"); - return StructuredData::ObjectSP(); - } - - StructuredData::ObjectSP module_sp; - - if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp)) - return module_sp; - - return StructuredData::ObjectSP(); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, - lldb_private::Error &error) -{ - if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get) - return StructuredData::DictionarySP(); - StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); - if (!generic) - return StructuredData::DictionarySP(); - - PyObject *reply_pyobj = nullptr; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - TargetSP target_sp(target->shared_from_this()); - reply_pyobj = (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp); - } - - PythonDictionary py_dict(reply_pyobj); - - return py_dict.CreateStructuredDictionary(); -} - -StructuredData::ObjectSP -ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::ObjectSP(); - - if (!valobj.get()) - return StructuredData::ObjectSP(); - - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return StructuredData::ObjectSP(); - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return StructuredData::ObjectSP(); - - void *ret_val = nullptr; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_synthetic_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - } - - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); -} - -StructuredData::GenericSP -ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name) -{ - DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this()); - - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!debugger_sp.get()) - return StructuredData::GenericSP(); - - void* ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_create_cmd (class_name, - m_dictionary_name.c_str(), - debugger_sp); - } - - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); -} - -bool -ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token) -{ - StringList input; - input.SplitIntoLines(oneliner, strlen(oneliner)); - return GenerateTypeScriptFunction(input, output, name_token); -} - -bool -ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token) -{ - StringList input; - input.SplitIntoLines(oneliner, strlen(oneliner)); - return GenerateTypeSynthClass(input, output, name_token); -} - - -Error -ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - Error error; - if (user_input.GetSize() == 0) - { - error.SetErrorString("No input data."); - return error; - } - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions)); - sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); - - error = GenerateFunction(sstr.GetData(), user_input); - if (!error.Success()) - return error; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return error; -} - -bool -ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - if (user_input.GetSize() == 0) - return false; - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions)); - sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(), user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - -bool -ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj, - StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, - std::string &retval) -{ - - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - if (!valobj.get()) - { - retval.assign("<no object>"); - return false; - } - - void *old_callee = nullptr; - StructuredData::Generic *generic = nullptr; - if (callee_wrapper_sp) - { - generic = callee_wrapper_sp->GetAsGeneric(); - if (generic) - old_callee = generic->GetValue(); - } - void* new_callee = old_callee; - - bool ret_val; - if (python_function_name && *python_function_name) - { - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - { - TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); - - Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback"); - ret_val = g_swig_typescript_callback (python_function_name, - GetSessionDictionary().get(), - valobj, - &new_callee, - options_sp, - retval); - } - } - } - else - { - retval.assign("<no function name>"); - return false; - } - - if (new_callee && old_callee != new_callee) - callee_wrapper_sp.reset(new StructuredPythonObject(new_callee)); - - return ret_val; -} - -void -ScriptInterpreterPython::Clear () -{ - // Release any global variables that might have strong references to - // LLDB objects when clearing the python script interpreter. - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); - - // This may be called as part of Py_Finalize. In that case the modules are destroyed in random - // order and we can't guarantee that we can access these. - if (Py_IsInitialized()) - PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None"); -} - -bool -ScriptInterpreterPython::BreakpointCallbackFunction -( - void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id -) -{ - BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton; - const char *python_function_name = bp_option_data->script_source.c_str(); - - if (!context) - return true; - - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return true; - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return true; - - if (python_function_name && python_function_name[0]) - { - const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); - BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id); - if (breakpoint_sp) - { - const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id)); - - if (stop_frame_sp && bp_loc_sp) - { - bool ret_val = true; - { - Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_breakpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - bp_loc_sp); - } - return ret_val; - } - } - } - // We currently always true so we stop in case anything goes wrong when - // trying to call the script function - return true; -} - -bool -ScriptInterpreterPython::WatchpointCallbackFunction -( - void *baton, - StoppointCallbackContext *context, - user_id_t watch_id -) -{ - WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton; - const char *python_function_name = wp_option_data->script_source.c_str(); - - if (!context) - return true; - - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return true; - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return true; - - if (python_function_name && python_function_name[0]) - { - const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); - WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id); - if (wp_sp) - { - if (stop_frame_sp && wp_sp) - { - bool ret_val = true; - { - Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_watchpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - wp_sp); - } - return ret_val; - } - } - } - // We currently always true so we stop in case anything goes wrong when - // trying to call the script function - return true; -} - -size_t -ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp) -{ - if (!implementor_sp) - return 0; - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return 0; - void *implementor = generic->GetValue(); - if (!implementor) - return 0; - - if (!g_swig_calc_children) - return 0; - - size_t ret_val = 0; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_calc_children (implementor); - } - - return ret_val; -} - -lldb::ValueObjectSP -ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx) -{ - if (!implementor_sp) - return lldb::ValueObjectSP(); - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return lldb::ValueObjectSP(); - void *implementor = generic->GetValue(); - if (!implementor) - return lldb::ValueObjectSP(); - - if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) - return lldb::ValueObjectSP(); - - lldb::ValueObjectSP ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void* child_ptr = g_swig_get_child_index (implementor,idx); - if (child_ptr != nullptr && child_ptr != Py_None) - { - lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); - if (sb_value_ptr == nullptr) - Py_XDECREF(child_ptr); - else - ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); - } - else - { - Py_XDECREF(child_ptr); - } - } - - return ret_val; -} - -int -ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name) -{ - if (!implementor_sp) - return UINT32_MAX; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return UINT32_MAX; - void *implementor = generic->GetValue(); - if (!implementor) - return UINT32_MAX; - - if (!g_swig_get_index_child) - return UINT32_MAX; - - int ret_val = UINT32_MAX; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_get_index_child (implementor, child_name); - } - - return ret_val; -} - -bool -ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) -{ - bool ret_val = false; - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_update_provider) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_update_provider (implementor); - } - - return ret_val; -} - -bool -ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) -{ - bool ret_val = false; - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_mighthavechildren_provider) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_mighthavechildren_provider (implementor); - } - - return ret_val; -} - -lldb::ValueObjectSP -ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp) -{ - lldb::ValueObjectSP ret_val(nullptr); - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void* child_ptr = g_swig_getvalue_provider (implementor); - if (child_ptr != nullptr && child_ptr != Py_None) - { - lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); - if (sb_value_ptr == nullptr) - Py_XDECREF(child_ptr); - else - ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); - } - else - { - Py_XDECREF(child_ptr); - } - } - - return ret_val; -} - -static std::string -ReadPythonBacktrace (PyObject* py_backtrace) -{ - PyObject* traceback_module = nullptr, - *stringIO_module = nullptr, - *stringIO_builder = nullptr, - *stringIO_buffer = nullptr, - *printTB = nullptr, - *printTB_args = nullptr, - *printTB_result = nullptr, - *stringIO_getvalue = nullptr, - *printTB_string = nullptr; - - std::string retval("backtrace unavailable"); - - if (py_backtrace && py_backtrace != Py_None) - { - traceback_module = PyImport_ImportModule("traceback"); - stringIO_module = PyImport_ImportModule("StringIO"); - - if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None) - { - stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO"); - if (stringIO_builder && stringIO_builder != Py_None) - { - stringIO_buffer = PyObject_CallObject(stringIO_builder, nullptr); - if (stringIO_buffer && stringIO_buffer != Py_None) - { - printTB = PyObject_GetAttrString(traceback_module, "print_tb"); - if (printTB && printTB != Py_None) - { - printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer); - printTB_result = PyObject_CallObject(printTB, printTB_args); - stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue"); - if (stringIO_getvalue && stringIO_getvalue != Py_None) - { - printTB_string = PyObject_CallObject (stringIO_getvalue,nullptr); - if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string)) - retval.assign(PyString_AsString(printTB_string)); - } - } - } - } - } - } - Py_XDECREF(traceback_module); - Py_XDECREF(stringIO_module); - Py_XDECREF(stringIO_builder); - Py_XDECREF(stringIO_buffer); - Py_XDECREF(printTB); - Py_XDECREF(printTB_args); - Py_XDECREF(printTB_result); - Py_XDECREF(stringIO_getvalue); - Py_XDECREF(printTB_string); - return retval; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Process* process, - std::string& output, - Error& error) -{ - bool ret_val; - if (!process) - { - error.SetErrorString("no process"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_process) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ProcessSP process_sp(process->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Thread* thread, - std::string& output, - Error& error) -{ - bool ret_val; - if (!thread) - { - error.SetErrorString("no thread"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_thread) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ThreadSP thread_sp(thread->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Target* target, - std::string& output, - Error& error) -{ - bool ret_val; - if (!target) - { - error.SetErrorString("no thread"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_target) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - TargetSP target_sp(target->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - StackFrame* frame, - std::string& output, - Error& error) -{ - bool ret_val; - if (!frame) - { - error.SetErrorString("no frame"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_frame) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - StackFrameSP frame_sp(frame->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - ValueObject *value, - std::string& output, - Error& error) -{ - bool ret_val; - if (!value) - { - error.SetErrorString("no value"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_value) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ValueObjectSP value_sp(value->GetSP()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr) -{ - size_t pos = 0; - uint64_t matches = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) - { - matches++; - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } - return matches; -} - -bool -ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error, - StructuredData::ObjectSP *module_sp) -{ - if (!pathname || !pathname[0]) - { - error.SetErrorString("invalid pathname"); - return false; - } - - if (!g_swig_call_module_init) - { - error.SetErrorString("internal helper function missing"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - - { - FileSpec target_file(pathname, true); - std::string basename(target_file.GetFilename().GetCString()); - - StreamString command_stream; - - // Before executing Pyton code, lock the GIL. - Locker py_lock (this, - Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, - Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); - - if (target_file.GetFileType() == FileSpec::eFileTypeInvalid || - target_file.GetFileType() == FileSpec::eFileTypeUnknown) - { - // if not a valid file of any sort, check if it might be a filename still - // dot can't be used but / and \ can, and if either is found, reject - if (strchr(pathname,'\\') || strchr(pathname,'/')) - { - error.SetErrorString("invalid pathname"); - return false; - } - basename = pathname; // not a filename, probably a package of some sort, let it go through - } - else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory || - target_file.GetFileType() == FileSpec::eFileTypeRegular || - target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink) - { - std::string directory(target_file.GetDirectory().GetCString()); - replace_all(directory,"'","\\'"); - - // 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.insert(1,'%s');\n\n", - directory.c_str(), - directory.c_str()); - bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success(); - if (!syspath_retval) - { - error.SetErrorString("Python sys.path handling failed"); - return false; - } - - // strip .py or .pyc extension - ConstString extension = target_file.GetFileNameExtension(); - if (extension) - { - if (::strcmp(extension.GetCString(), "py") == 0) - basename.resize(basename.length()-3); - else if(::strcmp(extension.GetCString(), "pyc") == 0) - basename.resize(basename.length()-4); - } - } - else - { - error.SetErrorString("no known way to import this module specification"); - return false; - } - - // check if the module is already import-ed - command_stream.Clear(); - command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str()); - bool does_contain = false; - // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process - // in which this LLDB framework is living - bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(), - ScriptInterpreterPython::eScriptReturnTypeBool, - &does_contain, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain); - // this call will fail if the module was not imported in this Debugger before - command_stream.Clear(); - command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); - bool was_imported_locally = !(GetSessionDictionary().GetItemForKey(basename.c_str()).IsNULLOrNone()); - - bool was_imported = (was_imported_globally || was_imported_locally); - - if (was_imported == true && can_reload == false) - { - error.SetErrorString("module already imported"); - return false; - } - - // now actually do the import - command_stream.Clear(); - - if (was_imported) - { - if (!was_imported_locally) - command_stream.Printf("import %s ; reload(%s)",basename.c_str(),basename.c_str()); - else - command_stream.Printf("reload(%s)",basename.c_str()); - } - else - command_stream.Printf("import %s",basename.c_str()); - - error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)); - if (error.Fail()) - return false; - - // if we are here, everything worked - // call __lldb_init_module(debugger,dict) - if (!g_swig_call_module_init (basename.c_str(), - m_dictionary_name.c_str(), - debugger_sp)) - { - 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->reset(new StructuredPythonObject(module_pyobj)); - } - - return true; - } -} - -bool -ScriptInterpreterPython::IsReservedWord (const char* word) -{ - if (!word || !word[0]) - return false; - - llvm::StringRef word_sr(word); - - // filter out a few characters that would just confuse us - // and that are clearly not keyword material anyway - if (word_sr.find_first_of("'\"") != llvm::StringRef::npos) - return false; - - StreamString command_stream; - command_stream.Printf("keyword.iskeyword('%s')", word); - bool result; - ExecuteScriptOptions options; - options.SetEnableIO(false); - options.SetMaskoutErrors(true); - options.SetSetLLDBGlobals(false); - if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options)) - return result; - return false; -} - -ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp, - ScriptedCommandSynchronicity synchro) : - m_debugger_sp(debugger_sp), - m_synch_wanted(synchro), - m_old_asynch(debugger_sp->GetAsyncExecution()) -{ - if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous) - m_debugger_sp->SetAsyncExecution(false); - else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous) - m_debugger_sp->SetAsyncExecution(true); -} - -ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() -{ - if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) - m_debugger_sp->SetAsyncExecution(m_old_asynch); -} - -bool -ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) -{ - if (!impl_function) - { - error.SetErrorString("no function to execute"); - return false; - } - - if (!g_swig_call_command) - { - error.SetErrorString("no helper function to run scripted commands"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); - - if (!debugger_sp.get()) - { - error.SetErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - std::string err_msg; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), - Locker::FreeLock | Locker::TearDownSession); - - SynchronicityHandler synch_handler(debugger_sp, - synchronicity); - - ret_val = g_swig_call_command (impl_function, - m_dictionary_name.c_str(), - debugger_sp, - args, - cmd_retobj, - exe_ctx_ref_sp); - } - - if (!ret_val) - error.SetErrorString("unable to execute script function"); - else - error.Clear(); - - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) -{ - if (!impl_obj_sp || !impl_obj_sp->IsValid()) - { - error.SetErrorString("no function to execute"); - return false; - } - - if (!g_swig_call_command_object) - { - error.SetErrorString("no helper function to run scripted commands"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); - - if (!debugger_sp.get()) - { - error.SetErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - std::string err_msg; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), - Locker::FreeLock | Locker::TearDownSession); - - SynchronicityHandler synch_handler(debugger_sp, - synchronicity); - - ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(), - debugger_sp, - args, - cmd_retobj, - exe_ctx_ref_sp); - } - - if (!ret_val) - error.SetErrorString("unable to execute script function"); - else - error.Clear(); - - return ret_val; -} - -// in Python, a special attribute __doc__ contains the docstring -// for an object (function, method, class, ...) if any is defined -// Otherwise, the attribute's value is None -bool -ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest) -{ - dest.clear(); - if (!item || !*item) - return false; - std::string command(item); - command += ".__doc__"; - - char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully - - if (ExecuteOneLineWithReturn (command.c_str(), - ScriptInterpreter::eScriptReturnTypeCharStrOrNone, - &result_ptr, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) - { - if (result_ptr) - dest.assign(result_ptr); - return true; - } - else - { - StreamString str_stream; - str_stream.Printf("Function %s was not found. Containing module might be missing.",item); - dest.assign(str_stream.GetData()); - return false; - } -} - -bool -ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, - std::string& dest) -{ - bool got_string = false; - dest.clear(); - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_short_help"; - - if (!cmd_obj_sp) - return false; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return false; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return false; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return false; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyString_Check(py_return)) - { - dest.assign(PyString_AsString(py_return)); - got_string = true; - } - } - Py_XDECREF(py_return); - - return got_string; -} - -uint32_t -ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) -{ - uint32_t result = 0; - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_flags"; - - if (!cmd_obj_sp) - return result; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return result; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return result; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return result; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyInt_Check(py_return)) - result = (uint32_t)PyInt_AsLong(py_return); - else if (PyLong_Check(py_return)) - result = (uint32_t)PyLong_AsLong(py_return); - } - Py_XDECREF(py_return); - - return result; -} - -bool -ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, - std::string& dest) -{ - bool got_string = false; - dest.clear(); - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_long_help"; - - if (!cmd_obj_sp) - return false; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return false; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return false; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return false; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyString_Check(py_return)) - { - dest.assign(PyString_AsString(py_return)); - got_string = true; - } - } - Py_XDECREF(py_return); - - return got_string; -} - -std::unique_ptr<ScriptInterpreterLocker> -ScriptInterpreterPython::AcquireInterpreterLock () -{ - std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, - Locker::FreeLock | Locker::TearDownSession)); - return py_lock; -} - -void -ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback, - SWIGBreakpointCallbackFunction swig_breakpoint_callback, - SWIGWatchpointCallbackFunction swig_watchpoint_callback, - SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, - SWIGPythonCreateSyntheticProvider swig_synthetic_script, - SWIGPythonCreateCommandObject swig_create_cmd, - SWIGPythonCalculateNumChildren swig_calc_children, - SWIGPythonGetChildAtIndex swig_get_child_index, - SWIGPythonGetIndexOfChildWithName swig_get_index_child, - SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , - SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, - SWIGPythonUpdateSynthProviderInstance swig_update_provider, - SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, - SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, - SWIGPythonCallCommand swig_call_command, - SWIGPythonCallCommandObject swig_call_command_object, - SWIGPythonCallModuleInit swig_call_module_init, - SWIGPythonCreateOSPlugin swig_create_os_plugin, - SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, - SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, - SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, - SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, - SWIGPython_GetDynamicSetting swig_plugin_get, - SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, - SWIGPythonCallThreadPlan swig_call_thread_plan) -{ - g_swig_init_callback = swig_init_callback; - g_swig_breakpoint_callback = swig_breakpoint_callback; - g_swig_watchpoint_callback = swig_watchpoint_callback; - g_swig_typescript_callback = swig_typescript_callback; - g_swig_synthetic_script = swig_synthetic_script; - g_swig_create_cmd = swig_create_cmd; - g_swig_calc_children = swig_calc_children; - g_swig_get_child_index = swig_get_child_index; - g_swig_get_index_child = swig_get_index_child; - g_swig_cast_to_sbvalue = swig_cast_to_sbvalue; - g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; - g_swig_update_provider = swig_update_provider; - g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; - g_swig_getvalue_provider = swig_getvalue_provider; - g_swig_call_command = swig_call_command; - 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_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; - g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; - g_swig_run_script_keyword_value = swig_run_script_keyword_value; - g_swig_plugin_get = swig_plugin_get; - g_swig_thread_plan_script = swig_thread_plan_script; - g_swig_call_thread_plan = swig_call_thread_plan; -} - -void -ScriptInterpreterPython::InitializePrivate () -{ - assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!"); - g_initialized = true; - - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - // Python will muck with STDIN terminal state, so save off any current TTY - // settings so we can restore them. - TerminalState stdin_tty_state; - stdin_tty_state.Save(STDIN_FILENO, false); - -#if defined(LLDB_PYTHON_HOME) - Py_SetPythonHome(LLDB_PYTHON_HOME); -#endif - PyGILState_STATE gstate; - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - bool threads_already_initialized = false; - if (PyEval_ThreadsInitialized ()) { - gstate = PyGILState_Ensure (); - if (log) - log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : ""); - threads_already_initialized = true; - } else { - // InitThreads acquires the GIL if it hasn't been called before. - PyEval_InitThreads (); - } - Py_InitializeEx (0); - - if (g_swig_init_callback) - g_swig_init_callback (); - - // Update the path python uses to search for modules to include the current directory. - - PyRun_SimpleString ("import sys"); - AddToSysPath(AddLocation::End, "."); - - FileSpec file_spec; - // Don't denormalize paths when calling file_spec.GetPath(). On platforms that use - // a backslash as the path separator, this will result in executing python code containing - // paths with unescaped backslashes. But Python also accepts forward slashes, so to make - // life easier we just use that. - if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) - AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); - if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) - AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); - - PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line"); - - if (threads_already_initialized) { - if (log) - log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : ""); - PyGILState_Release (gstate); - } else { - // We initialized the threads in this function, just unlock the GIL. - PyEval_SaveThread(); - } - - stdin_tty_state.Restore(); -} - -void -ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path) -{ - std::string path_copy; - - std::string statement; - if (location == AddLocation::Beginning) - { - statement.assign("sys.path.insert(0,\""); - statement.append (path); - statement.append ("\")"); - } - else - { - statement.assign("sys.path.append(\""); - statement.append(path); - statement.append("\")"); - } - PyRun_SimpleString (statement.c_str()); -} - - -//void -//ScriptInterpreterPython::Terminate () -//{ -// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling -// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers -// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls -// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate, -// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls -// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from -// // within Py_Finalize, which results in a seg fault. -// // -// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't -// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the -// // process exits). -// // -//// Py_Finalize (); -//} - -#endif // #ifdef LLDB_DISABLE_PYTHON diff --git a/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py index 10186f5a9d50..8ba539a2b0c9 100644 --- a/source/Interpreter/embedded_interpreter.py +++ b/source/Interpreter/embedded_interpreter.py @@ -1,7 +1,10 @@ -import __builtin__ +import sys +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins import code import lldb -import sys import traceback try: @@ -42,8 +45,8 @@ def setquit(): # "sys.exit(123)" global g_builtin_override_called g_builtin_override_called = False - __builtin__.quit = LLDBQuitter('quit') - __builtin__.exit = LLDBQuitter('exit') + builtins.quit = LLDBQuitter('quit') + builtins.exit = LLDBQuitter('exit') # When running one line, we might place the string to run in this string # in case it would be hard to correctly escape a string's contents @@ -94,7 +97,7 @@ def run_python_interpreter (local_dict): except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print 'Script exited with %s' %(e) + print('Script exited with %s' %(e)) def run_one_line (local_dict, input_string): global g_run_one_line_str @@ -109,4 +112,4 @@ def run_one_line (local_dict, input_string): except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print 'Script exited with %s' %(e) + print('Script exited with %s' %(e)) |