diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:31:46 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:37:19 +0000 |
commit | e8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch) | |
tree | 94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python | |
parent | bb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff) | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python')
3 files changed, 227 insertions, 132 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 6f040fdef09b..7c49502f1b57 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -451,7 +451,11 @@ Expected<llvm::StringRef> PythonString::AsUTF8() const { size_t PythonString::GetSize() const { if (IsValid()) { #if PY_MAJOR_VERSION >= 3 +#if PY_MINOR_VERSION >= 3 + return PyUnicode_GetLength(m_py_obj); +#else return PyUnicode_GetSize(m_py_obj); +#endif #else return PyString_Size(m_py_obj); #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 9f56b4fa60a5..6b53bd3a2edc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" +#include "lldb/lldb-enumerations.h" #if LLDB_ENABLE_PYTHON @@ -32,6 +33,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" +#include "lldb/Utility/ReproducerInstrumentation.h" #include "lldb/Utility/Timer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -127,6 +129,16 @@ extern "C" unsigned int LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name, lldb_private::SymbolContext *sym_ctx); +extern "C" void *LLDBSwigPythonCreateScriptedStopHook( + TargetSP target_sp, const char *python_class_name, + const char *session_dictionary_name, lldb_private::StructuredDataImpl *args, + lldb_private::Status &error); + +extern "C" bool +LLDBSwigPythonStopHookCallHandleStop(void *implementor, + lldb::ExecutionContextRefSP exc_ctx, + lldb::StreamSP stream); + extern "C" size_t LLDBSwigPython_CalculateNumChildren(void *implementor, uint32_t max); @@ -204,6 +216,12 @@ extern "C" void * LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, const lldb::TargetSP &target_sp); +static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { + ScriptInterpreter *script_interpreter = + debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython); + return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); +} + static bool g_initialized = false; namespace { @@ -420,6 +438,7 @@ ScriptInterpreterPythonImpl::Locker::Locker( : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { + repro::Recorder::PrivateThread(); DoAcquireLock(); if ((on_entry & InitSession) == InitSession) { if (!DoInitSession(on_entry, in, out, err)) { @@ -982,8 +1001,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( } void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + LLDB_SCOPED_TIMER(); Debugger &debugger = m_debugger; @@ -1815,11 +1833,10 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( return {}; Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); ScriptInterpreterPythonImpl *python_interpreter = - static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); + GetPythonInterpreter(debugger); - if (!script_interpreter) + if (!python_interpreter) return {}; void *ret_val; @@ -1919,11 +1936,10 @@ ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( return StructuredData::GenericSP(); Debugger &debugger = bkpt_sp->GetTarget().GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); ScriptInterpreterPythonImpl *python_interpreter = - static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); + GetPythonInterpreter(debugger); - if (!script_interpreter) + if (!python_interpreter) return StructuredData::GenericSP(); void *ret_val; @@ -1979,6 +1995,59 @@ ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( return lldb::eSearchDepthModule; } +StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( + TargetSP target_sp, const char *class_name, StructuredDataImpl *args_data, + Status &error) { + + if (!target_sp) { + error.SetErrorString("No target for scripted stop-hook."); + return StructuredData::GenericSP(); + } + + if (class_name == nullptr || class_name[0] == '\0') { + error.SetErrorString("No class name for scripted stop-hook."); + return StructuredData::GenericSP(); + } + + ScriptInterpreterPythonImpl *python_interpreter = + GetPythonInterpreter(m_debugger); + + if (!python_interpreter) { + error.SetErrorString("No script interpreter for scripted stop-hook."); + return StructuredData::GenericSP(); + } + + void *ret_val; + + { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + + ret_val = LLDBSwigPythonCreateScriptedStopHook( + target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), + args_data, error); + } + + return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); +} + +bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( + StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx, + lldb::StreamSP stream_sp) { + assert(implementor_sp && + "can't call a stop hook with an invalid implementor"); + assert(stream_sp && "can't call a stop hook with an invalid stream"); + + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + + lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx)); + + bool ret_val = LLDBSwigPythonStopHookCallHandleStop( + implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp); + return ret_val; +} + StructuredData::ObjectSP ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { @@ -2039,11 +2108,10 @@ ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( return StructuredData::ObjectSP(); Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); ScriptInterpreterPythonImpl *python_interpreter = - (ScriptInterpreterPythonImpl *)script_interpreter; + GetPythonInterpreter(debugger); - if (!script_interpreter) + if (!python_interpreter) return StructuredData::ObjectSP(); void *ret_val = nullptr; @@ -2151,8 +2219,7 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) { - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + LLDB_SCOPED_TIMER(); if (!valobj.get()) { retval.assign("<no object>"); @@ -2210,11 +2277,10 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( return true; Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); ScriptInterpreterPythonImpl *python_interpreter = - (ScriptInterpreterPythonImpl *)script_interpreter; + GetPythonInterpreter(debugger); - if (!script_interpreter) + if (!python_interpreter) return true; if (python_function_name && python_function_name[0]) { @@ -2276,11 +2342,10 @@ bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction( return true; Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); ScriptInterpreterPythonImpl *python_interpreter = - (ScriptInterpreterPythonImpl *)script_interpreter; + GetPythonInterpreter(debugger); - if (!script_interpreter) + if (!python_interpreter) return true; if (python_function_name && python_function_name[0]) { @@ -2669,7 +2734,10 @@ uint64_t replace_all(std::string &str, const std::string &oldStr, bool ScriptInterpreterPythonImpl::LoadScriptingModule( const char *pathname, bool init_session, lldb_private::Status &error, - StructuredData::ObjectSP *module_sp) { + StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) { + namespace fs = llvm::sys::fs; + namespace path = llvm::sys::path; + if (!pathname || !pathname[0]) { error.SetErrorString("invalid pathname"); return false; @@ -2677,24 +2745,55 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); - { - FileSpec target_file(pathname); - FileSystem::Instance().Resolve(target_file); - FileSystem::Instance().Collect(target_file); - std::string basename(target_file.GetFilename().GetCString()); + // Before executing Python code, lock the GIL. + Locker py_lock(this, + Locker::AcquireLock | + (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, + Locker::FreeAcquiredLock | + (init_session ? Locker::TearDownSession : 0)); + + auto ExtendSysPath = [this](std::string directory) -> llvm::Error { + if (directory.empty()) { + return llvm::make_error<llvm::StringError>( + "invalid directory name", llvm::inconvertibleErrorCode()); + } + + replace_all(directory, "\\", "\\\\"); + replace_all(directory, "'", "\\'"); + // 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) { + return llvm::make_error<llvm::StringError>( + "Python sys.path handling failed", llvm::inconvertibleErrorCode()); + } + + return llvm::Error::success(); + }; + + std::string module_name(pathname); + + if (extra_search_dir) { + if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) { + error = std::move(e); + return false; + } + } else { + FileSpec module_file(pathname); + FileSystem::Instance().Resolve(module_file); + FileSystem::Instance().Collect(module_file); - // Before executing Python code, lock the GIL. - Locker py_lock(this, - Locker::AcquireLock | - (init_session ? Locker::InitSession : 0) | - Locker::NoSTDIN, - Locker::FreeAcquiredLock | - (init_session ? Locker::TearDownSession : 0)); - namespace fs = llvm::sys::fs; fs::file_status st; - std::error_code ec = status(target_file.GetPath(), st); + std::error_code ec = status(module_file.GetPath(), st); if (ec || st.type() == fs::file_type::status_error || st.type() == fs::file_type::type_unknown || @@ -2705,113 +2804,98 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( error.SetErrorString("invalid pathname"); return false; } - basename = pathname; // not a filename, probably a package of some sort, - // let it go through + // Not a filename, probably a package of some sort, let it go through. } else if (is_directory(st) || is_regular_file(st)) { - if (target_file.GetDirectory().IsEmpty()) { + if (module_file.GetDirectory().IsEmpty()) { error.SetErrorString("invalid directory name"); return false; } - - std::string directory = target_file.GetDirectory().GetCString(); - replace_all(directory, "\\", "\\\\"); - 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"); + if (llvm::Error e = + ExtendSysPath(module_file.GetDirectory().GetCString())) { + error = std::move(e); return false; } - - // strip .py or .pyc extension - ConstString extension = target_file.GetFileNameExtension(); - if (extension) { - if (llvm::StringRef(extension.GetCString()) == ".py") - basename.resize(basename.length() - 3); - else if (llvm::StringRef(extension.GetCString()) == ".pyc") - basename.resize(basename.length() - 4); - } + module_name = module_file.GetFilename().GetCString(); } 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(), - ScriptInterpreterPythonImpl::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(PythonString(basename)) - .IsAllocated(); - - bool was_imported = (was_imported_globally || was_imported_locally); - - // now actually do the import - command_stream.Clear(); - - if (was_imported) { - if (!was_imported_locally) - command_stream.Printf("import %s ; reload_module(%s)", basename.c_str(), - basename.c_str()); - else - command_stream.Printf("reload_module(%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; + // Strip .py or .pyc extension + llvm::StringRef extension = llvm::sys::path::extension(module_name); + if (!extension.empty()) { + if (extension == ".py") + module_name.resize(module_name.length() - 3); + else if (extension == ".pyc") + module_name.resize(module_name.length() - 4); + } - // if we are here, everything worked - // call __lldb_init_module(debugger,dict) - if (!LLDBSwigPythonCallModuleInit(basename.c_str(), - m_dictionary_name.c_str(), debugger_sp)) { - error.SetErrorString("calling __lldb_init_module failed"); - return false; - } + // check if the module is already import-ed + StreamString command_stream; + command_stream.Clear(); + command_stream.Printf("sys.modules.__contains__('%s')", module_name.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(), + ScriptInterpreterPythonImpl::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)", module_name.c_str()); + bool was_imported_locally = GetSessionDictionary() + .GetItemForKey(PythonString(module_name)) + .IsAllocated(); + + bool was_imported = (was_imported_globally || was_imported_locally); + + // now actually do the import + command_stream.Clear(); + + if (was_imported) { + if (!was_imported_locally) + command_stream.Printf("import %s ; reload_module(%s)", + module_name.c_str(), module_name.c_str()); + else + command_stream.Printf("reload_module(%s)", module_name.c_str()); + } else + command_stream.Printf("import %s", module_name.c_str()); + + error = ExecuteMultipleLines(command_stream.GetData(), + ScriptInterpreter::ExecuteScriptOptions() + .SetEnableIO(false) + .SetSetLLDBGlobals(false)); + if (error.Fail()) + 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 = std::make_shared<StructuredPythonObject>(module_pyobj); - } + // if we are here, everything worked + // call __lldb_init_module(debugger,dict) + if (!LLDBSwigPythonCallModuleInit(module_name.c_str(), + m_dictionary_name.c_str(), debugger_sp)) { + error.SetErrorString("calling __lldb_init_module failed"); + return false; + } - return true; + if (module_sp) { + // everything went just great, now set the module object + command_stream.Clear(); + command_stream.Printf("%s", module_name.c_str()); + void *module_pyobj = nullptr; + if (ExecuteOneLineWithReturn( + command_stream.GetData(), + ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) && + module_pyobj) + *module_sp = std::make_shared<StructuredPythonObject>(module_pyobj); } + + return true; } bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) { @@ -3154,8 +3238,7 @@ void ScriptInterpreterPythonImpl::InitializePrivate() { g_initialized = true; - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + LLDB_SCOPED_TIMER(); // RAII-based initialization which correctly handles multiple-initialization, // version- specific differences among Python 2 and Python 3, and saving and diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 22b2c8152eac..45dad4217005 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -106,6 +106,14 @@ public: StructuredData::GenericSP implementor_sp) override; StructuredData::GenericSP + CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, + StructuredDataImpl *args_data, Status &error) override; + + bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, + ExecutionContext &exc_ctx, + lldb::StreamSP stream_sp) override; + + StructuredData::GenericSP CreateFrameRecognizer(const char *class_name) override; lldb::ValueObjectListSP @@ -223,10 +231,10 @@ public: bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value, std::string &output, Status &error) override; - bool - LoadScriptingModule(const char *filename, bool init_session, - lldb_private::Status &error, - StructuredData::ObjectSP *module_sp = nullptr) override; + bool LoadScriptingModule(const char *filename, bool init_session, + lldb_private::Status &error, + StructuredData::ObjectSP *module_sp = nullptr, + FileSpec extra_search_dir = {}) override; bool IsReservedWord(const char *word) override; |