Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
39638 views
//===-- ScriptInterpreterPython.cpp ---------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Host/Config.h"9#include "lldb/lldb-enumerations.h"1011#if LLDB_ENABLE_PYTHON1213// LLDB Python header must be included first14#include "lldb-python.h"1516#include "Interfaces/OperatingSystemPythonInterface.h"17#include "Interfaces/ScriptedPlatformPythonInterface.h"18#include "Interfaces/ScriptedProcessPythonInterface.h"19#include "Interfaces/ScriptedThreadPlanPythonInterface.h"20#include "Interfaces/ScriptedThreadPythonInterface.h"21#include "PythonDataObjects.h"22#include "PythonReadline.h"23#include "SWIGPythonBridge.h"24#include "ScriptInterpreterPythonImpl.h"2526#include "lldb/API/SBError.h"27#include "lldb/API/SBExecutionContext.h"28#include "lldb/API/SBFrame.h"29#include "lldb/API/SBValue.h"30#include "lldb/Breakpoint/StoppointCallbackContext.h"31#include "lldb/Breakpoint/WatchpointOptions.h"32#include "lldb/Core/Debugger.h"33#include "lldb/Core/PluginManager.h"34#include "lldb/Core/ThreadedCommunication.h"35#include "lldb/Core/ValueObject.h"36#include "lldb/DataFormatters/TypeSummary.h"37#include "lldb/Host/FileSystem.h"38#include "lldb/Host/HostInfo.h"39#include "lldb/Host/Pipe.h"40#include "lldb/Interpreter/CommandInterpreter.h"41#include "lldb/Interpreter/CommandReturnObject.h"42#include "lldb/Target/Thread.h"43#include "lldb/Target/ThreadPlan.h"44#include "lldb/Utility/Instrumentation.h"45#include "lldb/Utility/LLDBLog.h"46#include "lldb/Utility/Timer.h"47#include "llvm/ADT/STLExtras.h"48#include "llvm/ADT/StringRef.h"49#include "llvm/Support/Error.h"50#include "llvm/Support/FileSystem.h"51#include "llvm/Support/FormatAdapters.h"5253#include <cstdio>54#include <cstdlib>55#include <memory>56#include <mutex>57#include <optional>58#include <string>5960using namespace lldb;61using namespace lldb_private;62using namespace lldb_private::python;63using llvm::Expected;6465LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)6667// Defined in the SWIG source file68extern "C" PyObject *PyInit__lldb(void);6970#define LLDBSwigPyInit PyInit__lldb7172#if defined(_WIN32)73// Don't mess with the signal handlers on Windows.74#define LLDB_USE_PYTHON_SET_INTERRUPT 075#else76// PyErr_SetInterrupt was introduced in 3.2.77#define LLDB_USE_PYTHON_SET_INTERRUPT \78(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)79#endif8081static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) {82ScriptInterpreter *script_interpreter =83debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython);84return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);85}8687namespace {8889// Initializing Python is not a straightforward process. We cannot control90// what external code may have done before getting to this point in LLDB,91// including potentially having already initialized Python, so we need to do a92// lot of work to ensure that the existing state of the system is maintained93// across our initialization. We do this by using an RAII pattern where we94// save off initial state at the beginning, and restore it at the end95struct InitializePythonRAII {96public:97InitializePythonRAII() {98InitializePythonHome();99100// The table of built-in modules can only be extended before Python is101// initialized.102if (!Py_IsInitialized()) {103#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE104// Python's readline is incompatible with libedit being linked into lldb.105// Provide a patched version local to the embedded interpreter.106bool ReadlinePatched = false;107for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {108if (strcmp(p->name, "readline") == 0) {109p->initfunc = initlldb_readline;110break;111}112}113if (!ReadlinePatched) {114PyImport_AppendInittab("readline", initlldb_readline);115ReadlinePatched = true;116}117#endif118119// Register _lldb as a built-in module.120PyImport_AppendInittab("_lldb", LLDBSwigPyInit);121}122123// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for124// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you125// call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.126#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)127Py_InitializeEx(0);128InitializeThreadsPrivate();129#else130InitializeThreadsPrivate();131Py_InitializeEx(0);132#endif133}134135~InitializePythonRAII() {136if (m_was_already_initialized) {137Log *log = GetLog(LLDBLog::Script);138LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",139m_gil_state == PyGILState_UNLOCKED ? "un" : "");140PyGILState_Release(m_gil_state);141} else {142// We initialized the threads in this function, just unlock the GIL.143PyEval_SaveThread();144}145}146147private:148void InitializePythonHome() {149#if LLDB_EMBED_PYTHON_HOME150typedef wchar_t *str_type;151static str_type g_python_home = []() -> str_type {152const char *lldb_python_home = LLDB_PYTHON_HOME;153const char *absolute_python_home = nullptr;154llvm::SmallString<64> path;155if (llvm::sys::path::is_absolute(lldb_python_home)) {156absolute_python_home = lldb_python_home;157} else {158FileSpec spec = HostInfo::GetShlibDir();159if (!spec)160return nullptr;161spec.GetPath(path);162llvm::sys::path::append(path, lldb_python_home);163absolute_python_home = path.c_str();164}165size_t size = 0;166return Py_DecodeLocale(absolute_python_home, &size);167}();168if (g_python_home != nullptr) {169Py_SetPythonHome(g_python_home);170}171#endif172}173174void InitializeThreadsPrivate() {175// Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside itself,176// so there is no way to determine whether the embedded interpreter177// was already initialized by some external code. `PyEval_ThreadsInitialized`178// would always return `true` and `PyGILState_Ensure/Release` flow would be179// executed instead of unlocking GIL with `PyEval_SaveThread`. When180// an another thread calls `PyGILState_Ensure` it would get stuck in deadlock.181#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION > 3)182// The only case we should go further and acquire the GIL: it is unlocked.183if (PyGILState_Check())184return;185#endif186187// `PyEval_ThreadsInitialized` was deprecated in Python 3.9 and removed in188// Python 3.13. It has been returning `true` always since Python 3.7.189#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3)190if (PyEval_ThreadsInitialized()) {191#else192if (true) {193#endif194Log *log = GetLog(LLDBLog::Script);195196m_was_already_initialized = true;197m_gil_state = PyGILState_Ensure();198LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n",199m_gil_state == PyGILState_UNLOCKED ? "un" : "");200201// `PyEval_InitThreads` was deprecated in Python 3.9 and removed in202// Python 3.13.203#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3)204return;205}206207// InitThreads acquires the GIL if it hasn't been called before.208PyEval_InitThreads();209#else210}211#endif212}213214PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;215bool m_was_already_initialized = false;216};217218#if LLDB_USE_PYTHON_SET_INTERRUPT219/// Saves the current signal handler for the specified signal and restores220/// it at the end of the current scope.221struct RestoreSignalHandlerScope {222/// The signal handler.223struct sigaction m_prev_handler;224int m_signal_code;225RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) {226// Initialize sigaction to their default state.227std::memset(&m_prev_handler, 0, sizeof(m_prev_handler));228// Don't install a new handler, just read back the old one.229struct sigaction *new_handler = nullptr;230int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler);231lldbassert(signal_err == 0 && "sigaction failed to read handler");232}233~RestoreSignalHandlerScope() {234int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr);235lldbassert(signal_err == 0 && "sigaction failed to restore old handler");236}237};238#endif239} // namespace240241void ScriptInterpreterPython::ComputePythonDirForApple(242llvm::SmallVectorImpl<char> &path) {243auto style = llvm::sys::path::Style::posix;244245llvm::StringRef path_ref(path.begin(), path.size());246auto rbegin = llvm::sys::path::rbegin(path_ref, style);247auto rend = llvm::sys::path::rend(path_ref);248auto framework = std::find(rbegin, rend, "LLDB.framework");249if (framework == rend) {250ComputePythonDir(path);251return;252}253path.resize(framework - rend);254llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");255}256257void ScriptInterpreterPython::ComputePythonDir(258llvm::SmallVectorImpl<char> &path) {259// Build the path by backing out of the lib dir, then building with whatever260// the real python interpreter uses. (e.g. lib for most, lib64 on RHEL261// x86_64, or bin on Windows).262llvm::sys::path::remove_filename(path);263llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);264265#if defined(_WIN32)266// This will be injected directly through FileSpec.SetDirectory(),267// so we need to normalize manually.268std::replace(path.begin(), path.end(), '\\', '/');269#endif270}271272FileSpec ScriptInterpreterPython::GetPythonDir() {273static FileSpec g_spec = []() {274FileSpec spec = HostInfo::GetShlibDir();275if (!spec)276return FileSpec();277llvm::SmallString<64> path;278spec.GetPath(path);279280#if defined(__APPLE__)281ComputePythonDirForApple(path);282#else283ComputePythonDir(path);284#endif285spec.SetDirectory(path);286return spec;287}();288return g_spec;289}290291static const char GetInterpreterInfoScript[] = R"(292import os293import sys294295def main(lldb_python_dir, python_exe_relative_path):296info = {297"lldb-pythonpath": lldb_python_dir,298"language": "python",299"prefix": sys.prefix,300"executable": os.path.join(sys.prefix, python_exe_relative_path)301}302return info303)";304305static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;306307StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {308GIL gil;309FileSpec python_dir_spec = GetPythonDir();310if (!python_dir_spec)311return nullptr;312PythonScript get_info(GetInterpreterInfoScript);313auto info_json = unwrapIgnoringErrors(314As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),315PythonString(python_exe_relative_path))));316if (!info_json)317return nullptr;318return info_json.CreateStructuredDictionary();319}320321void ScriptInterpreterPython::SharedLibraryDirectoryHelper(322FileSpec &this_file) {323// When we're loaded from python, this_file will point to the file inside the324// python package directory. Replace it with the one in the lib directory.325#ifdef _WIN32326// On windows, we need to manually back out of the python tree, and go into327// the bin directory. This is pretty much the inverse of what ComputePythonDir328// does.329if (this_file.GetFileNameExtension() == ".pyd") {330this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd331this_file.RemoveLastPathComponent(); // lldb332llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;333for (auto it = llvm::sys::path::begin(libdir),334end = llvm::sys::path::end(libdir);335it != end; ++it)336this_file.RemoveLastPathComponent();337this_file.AppendPathComponent("bin");338this_file.AppendPathComponent("liblldb.dll");339}340#else341// The python file is a symlink, so we can find the real library by resolving342// it. We can do this unconditionally.343FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);344#endif345}346347llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() {348return "Embedded Python interpreter";349}350351void ScriptInterpreterPython::Initialize() {352static llvm::once_flag g_once_flag;353llvm::call_once(g_once_flag, []() {354PluginManager::RegisterPlugin(GetPluginNameStatic(),355GetPluginDescriptionStatic(),356lldb::eScriptLanguagePython,357ScriptInterpreterPythonImpl::CreateInstance);358ScriptInterpreterPythonImpl::Initialize();359});360}361362void ScriptInterpreterPython::Terminate() {}363364ScriptInterpreterPythonImpl::Locker::Locker(365ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,366uint16_t on_leave, FileSP in, FileSP out, FileSP err)367: ScriptInterpreterLocker(),368m_teardown_session((on_leave & TearDownSession) == TearDownSession),369m_python_interpreter(py_interpreter) {370DoAcquireLock();371if ((on_entry & InitSession) == InitSession) {372if (!DoInitSession(on_entry, in, out, err)) {373// Don't teardown the session if we didn't init it.374m_teardown_session = false;375}376}377}378379bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() {380Log *log = GetLog(LLDBLog::Script);381m_GILState = PyGILState_Ensure();382LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked",383m_GILState == PyGILState_UNLOCKED ? "un" : "");384385// we need to save the thread state when we first start the command because386// we might decide to interrupt it while some action is taking place outside387// of Python (e.g. printing to screen, waiting for the network, ...) in that388// case, _PyThreadState_Current will be NULL - and we would be unable to set389// the asynchronous exception - not a desirable situation390m_python_interpreter->SetThreadState(PyThreadState_Get());391m_python_interpreter->IncrementLockCount();392return true;393}394395bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,396FileSP in, FileSP out,397FileSP err) {398if (!m_python_interpreter)399return false;400return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);401}402403bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {404Log *log = GetLog(LLDBLog::Script);405LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",406m_GILState == PyGILState_UNLOCKED ? "un" : "");407PyGILState_Release(m_GILState);408m_python_interpreter->DecrementLockCount();409return true;410}411412bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {413if (!m_python_interpreter)414return false;415m_python_interpreter->LeaveSession();416return true;417}418419ScriptInterpreterPythonImpl::Locker::~Locker() {420if (m_teardown_session)421DoTearDownSession();422DoFreeLock();423}424425ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)426: ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(),427m_saved_stderr(), m_main_module(),428m_session_dict(PyInitialValue::Invalid),429m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),430m_run_one_line_str_global(),431m_dictionary_name(m_debugger.GetInstanceName()),432m_active_io_handler(eIOHandlerNone), m_session_is_active(false),433m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),434m_command_thread_state(nullptr) {435436m_dictionary_name.append("_dict");437StreamString run_string;438run_string.Printf("%s = dict()", m_dictionary_name.c_str());439440Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);441PyRun_SimpleString(run_string.GetData());442443run_string.Clear();444run_string.Printf(445"run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')",446m_dictionary_name.c_str());447PyRun_SimpleString(run_string.GetData());448449// Reloading modules requires a different syntax in Python 2 and Python 3.450// This provides a consistent syntax no matter what version of Python.451run_string.Clear();452run_string.Printf("run_one_line (%s, 'from importlib import reload as reload_module')",453m_dictionary_name.c_str());454PyRun_SimpleString(run_string.GetData());455456// WARNING: temporary code that loads Cocoa formatters - this should be done457// on a per-platform basis rather than loading the whole set and letting the458// individual formatter classes exploit APIs to check whether they can/cannot459// do their task460run_string.Clear();461run_string.Printf(462"run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",463m_dictionary_name.c_str());464PyRun_SimpleString(run_string.GetData());465run_string.Clear();466467run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "468"lldb.embedded_interpreter import run_python_interpreter; "469"from lldb.embedded_interpreter import run_one_line')",470m_dictionary_name.c_str());471PyRun_SimpleString(run_string.GetData());472run_string.Clear();473474run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64475"')",476m_dictionary_name.c_str(), m_debugger.GetID());477PyRun_SimpleString(run_string.GetData());478}479480ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() {481// the session dictionary may hold objects with complex state which means482// that they may need to be torn down with some level of smarts and that, in483// turn, requires a valid thread state force Python to procure itself such a484// thread state, nuke the session dictionary and then release it for others485// to use and proceed with the rest of the shutdown486auto gil_state = PyGILState_Ensure();487m_session_dict.Reset();488PyGILState_Release(gil_state);489}490491void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler,492bool interactive) {493const char *instructions = nullptr;494495switch (m_active_io_handler) {496case eIOHandlerNone:497break;498case eIOHandlerBreakpoint:499instructions = R"(Enter your Python command(s). Type 'DONE' to end.500def function (frame, bp_loc, internal_dict):501"""frame: the lldb.SBFrame for the location at which you stopped502bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information503internal_dict: an LLDB support object not to be used"""504)";505break;506case eIOHandlerWatchpoint:507instructions = "Enter your Python command(s). Type 'DONE' to end.\n";508break;509}510511if (instructions) {512StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());513if (output_sp && interactive) {514output_sp->PutCString(instructions);515output_sp->Flush();516}517}518}519520void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,521std::string &data) {522io_handler.SetIsDone(true);523bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();524525switch (m_active_io_handler) {526case eIOHandlerNone:527break;528case eIOHandlerBreakpoint: {529std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =530(std::vector<std::reference_wrapper<BreakpointOptions>> *)531io_handler.GetUserData();532for (BreakpointOptions &bp_options : *bp_options_vec) {533534auto data_up = std::make_unique<CommandDataPython>();535if (!data_up)536break;537data_up->user_source.SplitIntoLines(data);538539if (GenerateBreakpointCommandCallbackData(data_up->user_source,540data_up->script_source,541/*has_extra_args=*/false,542/*is_callback=*/false)543.Success()) {544auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(545std::move(data_up));546bp_options.SetCallback(547ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);548} else if (!batch_mode) {549StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();550if (error_sp) {551error_sp->Printf("Warning: No command attached to breakpoint.\n");552error_sp->Flush();553}554}555}556m_active_io_handler = eIOHandlerNone;557} break;558case eIOHandlerWatchpoint: {559WatchpointOptions *wp_options =560(WatchpointOptions *)io_handler.GetUserData();561auto data_up = std::make_unique<WatchpointOptions::CommandData>();562data_up->user_source.SplitIntoLines(data);563564if (GenerateWatchpointCommandCallbackData(data_up->user_source,565data_up->script_source,566/*is_callback=*/false)) {567auto baton_sp =568std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));569wp_options->SetCallback(570ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);571} else if (!batch_mode) {572StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();573if (error_sp) {574error_sp->Printf("Warning: No command attached to breakpoint.\n");575error_sp->Flush();576}577}578m_active_io_handler = eIOHandlerNone;579} break;580}581}582583lldb::ScriptInterpreterSP584ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {585return std::make_shared<ScriptInterpreterPythonImpl>(debugger);586}587588void ScriptInterpreterPythonImpl::LeaveSession() {589Log *log = GetLog(LLDBLog::Script);590if (log)591log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");592593// Unset the LLDB global variables.594PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "595"= None; lldb.thread = None; lldb.frame = None");596597// checking that we have a valid thread state - since we use our own598// threading and locking in some (rare) cases during cleanup Python may end599// up believing we have no thread state and PyImport_AddModule will crash if600// that is the case - since that seems to only happen when destroying the601// SBDebugger, we can make do without clearing up stdout and stderr602if (PyThreadState_GetDict()) {603PythonDictionary &sys_module_dict = GetSysModuleDictionary();604if (sys_module_dict.IsValid()) {605if (m_saved_stdin.IsValid()) {606sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);607m_saved_stdin.Reset();608}609if (m_saved_stdout.IsValid()) {610sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);611m_saved_stdout.Reset();612}613if (m_saved_stderr.IsValid()) {614sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);615m_saved_stderr.Reset();616}617}618}619620m_session_is_active = false;621}622623bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp,624const char *py_name,625PythonObject &save_file,626const char *mode) {627if (!file_sp || !*file_sp) {628save_file.Reset();629return false;630}631File &file = *file_sp;632633// Flush the file before giving it to python to avoid interleaved output.634file.Flush();635636PythonDictionary &sys_module_dict = GetSysModuleDictionary();637638auto new_file = PythonFile::FromFile(file, mode);639if (!new_file) {640llvm::consumeError(new_file.takeError());641return false;642}643644save_file = sys_module_dict.GetItemForKey(PythonString(py_name));645646sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());647return true;648}649650bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,651FileSP in_sp, FileSP out_sp,652FileSP err_sp) {653// If we have already entered the session, without having officially 'left'654// it, then there is no need to 'enter' it again.655Log *log = GetLog(LLDBLog::Script);656if (m_session_is_active) {657LLDB_LOGF(658log,659"ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16660") session is already active, returning without doing anything",661on_entry_flags);662return false;663}664665LLDB_LOGF(666log,667"ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",668on_entry_flags);669670m_session_is_active = true;671672StreamString run_string;673674if (on_entry_flags & Locker::InitGlobals) {675run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,676m_dictionary_name.c_str(), m_debugger.GetID());677run_string.Printf(678"; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",679m_debugger.GetID());680run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");681run_string.PutCString("; lldb.process = lldb.target.GetProcess()");682run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");683run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");684run_string.PutCString("')");685} else {686// If we aren't initing the globals, we should still always set the687// debugger (since that is always unique.)688run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,689m_dictionary_name.c_str(), m_debugger.GetID());690run_string.Printf(691"; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",692m_debugger.GetID());693run_string.PutCString("')");694}695696PyRun_SimpleString(run_string.GetData());697run_string.Clear();698699PythonDictionary &sys_module_dict = GetSysModuleDictionary();700if (sys_module_dict.IsValid()) {701lldb::FileSP top_in_sp;702lldb::StreamFileSP top_out_sp, top_err_sp;703if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)704m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,705top_err_sp);706707if (on_entry_flags & Locker::NoSTDIN) {708m_saved_stdin.Reset();709} else {710if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) {711if (top_in_sp)712SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r");713}714}715716if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) {717if (top_out_sp)718SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w");719}720721if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) {722if (top_err_sp)723SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w");724}725}726727if (PyErr_Occurred())728PyErr_Clear();729730return true;731}732733PythonModule &ScriptInterpreterPythonImpl::GetMainModule() {734if (!m_main_module.IsValid())735m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__"));736return m_main_module;737}738739PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {740if (m_session_dict.IsValid())741return m_session_dict;742743PythonObject &main_module = GetMainModule();744if (!main_module.IsValid())745return m_session_dict;746747PythonDictionary main_dict(PyRefType::Borrowed,748PyModule_GetDict(main_module.get()));749if (!main_dict.IsValid())750return m_session_dict;751752m_session_dict = unwrapIgnoringErrors(753As<PythonDictionary>(main_dict.GetItem(m_dictionary_name)));754return m_session_dict;755}756757PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {758if (m_sys_module_dict.IsValid())759return m_sys_module_dict;760PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));761m_sys_module_dict = sys_module.GetDictionary();762return m_sys_module_dict;763}764765llvm::Expected<unsigned>766ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(767const llvm::StringRef &callable_name) {768if (callable_name.empty()) {769return llvm::createStringError(770llvm::inconvertibleErrorCode(),771"called with empty callable name.");772}773Locker py_lock(this, Locker::AcquireLock |774Locker::InitSession |775Locker::NoSTDIN);776auto dict = PythonModule::MainModule()777.ResolveName<PythonDictionary>(m_dictionary_name);778auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(779callable_name, dict);780if (!pfunc.IsAllocated()) {781return llvm::createStringError(782llvm::inconvertibleErrorCode(),783"can't find callable: %s", callable_name.str().c_str());784}785llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();786if (!arg_info)787return arg_info.takeError();788return arg_info.get().max_positional_args;789}790791static std::string GenerateUniqueName(const char *base_name_wanted,792uint32_t &functions_counter,793const void *name_token = nullptr) {794StreamString sstr;795796if (!base_name_wanted)797return std::string();798799if (!name_token)800sstr.Printf("%s_%d", base_name_wanted, functions_counter++);801else802sstr.Printf("%s_%p", base_name_wanted, name_token);803804return std::string(sstr.GetString());805}806807bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() {808if (m_run_one_line_function.IsValid())809return true;810811PythonObject module(PyRefType::Borrowed,812PyImport_AddModule("lldb.embedded_interpreter"));813if (!module.IsValid())814return false;815816PythonDictionary module_dict(PyRefType::Borrowed,817PyModule_GetDict(module.get()));818if (!module_dict.IsValid())819return false;820821m_run_one_line_function =822module_dict.GetItemForKey(PythonString("run_one_line"));823m_run_one_line_str_global =824module_dict.GetItemForKey(PythonString("g_run_one_line_str"));825return m_run_one_line_function.IsValid();826}827828bool ScriptInterpreterPythonImpl::ExecuteOneLine(829llvm::StringRef command, CommandReturnObject *result,830const ExecuteScriptOptions &options) {831std::string command_str = command.str();832833if (!m_valid_session)834return false;835836if (!command.empty()) {837// We want to call run_one_line, passing in the dictionary and the command838// string. We cannot do this through PyRun_SimpleString here because the839// command string may contain escaped characters, and putting it inside840// another string to pass to PyRun_SimpleString messes up the escaping. So841// we use the following more complicated method to pass the command string842// directly down to Python.843llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>844io_redirect_or_error = ScriptInterpreterIORedirect::Create(845options.GetEnableIO(), m_debugger, result);846if (!io_redirect_or_error) {847if (result)848result->AppendErrorWithFormatv(849"failed to redirect I/O: {0}\n",850llvm::fmt_consume(io_redirect_or_error.takeError()));851else852llvm::consumeError(io_redirect_or_error.takeError());853return false;854}855856ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;857858bool success = false;859{860// WARNING! It's imperative that this RAII scope be as tight as861// possible. In particular, the scope must end *before* we try to join862// the read thread. The reason for this is that a pre-requisite for863// joining the read thread is that we close the write handle (to break864// the pipe and cause it to wake up and exit). But acquiring the GIL as865// below will redirect Python's stdio to use this same handle. If we866// close the handle while Python is still using it, bad things will867// happen.868Locker locker(869this,870Locker::AcquireLock | Locker::InitSession |871(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |872((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),873Locker::FreeAcquiredLock | Locker::TearDownSession,874io_redirect.GetInputFile(), io_redirect.GetOutputFile(),875io_redirect.GetErrorFile());876877// Find the correct script interpreter dictionary in the main module.878PythonDictionary &session_dict = GetSessionDictionary();879if (session_dict.IsValid()) {880if (GetEmbeddedInterpreterModuleObjects()) {881if (PyCallable_Check(m_run_one_line_function.get())) {882PythonObject pargs(883PyRefType::Owned,884Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));885if (pargs.IsValid()) {886PythonObject return_value(887PyRefType::Owned,888PyObject_CallObject(m_run_one_line_function.get(),889pargs.get()));890if (return_value.IsValid())891success = true;892else if (options.GetMaskoutErrors() && PyErr_Occurred()) {893PyErr_Print();894PyErr_Clear();895}896}897}898}899}900901io_redirect.Flush();902}903904if (success)905return true;906907// The one-liner failed. Append the error message.908if (result) {909result->AppendErrorWithFormat(910"python failed attempting to evaluate '%s'\n", command_str.c_str());911}912return false;913}914915if (result)916result->AppendError("empty command passed to python\n");917return false;918}919920void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() {921LLDB_SCOPED_TIMER();922923Debugger &debugger = m_debugger;924925// At the moment, the only time the debugger does not have an input file926// handle is when this is called directly from Python, in which case it is927// both dangerous and unnecessary (not to mention confusing) to try to embed928// a running interpreter loop inside the already running Python interpreter929// loop, so we won't do it.930931if (!debugger.GetInputFile().IsValid())932return;933934IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));935if (io_handler_sp) {936debugger.RunIOHandlerAsync(io_handler_sp);937}938}939940bool ScriptInterpreterPythonImpl::Interrupt() {941#if LLDB_USE_PYTHON_SET_INTERRUPT942// If the interpreter isn't evaluating any Python at the moment then return943// false to signal that this function didn't handle the interrupt and the944// next component should try handling it.945if (!IsExecutingPython())946return false;947948// Tell Python that it should pretend to have received a SIGINT.949PyErr_SetInterrupt();950// PyErr_SetInterrupt has no way to return an error so we can only pretend the951// signal got successfully handled and return true.952// Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but953// the error handling is limited to checking the arguments which would be954// just our (hardcoded) input signal code SIGINT, so that's not useful at all.955return true;956#else957Log *log = GetLog(LLDBLog::Script);958959if (IsExecutingPython()) {960PyThreadState *state = PyThreadState_GET();961if (!state)962state = GetThreadState();963if (state) {964long tid = state->thread_id;965PyThreadState_Swap(state);966int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);967LLDB_LOGF(log,968"ScriptInterpreterPythonImpl::Interrupt() sending "969"PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",970tid, num_threads);971return true;972}973}974LLDB_LOGF(log,975"ScriptInterpreterPythonImpl::Interrupt() python code not running, "976"can't interrupt");977return false;978#endif979}980981bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(982llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,983void *ret_value, const ExecuteScriptOptions &options) {984985llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>986io_redirect_or_error = ScriptInterpreterIORedirect::Create(987options.GetEnableIO(), m_debugger, /*result=*/nullptr);988989if (!io_redirect_or_error) {990llvm::consumeError(io_redirect_or_error.takeError());991return false;992}993994ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;995996Locker locker(this,997Locker::AcquireLock | Locker::InitSession |998(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |999Locker::NoSTDIN,1000Locker::FreeAcquiredLock | Locker::TearDownSession,1001io_redirect.GetInputFile(), io_redirect.GetOutputFile(),1002io_redirect.GetErrorFile());10031004PythonModule &main_module = GetMainModule();1005PythonDictionary globals = main_module.GetDictionary();10061007PythonDictionary locals = GetSessionDictionary();1008if (!locals.IsValid())1009locals = unwrapIgnoringErrors(1010As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));1011if (!locals.IsValid())1012locals = globals;10131014Expected<PythonObject> maybe_py_return =1015runStringOneLine(in_string, globals, locals);10161017if (!maybe_py_return) {1018llvm::handleAllErrors(1019maybe_py_return.takeError(),1020[&](PythonException &E) {1021E.Restore();1022if (options.GetMaskoutErrors()) {1023if (E.Matches(PyExc_SyntaxError)) {1024PyErr_Print();1025}1026PyErr_Clear();1027}1028},1029[](const llvm::ErrorInfoBase &E) {});1030return false;1031}10321033PythonObject py_return = std::move(maybe_py_return.get());1034assert(py_return.IsValid());10351036switch (return_type) {1037case eScriptReturnTypeCharPtr: // "char *"1038{1039const char format[3] = "s#";1040return PyArg_Parse(py_return.get(), format, (char **)ret_value);1041}1042case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==1043// Py_None1044{1045const char format[3] = "z";1046return PyArg_Parse(py_return.get(), format, (char **)ret_value);1047}1048case eScriptReturnTypeBool: {1049const char format[2] = "b";1050return PyArg_Parse(py_return.get(), format, (bool *)ret_value);1051}1052case eScriptReturnTypeShortInt: {1053const char format[2] = "h";1054return PyArg_Parse(py_return.get(), format, (short *)ret_value);1055}1056case eScriptReturnTypeShortIntUnsigned: {1057const char format[2] = "H";1058return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);1059}1060case eScriptReturnTypeInt: {1061const char format[2] = "i";1062return PyArg_Parse(py_return.get(), format, (int *)ret_value);1063}1064case eScriptReturnTypeIntUnsigned: {1065const char format[2] = "I";1066return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);1067}1068case eScriptReturnTypeLongInt: {1069const char format[2] = "l";1070return PyArg_Parse(py_return.get(), format, (long *)ret_value);1071}1072case eScriptReturnTypeLongIntUnsigned: {1073const char format[2] = "k";1074return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);1075}1076case eScriptReturnTypeLongLong: {1077const char format[2] = "L";1078return PyArg_Parse(py_return.get(), format, (long long *)ret_value);1079}1080case eScriptReturnTypeLongLongUnsigned: {1081const char format[2] = "K";1082return PyArg_Parse(py_return.get(), format,1083(unsigned long long *)ret_value);1084}1085case eScriptReturnTypeFloat: {1086const char format[2] = "f";1087return PyArg_Parse(py_return.get(), format, (float *)ret_value);1088}1089case eScriptReturnTypeDouble: {1090const char format[2] = "d";1091return PyArg_Parse(py_return.get(), format, (double *)ret_value);1092}1093case eScriptReturnTypeChar: {1094const char format[2] = "c";1095return PyArg_Parse(py_return.get(), format, (char *)ret_value);1096}1097case eScriptReturnTypeOpaqueObject: {1098*((PyObject **)ret_value) = py_return.release();1099return true;1100}1101}1102llvm_unreachable("Fully covered switch!");1103}11041105Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(1106const char *in_string, const ExecuteScriptOptions &options) {11071108if (in_string == nullptr)1109return Status();11101111llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>1112io_redirect_or_error = ScriptInterpreterIORedirect::Create(1113options.GetEnableIO(), m_debugger, /*result=*/nullptr);11141115if (!io_redirect_or_error)1116return Status(io_redirect_or_error.takeError());11171118ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;11191120Locker locker(this,1121Locker::AcquireLock | Locker::InitSession |1122(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |1123Locker::NoSTDIN,1124Locker::FreeAcquiredLock | Locker::TearDownSession,1125io_redirect.GetInputFile(), io_redirect.GetOutputFile(),1126io_redirect.GetErrorFile());11271128PythonModule &main_module = GetMainModule();1129PythonDictionary globals = main_module.GetDictionary();11301131PythonDictionary locals = GetSessionDictionary();1132if (!locals.IsValid())1133locals = unwrapIgnoringErrors(1134As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));1135if (!locals.IsValid())1136locals = globals;11371138Expected<PythonObject> return_value =1139runStringMultiLine(in_string, globals, locals);11401141if (!return_value) {1142llvm::Error error =1143llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {1144llvm::Error error = llvm::createStringError(1145llvm::inconvertibleErrorCode(), E.ReadBacktrace());1146if (!options.GetMaskoutErrors())1147E.Restore();1148return error;1149});1150return Status(std::move(error));1151}11521153return Status();1154}11551156void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(1157std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,1158CommandReturnObject &result) {1159m_active_io_handler = eIOHandlerBreakpoint;1160m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(1161" ", *this, &bp_options_vec);1162}11631164void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(1165WatchpointOptions *wp_options, CommandReturnObject &result) {1166m_active_io_handler = eIOHandlerWatchpoint;1167m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(1168" ", *this, wp_options);1169}11701171Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(1172BreakpointOptions &bp_options, const char *function_name,1173StructuredData::ObjectSP extra_args_sp) {1174Status error;1175// For now just cons up a oneliner that calls the provided function.1176std::string function_signature = function_name;11771178llvm::Expected<unsigned> maybe_args =1179GetMaxPositionalArgumentsForCallable(function_name);1180if (!maybe_args) {1181error.SetErrorStringWithFormat(1182"could not get num args: %s",1183llvm::toString(maybe_args.takeError()).c_str());1184return error;1185}1186size_t max_args = *maybe_args;11871188bool uses_extra_args = false;1189if (max_args >= 4) {1190uses_extra_args = true;1191function_signature += "(frame, bp_loc, extra_args, internal_dict)";1192} else if (max_args >= 3) {1193if (extra_args_sp) {1194error.SetErrorString("cannot pass extra_args to a three argument callback"1195);1196return error;1197}1198uses_extra_args = false;1199function_signature += "(frame, bp_loc, internal_dict)";1200} else {1201error.SetErrorStringWithFormat("expected 3 or 4 argument "1202"function, %s can only take %zu",1203function_name, max_args);1204return error;1205}12061207SetBreakpointCommandCallback(bp_options, function_signature.c_str(),1208extra_args_sp, uses_extra_args,1209/*is_callback=*/true);1210return error;1211}12121213Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1214BreakpointOptions &bp_options,1215std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {1216Status error;1217error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,1218cmd_data_up->script_source,1219/*has_extra_args=*/false,1220/*is_callback=*/false);1221if (error.Fail()) {1222return error;1223}1224auto baton_sp =1225std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));1226bp_options.SetCallback(1227ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);1228return error;1229}12301231Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1232BreakpointOptions &bp_options, const char *command_body_text,1233bool is_callback) {1234return SetBreakpointCommandCallback(bp_options, command_body_text, {},1235/*uses_extra_args=*/false, is_callback);1236}12371238// Set a Python one-liner as the callback for the breakpoint.1239Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1240BreakpointOptions &bp_options, const char *command_body_text,1241StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,1242bool is_callback) {1243auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);1244// Split the command_body_text into lines, and pass that to1245// GenerateBreakpointCommandCallbackData. That will wrap the body in an1246// auto-generated function, and return the function name in script_source.1247// That is what the callback will actually invoke.12481249data_up->user_source.SplitIntoLines(command_body_text);1250Status error = GenerateBreakpointCommandCallbackData(1251data_up->user_source, data_up->script_source, uses_extra_args,1252is_callback);1253if (error.Success()) {1254auto baton_sp =1255std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));1256bp_options.SetCallback(1257ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);1258return error;1259}1260return error;1261}12621263// Set a Python one-liner as the callback for the watchpoint.1264void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback(1265WatchpointOptions *wp_options, const char *user_input,1266bool is_callback) {1267auto data_up = std::make_unique<WatchpointOptions::CommandData>();12681269// It's necessary to set both user_source and script_source to the oneliner.1270// The former is used to generate callback description (as in watchpoint1271// command list) while the latter is used for Python to interpret during the1272// actual callback.12731274data_up->user_source.AppendString(user_input);1275data_up->script_source.assign(user_input);12761277if (GenerateWatchpointCommandCallbackData(1278data_up->user_source, data_up->script_source, is_callback)) {1279auto baton_sp =1280std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));1281wp_options->SetCallback(1282ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);1283}1284}12851286Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(1287StringList &function_def) {1288// Convert StringList to one long, newline delimited, const char *.1289std::string function_def_string(function_def.CopyList());12901291Status error = ExecuteMultipleLines(1292function_def_string.c_str(),1293ExecuteScriptOptions().SetEnableIO(false));1294return error;1295}12961297Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,1298const StringList &input,1299bool is_callback) {1300Status error;1301int num_lines = input.GetSize();1302if (num_lines == 0) {1303error.SetErrorString("No input data.");1304return error;1305}13061307if (!signature || *signature == 0) {1308error.SetErrorString("No output function name.");1309return error;1310}13111312StreamString sstr;1313StringList auto_generated_function;1314auto_generated_function.AppendString(signature);1315auto_generated_function.AppendString(1316" global_dict = globals()"); // Grab the global dictionary1317auto_generated_function.AppendString(1318" new_keys = internal_dict.keys()"); // Make a list of keys in the1319// session dict1320auto_generated_function.AppendString(1321" old_keys = global_dict.keys()"); // Save list of keys in global dict1322auto_generated_function.AppendString(1323" global_dict.update(internal_dict)"); // Add the session dictionary1324// to the global dictionary.13251326if (is_callback) {1327// If the user input is a callback to a python function, make sure the input1328// is only 1 line, otherwise appending the user input would break the1329// generated wrapped function1330if (num_lines == 1) {1331sstr.Clear();1332sstr.Printf(" __return_val = %s", input.GetStringAtIndex(0));1333auto_generated_function.AppendString(sstr.GetData());1334} else {1335return Status("ScriptInterpreterPythonImpl::GenerateFunction(is_callback="1336"true) = ERROR: python function is multiline.");1337}1338} else {1339auto_generated_function.AppendString(1340" __return_val = None"); // Initialize user callback return value.1341auto_generated_function.AppendString(1342" def __user_code():"); // Create a nested function that will wrap1343// the user input. This is necessary to1344// capture the return value of the user input1345// and prevent early returns.1346for (int i = 0; i < num_lines; ++i) {1347sstr.Clear();1348sstr.Printf(" %s", input.GetStringAtIndex(i));1349auto_generated_function.AppendString(sstr.GetData());1350}1351auto_generated_function.AppendString(1352" __return_val = __user_code()"); // Call user code and capture1353// return value1354}1355auto_generated_function.AppendString(1356" for key in new_keys:"); // Iterate over all the keys from session1357// dict1358auto_generated_function.AppendString(1359" internal_dict[key] = global_dict[key]"); // Update session dict1360// values1361auto_generated_function.AppendString(1362" if key not in old_keys:"); // If key was not originally in1363// global dict1364auto_generated_function.AppendString(1365" del global_dict[key]"); // ...then remove key/value from1366// global dict1367auto_generated_function.AppendString(1368" return __return_val"); // Return the user callback return value.13691370// Verify that the results are valid Python.1371error = ExportFunctionDefinitionToInterpreter(auto_generated_function);13721373return error;1374}13751376bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(1377StringList &user_input, std::string &output, const void *name_token) {1378static uint32_t num_created_functions = 0;1379user_input.RemoveBlankLines();1380StreamString sstr;13811382// Check to see if we have any data; if not, just return.1383if (user_input.GetSize() == 0)1384return false;13851386// Take what the user wrote, wrap it all up inside one big auto-generated1387// Python function, passing in the ValueObject as parameter to the function.13881389std::string auto_generated_function_name(1390GenerateUniqueName("lldb_autogen_python_type_print_func",1391num_created_functions, name_token));1392sstr.Printf("def %s (valobj, internal_dict):",1393auto_generated_function_name.c_str());13941395if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)1396.Success())1397return false;13981399// Store the name of the auto-generated function to be called.1400output.assign(auto_generated_function_name);1401return true;1402}14031404bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(1405StringList &user_input, std::string &output) {1406static uint32_t num_created_functions = 0;1407user_input.RemoveBlankLines();1408StreamString sstr;14091410// Check to see if we have any data; if not, just return.1411if (user_input.GetSize() == 0)1412return false;14131414std::string auto_generated_function_name(GenerateUniqueName(1415"lldb_autogen_python_cmd_alias_func", num_created_functions));14161417sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",1418auto_generated_function_name.c_str());14191420if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)1421.Success())1422return false;14231424// Store the name of the auto-generated function to be called.1425output.assign(auto_generated_function_name);1426return true;1427}14281429bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(1430StringList &user_input, std::string &output, const void *name_token) {1431static uint32_t num_created_classes = 0;1432user_input.RemoveBlankLines();1433int num_lines = user_input.GetSize();1434StreamString sstr;14351436// Check to see if we have any data; if not, just return.1437if (user_input.GetSize() == 0)1438return false;14391440// Wrap all user input into a Python class14411442std::string auto_generated_class_name(GenerateUniqueName(1443"lldb_autogen_python_type_synth_class", num_created_classes, name_token));14441445StringList auto_generated_class;14461447// Create the function name & definition string.14481449sstr.Printf("class %s:", auto_generated_class_name.c_str());1450auto_generated_class.AppendString(sstr.GetString());14511452// Wrap everything up inside the class, increasing the indentation. we don't1453// need to play any fancy indentation tricks here because there is no1454// surrounding code whose indentation we need to honor1455for (int i = 0; i < num_lines; ++i) {1456sstr.Clear();1457sstr.Printf(" %s", user_input.GetStringAtIndex(i));1458auto_generated_class.AppendString(sstr.GetString());1459}14601461// Verify that the results are valid Python. (even though the method is1462// ExportFunctionDefinitionToInterpreter, a class will actually be exported)1463// (TODO: rename that method to ExportDefinitionToInterpreter)1464if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())1465return false;14661467// Store the name of the auto-generated class14681469output.assign(auto_generated_class_name);1470return true;1471}14721473StructuredData::GenericSP1474ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) {1475if (class_name == nullptr || class_name[0] == '\0')1476return StructuredData::GenericSP();14771478Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1479PythonObject ret_val = SWIGBridge::LLDBSWIGPython_CreateFrameRecognizer(1480class_name, m_dictionary_name.c_str());14811482return StructuredData::GenericSP(1483new StructuredPythonObject(std::move(ret_val)));1484}14851486lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments(1487const StructuredData::ObjectSP &os_plugin_object_sp,1488lldb::StackFrameSP frame_sp) {1489Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);14901491if (!os_plugin_object_sp)1492return ValueObjectListSP();14931494StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();1495if (!generic)1496return nullptr;14971498PythonObject implementor(PyRefType::Borrowed,1499(PyObject *)generic->GetValue());15001501if (!implementor.IsAllocated())1502return ValueObjectListSP();15031504PythonObject py_return(PyRefType::Owned,1505SWIGBridge::LLDBSwigPython_GetRecognizedArguments(1506implementor.get(), frame_sp));15071508// if it fails, print the error but otherwise go on1509if (PyErr_Occurred()) {1510PyErr_Print();1511PyErr_Clear();1512}1513if (py_return.get()) {1514PythonList result_list(PyRefType::Borrowed, py_return.get());1515ValueObjectListSP result = ValueObjectListSP(new ValueObjectList());1516for (size_t i = 0; i < result_list.GetSize(); i++) {1517PyObject *item = result_list.GetItemAtIndex(i).get();1518lldb::SBValue *sb_value_ptr =1519(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item);1520auto valobj_sp =1521SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr);1522if (valobj_sp)1523result->Append(valobj_sp);1524}1525return result;1526}1527return ValueObjectListSP();1528}15291530ScriptedProcessInterfaceUP1531ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {1532return std::make_unique<ScriptedProcessPythonInterface>(*this);1533}15341535ScriptedThreadInterfaceSP1536ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {1537return std::make_shared<ScriptedThreadPythonInterface>(*this);1538}15391540ScriptedThreadPlanInterfaceSP1541ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {1542return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);1543}15441545OperatingSystemInterfaceSP1546ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {1547return std::make_shared<OperatingSystemPythonInterface>(*this);1548}15491550StructuredData::ObjectSP1551ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(1552ScriptObject obj) {1553void *ptr = const_cast<void *>(obj.GetPointer());1554PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));1555if (!py_obj.IsValid() || py_obj.IsNone())1556return {};1557Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1558return py_obj.CreateStructuredObject();1559}15601561StructuredData::GenericSP1562ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(1563const char *class_name, const StructuredDataImpl &args_data,1564lldb::BreakpointSP &bkpt_sp) {15651566if (class_name == nullptr || class_name[0] == '\0')1567return StructuredData::GenericSP();15681569if (!bkpt_sp.get())1570return StructuredData::GenericSP();15711572Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();1573ScriptInterpreterPythonImpl *python_interpreter =1574GetPythonInterpreter(debugger);15751576if (!python_interpreter)1577return StructuredData::GenericSP();15781579Locker py_lock(this,1580Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);15811582PythonObject ret_val =1583SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(1584class_name, python_interpreter->m_dictionary_name.c_str(), args_data,1585bkpt_sp);15861587return StructuredData::GenericSP(1588new StructuredPythonObject(std::move(ret_val)));1589}15901591bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback(1592StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) {1593bool should_continue = false;15941595if (implementor_sp) {1596Locker py_lock(this,1597Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1598should_continue = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(1599implementor_sp->GetValue(), "__callback__", sym_ctx);1600if (PyErr_Occurred()) {1601PyErr_Print();1602PyErr_Clear();1603}1604}1605return should_continue;1606}16071608lldb::SearchDepth1609ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth(1610StructuredData::GenericSP implementor_sp) {1611int depth_as_int = lldb::eSearchDepthModule;1612if (implementor_sp) {1613Locker py_lock(this,1614Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1615depth_as_int = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(1616implementor_sp->GetValue(), "__get_depth__", nullptr);1617if (PyErr_Occurred()) {1618PyErr_Print();1619PyErr_Clear();1620}1621}1622if (depth_as_int == lldb::eSearchDepthInvalid)1623return lldb::eSearchDepthModule;16241625if (depth_as_int <= lldb::kLastSearchDepthKind)1626return (lldb::SearchDepth)depth_as_int;1627return lldb::eSearchDepthModule;1628}16291630StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook(1631TargetSP target_sp, const char *class_name,1632const StructuredDataImpl &args_data, Status &error) {16331634if (!target_sp) {1635error.SetErrorString("No target for scripted stop-hook.");1636return StructuredData::GenericSP();1637}16381639if (class_name == nullptr || class_name[0] == '\0') {1640error.SetErrorString("No class name for scripted stop-hook.");1641return StructuredData::GenericSP();1642}16431644ScriptInterpreterPythonImpl *python_interpreter =1645GetPythonInterpreter(m_debugger);16461647if (!python_interpreter) {1648error.SetErrorString("No script interpreter for scripted stop-hook.");1649return StructuredData::GenericSP();1650}16511652Locker py_lock(this,1653Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);16541655PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedStopHook(1656target_sp, class_name, python_interpreter->m_dictionary_name.c_str(),1657args_data, error);16581659return StructuredData::GenericSP(1660new StructuredPythonObject(std::move(ret_val)));1661}16621663bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop(1664StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx,1665lldb::StreamSP stream_sp) {1666assert(implementor_sp &&1667"can't call a stop hook with an invalid implementor");1668assert(stream_sp && "can't call a stop hook with an invalid stream");16691670Locker py_lock(this,1671Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);16721673lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx));16741675bool ret_val = SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(1676implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp);1677return ret_val;1678}16791680StructuredData::ObjectSP1681ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,1682lldb_private::Status &error) {1683if (!FileSystem::Instance().Exists(file_spec)) {1684error.SetErrorString("no such file");1685return StructuredData::ObjectSP();1686}16871688StructuredData::ObjectSP module_sp;16891690LoadScriptOptions load_script_options =1691LoadScriptOptions().SetInitSession(true).SetSilent(false);1692if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,1693error, &module_sp))1694return module_sp;16951696return StructuredData::ObjectSP();1697}16981699StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(1700StructuredData::ObjectSP plugin_module_sp, Target *target,1701const char *setting_name, lldb_private::Status &error) {1702if (!plugin_module_sp || !target || !setting_name || !setting_name[0])1703return StructuredData::DictionarySP();1704StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();1705if (!generic)1706return StructuredData::DictionarySP();17071708Locker py_lock(this,1709Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1710TargetSP target_sp(target->shared_from_this());17111712auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(1713generic->GetValue(), setting_name, target_sp);17141715if (!setting)1716return StructuredData::DictionarySP();17171718PythonDictionary py_dict =1719unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting)));17201721if (!py_dict)1722return StructuredData::DictionarySP();17231724return py_dict.CreateStructuredDictionary();1725}17261727StructuredData::ObjectSP1728ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider(1729const char *class_name, lldb::ValueObjectSP valobj) {1730if (class_name == nullptr || class_name[0] == '\0')1731return StructuredData::ObjectSP();17321733if (!valobj.get())1734return StructuredData::ObjectSP();17351736ExecutionContext exe_ctx(valobj->GetExecutionContextRef());1737Target *target = exe_ctx.GetTargetPtr();17381739if (!target)1740return StructuredData::ObjectSP();17411742Debugger &debugger = target->GetDebugger();1743ScriptInterpreterPythonImpl *python_interpreter =1744GetPythonInterpreter(debugger);17451746if (!python_interpreter)1747return StructuredData::ObjectSP();17481749Locker py_lock(this,1750Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1751PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateSyntheticProvider(1752class_name, python_interpreter->m_dictionary_name.c_str(), valobj);17531754return StructuredData::ObjectSP(1755new StructuredPythonObject(std::move(ret_val)));1756}17571758StructuredData::GenericSP1759ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) {1760DebuggerSP debugger_sp(m_debugger.shared_from_this());17611762if (class_name == nullptr || class_name[0] == '\0')1763return StructuredData::GenericSP();17641765if (!debugger_sp.get())1766return StructuredData::GenericSP();17671768Locker py_lock(this,1769Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1770PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateCommandObject(1771class_name, m_dictionary_name.c_str(), debugger_sp);17721773if (ret_val.IsValid())1774return StructuredData::GenericSP(1775new StructuredPythonObject(std::move(ret_val)));1776else1777return {};1778}17791780bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(1781const char *oneliner, std::string &output, const void *name_token) {1782StringList input;1783input.SplitIntoLines(oneliner, strlen(oneliner));1784return GenerateTypeScriptFunction(input, output, name_token);1785}17861787bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(1788const char *oneliner, std::string &output, const void *name_token) {1789StringList input;1790input.SplitIntoLines(oneliner, strlen(oneliner));1791return GenerateTypeSynthClass(input, output, name_token);1792}17931794Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(1795StringList &user_input, std::string &output, bool has_extra_args,1796bool is_callback) {1797static uint32_t num_created_functions = 0;1798user_input.RemoveBlankLines();1799StreamString sstr;1800Status error;1801if (user_input.GetSize() == 0) {1802error.SetErrorString("No input data.");1803return error;1804}18051806std::string auto_generated_function_name(GenerateUniqueName(1807"lldb_autogen_python_bp_callback_func_", num_created_functions));1808if (has_extra_args)1809sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",1810auto_generated_function_name.c_str());1811else1812sstr.Printf("def %s (frame, bp_loc, internal_dict):",1813auto_generated_function_name.c_str());18141815error = GenerateFunction(sstr.GetData(), user_input, is_callback);1816if (!error.Success())1817return error;18181819// Store the name of the auto-generated function to be called.1820output.assign(auto_generated_function_name);1821return error;1822}18231824bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData(1825StringList &user_input, std::string &output, bool is_callback) {1826static uint32_t num_created_functions = 0;1827user_input.RemoveBlankLines();1828StreamString sstr;18291830if (user_input.GetSize() == 0)1831return false;18321833std::string auto_generated_function_name(GenerateUniqueName(1834"lldb_autogen_python_wp_callback_func_", num_created_functions));1835sstr.Printf("def %s (frame, wp, internal_dict):",1836auto_generated_function_name.c_str());18371838if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())1839return false;18401841// Store the name of the auto-generated function to be called.1842output.assign(auto_generated_function_name);1843return true;1844}18451846bool ScriptInterpreterPythonImpl::GetScriptedSummary(1847const char *python_function_name, lldb::ValueObjectSP valobj,1848StructuredData::ObjectSP &callee_wrapper_sp,1849const TypeSummaryOptions &options, std::string &retval) {18501851LLDB_SCOPED_TIMER();18521853if (!valobj.get()) {1854retval.assign("<no object>");1855return false;1856}18571858void *old_callee = nullptr;1859StructuredData::Generic *generic = nullptr;1860if (callee_wrapper_sp) {1861generic = callee_wrapper_sp->GetAsGeneric();1862if (generic)1863old_callee = generic->GetValue();1864}1865void *new_callee = old_callee;18661867bool ret_val;1868if (python_function_name && *python_function_name) {1869{1870Locker py_lock(this, Locker::AcquireLock | Locker::InitSession |1871Locker::NoSTDIN);1872{1873TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));18741875static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");1876Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");1877ret_val = SWIGBridge::LLDBSwigPythonCallTypeScript(1878python_function_name, GetSessionDictionary().get(), valobj,1879&new_callee, options_sp, retval);1880}1881}1882} else {1883retval.assign("<no function name>");1884return false;1885}18861887if (new_callee && old_callee != new_callee) {1888Locker py_lock(this,1889Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1890callee_wrapper_sp = std::make_shared<StructuredPythonObject>(1891PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));1892}18931894return ret_val;1895}18961897bool ScriptInterpreterPythonImpl::FormatterCallbackFunction(1898const char *python_function_name, TypeImplSP type_impl_sp) {1899Locker py_lock(this,1900Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1901return SWIGBridge::LLDBSwigPythonFormatterCallbackFunction(1902python_function_name, m_dictionary_name.c_str(), type_impl_sp);1903}19041905bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(1906void *baton, StoppointCallbackContext *context, user_id_t break_id,1907user_id_t break_loc_id) {1908CommandDataPython *bp_option_data = (CommandDataPython *)baton;1909const char *python_function_name = bp_option_data->script_source.c_str();19101911if (!context)1912return true;19131914ExecutionContext exe_ctx(context->exe_ctx_ref);1915Target *target = exe_ctx.GetTargetPtr();19161917if (!target)1918return true;19191920Debugger &debugger = target->GetDebugger();1921ScriptInterpreterPythonImpl *python_interpreter =1922GetPythonInterpreter(debugger);19231924if (!python_interpreter)1925return true;19261927if (python_function_name && python_function_name[0]) {1928const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());1929BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);1930if (breakpoint_sp) {1931const BreakpointLocationSP bp_loc_sp(1932breakpoint_sp->FindLocationByID(break_loc_id));19331934if (stop_frame_sp && bp_loc_sp) {1935bool ret_val = true;1936{1937Locker py_lock(python_interpreter, Locker::AcquireLock |1938Locker::InitSession |1939Locker::NoSTDIN);1940Expected<bool> maybe_ret_val =1941SWIGBridge::LLDBSwigPythonBreakpointCallbackFunction(1942python_function_name,1943python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,1944bp_loc_sp, bp_option_data->m_extra_args);19451946if (!maybe_ret_val) {19471948llvm::handleAllErrors(1949maybe_ret_val.takeError(),1950[&](PythonException &E) {1951debugger.GetErrorStream() << E.ReadBacktrace();1952},1953[&](const llvm::ErrorInfoBase &E) {1954debugger.GetErrorStream() << E.message();1955});19561957} else {1958ret_val = maybe_ret_val.get();1959}1960}1961return ret_val;1962}1963}1964}1965// We currently always true so we stop in case anything goes wrong when1966// trying to call the script function1967return true;1968}19691970bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction(1971void *baton, StoppointCallbackContext *context, user_id_t watch_id) {1972WatchpointOptions::CommandData *wp_option_data =1973(WatchpointOptions::CommandData *)baton;1974const char *python_function_name = wp_option_data->script_source.c_str();19751976if (!context)1977return true;19781979ExecutionContext exe_ctx(context->exe_ctx_ref);1980Target *target = exe_ctx.GetTargetPtr();19811982if (!target)1983return true;19841985Debugger &debugger = target->GetDebugger();1986ScriptInterpreterPythonImpl *python_interpreter =1987GetPythonInterpreter(debugger);19881989if (!python_interpreter)1990return true;19911992if (python_function_name && python_function_name[0]) {1993const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());1994WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);1995if (wp_sp) {1996if (stop_frame_sp && wp_sp) {1997bool ret_val = true;1998{1999Locker py_lock(python_interpreter, Locker::AcquireLock |2000Locker::InitSession |2001Locker::NoSTDIN);2002ret_val = SWIGBridge::LLDBSwigPythonWatchpointCallbackFunction(2003python_function_name,2004python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,2005wp_sp);2006}2007return ret_val;2008}2009}2010}2011// We currently always true so we stop in case anything goes wrong when2012// trying to call the script function2013return true;2014}20152016size_t ScriptInterpreterPythonImpl::CalculateNumChildren(2017const StructuredData::ObjectSP &implementor_sp, uint32_t max) {2018if (!implementor_sp)2019return 0;2020StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2021if (!generic)2022return 0;2023auto *implementor = static_cast<PyObject *>(generic->GetValue());2024if (!implementor)2025return 0;20262027size_t ret_val = 0;20282029{2030Locker py_lock(this,2031Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2032ret_val = SWIGBridge::LLDBSwigPython_CalculateNumChildren(implementor, max);2033}20342035return ret_val;2036}20372038lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex(2039const StructuredData::ObjectSP &implementor_sp, uint32_t idx) {2040if (!implementor_sp)2041return lldb::ValueObjectSP();20422043StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2044if (!generic)2045return lldb::ValueObjectSP();2046auto *implementor = static_cast<PyObject *>(generic->GetValue());2047if (!implementor)2048return lldb::ValueObjectSP();20492050lldb::ValueObjectSP ret_val;2051{2052Locker py_lock(this,2053Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2054PyObject *child_ptr =2055SWIGBridge::LLDBSwigPython_GetChildAtIndex(implementor, idx);2056if (child_ptr != nullptr && child_ptr != Py_None) {2057lldb::SBValue *sb_value_ptr =2058(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);2059if (sb_value_ptr == nullptr)2060Py_XDECREF(child_ptr);2061else2062ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(2063sb_value_ptr);2064} else {2065Py_XDECREF(child_ptr);2066}2067}20682069return ret_val;2070}20712072int ScriptInterpreterPythonImpl::GetIndexOfChildWithName(2073const StructuredData::ObjectSP &implementor_sp, const char *child_name) {2074if (!implementor_sp)2075return UINT32_MAX;20762077StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2078if (!generic)2079return UINT32_MAX;2080auto *implementor = static_cast<PyObject *>(generic->GetValue());2081if (!implementor)2082return UINT32_MAX;20832084int ret_val = UINT32_MAX;20852086{2087Locker py_lock(this,2088Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2089ret_val = SWIGBridge::LLDBSwigPython_GetIndexOfChildWithName(implementor, child_name);2090}20912092return ret_val;2093}20942095bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance(2096const StructuredData::ObjectSP &implementor_sp) {2097bool ret_val = false;20982099if (!implementor_sp)2100return ret_val;21012102StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2103if (!generic)2104return ret_val;2105auto *implementor = static_cast<PyObject *>(generic->GetValue());2106if (!implementor)2107return ret_val;21082109{2110Locker py_lock(this,2111Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2112ret_val =2113SWIGBridge::LLDBSwigPython_UpdateSynthProviderInstance(implementor);2114}21152116return ret_val;2117}21182119bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance(2120const StructuredData::ObjectSP &implementor_sp) {2121bool ret_val = false;21222123if (!implementor_sp)2124return ret_val;21252126StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2127if (!generic)2128return ret_val;2129auto *implementor = static_cast<PyObject *>(generic->GetValue());2130if (!implementor)2131return ret_val;21322133{2134Locker py_lock(this,2135Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2136ret_val = SWIGBridge::LLDBSwigPython_MightHaveChildrenSynthProviderInstance(2137implementor);2138}21392140return ret_val;2141}21422143lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue(2144const StructuredData::ObjectSP &implementor_sp) {2145lldb::ValueObjectSP ret_val(nullptr);21462147if (!implementor_sp)2148return ret_val;21492150StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2151if (!generic)2152return ret_val;2153auto *implementor = static_cast<PyObject *>(generic->GetValue());2154if (!implementor)2155return ret_val;21562157{2158Locker py_lock(this,2159Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2160PyObject *child_ptr =2161SWIGBridge::LLDBSwigPython_GetValueSynthProviderInstance(implementor);2162if (child_ptr != nullptr && child_ptr != Py_None) {2163lldb::SBValue *sb_value_ptr =2164(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);2165if (sb_value_ptr == nullptr)2166Py_XDECREF(child_ptr);2167else2168ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(2169sb_value_ptr);2170} else {2171Py_XDECREF(child_ptr);2172}2173}21742175return ret_val;2176}21772178ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName(2179const StructuredData::ObjectSP &implementor_sp) {2180Locker py_lock(this,2181Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);21822183if (!implementor_sp)2184return {};21852186StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2187if (!generic)2188return {};21892190PythonObject implementor(PyRefType::Borrowed,2191(PyObject *)generic->GetValue());2192if (!implementor.IsAllocated())2193return {};21942195llvm::Expected<PythonObject> expected_py_return =2196implementor.CallMethod("get_type_name");21972198if (!expected_py_return) {2199llvm::consumeError(expected_py_return.takeError());2200return {};2201}22022203PythonObject py_return = std::move(expected_py_return.get());2204if (!py_return.IsAllocated() || !PythonString::Check(py_return.get()))2205return {};22062207PythonString type_name(PyRefType::Borrowed, py_return.get());2208return ConstString(type_name.GetString());2209}22102211bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2212const char *impl_function, Process *process, std::string &output,2213Status &error) {2214bool ret_val;2215if (!process) {2216error.SetErrorString("no process");2217return false;2218}2219if (!impl_function || !impl_function[0]) {2220error.SetErrorString("no function to execute");2221return false;2222}22232224{2225Locker py_lock(this,2226Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2227ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordProcess(2228impl_function, m_dictionary_name.c_str(), process->shared_from_this(),2229output);2230if (!ret_val)2231error.SetErrorString("python script evaluation failed");2232}2233return ret_val;2234}22352236bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2237const char *impl_function, Thread *thread, std::string &output,2238Status &error) {2239if (!thread) {2240error.SetErrorString("no thread");2241return false;2242}2243if (!impl_function || !impl_function[0]) {2244error.SetErrorString("no function to execute");2245return false;2246}22472248Locker py_lock(this,2249Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2250if (std::optional<std::string> result =2251SWIGBridge::LLDBSWIGPythonRunScriptKeywordThread(2252impl_function, m_dictionary_name.c_str(),2253thread->shared_from_this())) {2254output = std::move(*result);2255return true;2256}2257error.SetErrorString("python script evaluation failed");2258return false;2259}22602261bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2262const char *impl_function, Target *target, std::string &output,2263Status &error) {2264bool ret_val;2265if (!target) {2266error.SetErrorString("no thread");2267return false;2268}2269if (!impl_function || !impl_function[0]) {2270error.SetErrorString("no function to execute");2271return false;2272}22732274{2275TargetSP target_sp(target->shared_from_this());2276Locker py_lock(this,2277Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2278ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordTarget(2279impl_function, m_dictionary_name.c_str(), target_sp, output);2280if (!ret_val)2281error.SetErrorString("python script evaluation failed");2282}2283return ret_val;2284}22852286bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2287const char *impl_function, StackFrame *frame, std::string &output,2288Status &error) {2289if (!frame) {2290error.SetErrorString("no frame");2291return false;2292}2293if (!impl_function || !impl_function[0]) {2294error.SetErrorString("no function to execute");2295return false;2296}22972298Locker py_lock(this,2299Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2300if (std::optional<std::string> result =2301SWIGBridge::LLDBSWIGPythonRunScriptKeywordFrame(2302impl_function, m_dictionary_name.c_str(),2303frame->shared_from_this())) {2304output = std::move(*result);2305return true;2306}2307error.SetErrorString("python script evaluation failed");2308return false;2309}23102311bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2312const char *impl_function, ValueObject *value, std::string &output,2313Status &error) {2314bool ret_val;2315if (!value) {2316error.SetErrorString("no value");2317return false;2318}2319if (!impl_function || !impl_function[0]) {2320error.SetErrorString("no function to execute");2321return false;2322}23232324{2325Locker py_lock(this,2326Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2327ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(2328impl_function, m_dictionary_name.c_str(), value->GetSP(), output);2329if (!ret_val)2330error.SetErrorString("python script evaluation failed");2331}2332return ret_val;2333}23342335uint64_t replace_all(std::string &str, const std::string &oldStr,2336const std::string &newStr) {2337size_t pos = 0;2338uint64_t matches = 0;2339while ((pos = str.find(oldStr, pos)) != std::string::npos) {2340matches++;2341str.replace(pos, oldStr.length(), newStr);2342pos += newStr.length();2343}2344return matches;2345}23462347bool ScriptInterpreterPythonImpl::LoadScriptingModule(2348const char *pathname, const LoadScriptOptions &options,2349lldb_private::Status &error, StructuredData::ObjectSP *module_sp,2350FileSpec extra_search_dir) {2351namespace fs = llvm::sys::fs;2352namespace path = llvm::sys::path;23532354ExecuteScriptOptions exc_options = ExecuteScriptOptions()2355.SetEnableIO(!options.GetSilent())2356.SetSetLLDBGlobals(false);23572358if (!pathname || !pathname[0]) {2359error.SetErrorString("empty path");2360return false;2361}23622363llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>2364io_redirect_or_error = ScriptInterpreterIORedirect::Create(2365exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);23662367if (!io_redirect_or_error) {2368error = io_redirect_or_error.takeError();2369return false;2370}23712372ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;23732374// Before executing Python code, lock the GIL.2375Locker py_lock(this,2376Locker::AcquireLock |2377(options.GetInitSession() ? Locker::InitSession : 0) |2378Locker::NoSTDIN,2379Locker::FreeAcquiredLock |2380(options.GetInitSession() ? Locker::TearDownSession : 0),2381io_redirect.GetInputFile(), io_redirect.GetOutputFile(),2382io_redirect.GetErrorFile());23832384auto ExtendSysPath = [&](std::string directory) -> llvm::Error {2385if (directory.empty()) {2386return llvm::createStringError("invalid directory name");2387}23882389replace_all(directory, "\\", "\\\\");2390replace_all(directory, "'", "\\'");23912392// Make sure that Python has "directory" in the search path.2393StreamString command_stream;2394command_stream.Printf("if not (sys.path.__contains__('%s')):\n "2395"sys.path.insert(1,'%s');\n\n",2396directory.c_str(), directory.c_str());2397bool syspath_retval =2398ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();2399if (!syspath_retval)2400return llvm::createStringError("Python sys.path handling failed");24012402return llvm::Error::success();2403};24042405std::string module_name(pathname);2406bool possible_package = false;24072408if (extra_search_dir) {2409if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {2410error = std::move(e);2411return false;2412}2413} else {2414FileSpec module_file(pathname);2415FileSystem::Instance().Resolve(module_file);24162417fs::file_status st;2418std::error_code ec = status(module_file.GetPath(), st);24192420if (ec || st.type() == fs::file_type::status_error ||2421st.type() == fs::file_type::type_unknown ||2422st.type() == fs::file_type::file_not_found) {2423// if not a valid file of any sort, check if it might be a filename still2424// dot can't be used but / and \ can, and if either is found, reject2425if (strchr(pathname, '\\') || strchr(pathname, '/')) {2426error.SetErrorStringWithFormatv("invalid pathname '{0}'", pathname);2427return false;2428}2429// Not a filename, probably a package of some sort, let it go through.2430possible_package = true;2431} else if (is_directory(st) || is_regular_file(st)) {2432if (module_file.GetDirectory().IsEmpty()) {2433error.SetErrorStringWithFormatv("invalid directory name '{0}'", pathname);2434return false;2435}2436if (llvm::Error e =2437ExtendSysPath(module_file.GetDirectory().GetCString())) {2438error = std::move(e);2439return false;2440}2441module_name = module_file.GetFilename().GetCString();2442} else {2443error.SetErrorString("no known way to import this module specification");2444return false;2445}2446}24472448// Strip .py or .pyc extension2449llvm::StringRef extension = llvm::sys::path::extension(module_name);2450if (!extension.empty()) {2451if (extension == ".py")2452module_name.resize(module_name.length() - 3);2453else if (extension == ".pyc")2454module_name.resize(module_name.length() - 4);2455}24562457if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {2458error.SetErrorStringWithFormat(2459"Python does not allow dots in module names: %s", module_name.c_str());2460return false;2461}24622463if (module_name.find('-') != llvm::StringRef::npos) {2464error.SetErrorStringWithFormat(2465"Python discourages dashes in module names: %s", module_name.c_str());2466return false;2467}24682469// Check if the module is already imported.2470StreamString command_stream;2471command_stream.Clear();2472command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());2473bool does_contain = false;2474// This call will succeed if the module was ever imported in any Debugger in2475// the lifetime of the process in which this LLDB framework is living.2476const bool does_contain_executed = ExecuteOneLineWithReturn(2477command_stream.GetData(),2478ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options);24792480const bool was_imported_globally = does_contain_executed && does_contain;2481const bool was_imported_locally =2482GetSessionDictionary()2483.GetItemForKey(PythonString(module_name))2484.IsAllocated();24852486// now actually do the import2487command_stream.Clear();24882489if (was_imported_globally || was_imported_locally) {2490if (!was_imported_locally)2491command_stream.Printf("import %s ; reload_module(%s)",2492module_name.c_str(), module_name.c_str());2493else2494command_stream.Printf("reload_module(%s)", module_name.c_str());2495} else2496command_stream.Printf("import %s", module_name.c_str());24972498error = ExecuteMultipleLines(command_stream.GetData(), exc_options);2499if (error.Fail())2500return false;25012502// if we are here, everything worked2503// call __lldb_init_module(debugger,dict)2504if (!SWIGBridge::LLDBSwigPythonCallModuleInit(2505module_name.c_str(), m_dictionary_name.c_str(),2506m_debugger.shared_from_this())) {2507error.SetErrorString("calling __lldb_init_module failed");2508return false;2509}25102511if (module_sp) {2512// everything went just great, now set the module object2513command_stream.Clear();2514command_stream.Printf("%s", module_name.c_str());2515void *module_pyobj = nullptr;2516if (ExecuteOneLineWithReturn(2517command_stream.GetData(),2518ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,2519exc_options) &&2520module_pyobj)2521*module_sp = std::make_shared<StructuredPythonObject>(PythonObject(2522PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));2523}25242525return true;2526}25272528bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {2529if (!word || !word[0])2530return false;25312532llvm::StringRef word_sr(word);25332534// filter out a few characters that would just confuse us and that are2535// clearly not keyword material anyway2536if (word_sr.find('"') != llvm::StringRef::npos ||2537word_sr.find('\'') != llvm::StringRef::npos)2538return false;25392540StreamString command_stream;2541command_stream.Printf("keyword.iskeyword('%s')", word);2542bool result;2543ExecuteScriptOptions options;2544options.SetEnableIO(false);2545options.SetMaskoutErrors(true);2546options.SetSetLLDBGlobals(false);2547if (ExecuteOneLineWithReturn(command_stream.GetData(),2548ScriptInterpreter::eScriptReturnTypeBool,2549&result, options))2550return result;2551return false;2552}25532554ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler(2555lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro)2556: m_debugger_sp(debugger_sp), m_synch_wanted(synchro),2557m_old_asynch(debugger_sp->GetAsyncExecution()) {2558if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)2559m_debugger_sp->SetAsyncExecution(false);2560else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)2561m_debugger_sp->SetAsyncExecution(true);2562}25632564ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() {2565if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)2566m_debugger_sp->SetAsyncExecution(m_old_asynch);2567}25682569bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(2570const char *impl_function, llvm::StringRef args,2571ScriptedCommandSynchronicity synchronicity,2572lldb_private::CommandReturnObject &cmd_retobj, Status &error,2573const lldb_private::ExecutionContext &exe_ctx) {2574if (!impl_function) {2575error.SetErrorString("no function to execute");2576return false;2577}25782579lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2580lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));25812582if (!debugger_sp.get()) {2583error.SetErrorString("invalid Debugger pointer");2584return false;2585}25862587bool ret_val = false;25882589std::string err_msg;25902591{2592Locker py_lock(this,2593Locker::AcquireLock | Locker::InitSession |2594(cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2595Locker::FreeLock | Locker::TearDownSession);25962597SynchronicityHandler synch_handler(debugger_sp, synchronicity);25982599std::string args_str = args.str();2600ret_val = SWIGBridge::LLDBSwigPythonCallCommand(2601impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),2602cmd_retobj, exe_ctx_ref_sp);2603}26042605if (!ret_val)2606error.SetErrorString("unable to execute script function");2607else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2608return false;26092610error.Clear();2611return ret_val;2612}26132614bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(2615StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,2616ScriptedCommandSynchronicity synchronicity,2617lldb_private::CommandReturnObject &cmd_retobj, Status &error,2618const lldb_private::ExecutionContext &exe_ctx) {2619if (!impl_obj_sp || !impl_obj_sp->IsValid()) {2620error.SetErrorString("no function to execute");2621return false;2622}26232624lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2625lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));26262627if (!debugger_sp.get()) {2628error.SetErrorString("invalid Debugger pointer");2629return false;2630}26312632bool ret_val = false;26332634std::string err_msg;26352636{2637Locker py_lock(this,2638Locker::AcquireLock | Locker::InitSession |2639(cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2640Locker::FreeLock | Locker::TearDownSession);26412642SynchronicityHandler synch_handler(debugger_sp, synchronicity);26432644std::string args_str = args.str();2645ret_val = SWIGBridge::LLDBSwigPythonCallCommandObject(2646static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp,2647args_str.c_str(), cmd_retobj, exe_ctx_ref_sp);2648}26492650if (!ret_val)2651error.SetErrorString("unable to execute script function");2652else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2653return false;26542655error.Clear();2656return ret_val;2657}26582659bool ScriptInterpreterPythonImpl::RunScriptBasedParsedCommand(2660StructuredData::GenericSP impl_obj_sp, Args &args,2661ScriptedCommandSynchronicity synchronicity,2662lldb_private::CommandReturnObject &cmd_retobj, Status &error,2663const lldb_private::ExecutionContext &exe_ctx) {2664if (!impl_obj_sp || !impl_obj_sp->IsValid()) {2665error.SetErrorString("no function to execute");2666return false;2667}26682669lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2670lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));26712672if (!debugger_sp.get()) {2673error.SetErrorString("invalid Debugger pointer");2674return false;2675}26762677bool ret_val = false;26782679std::string err_msg;26802681{2682Locker py_lock(this,2683Locker::AcquireLock | Locker::InitSession |2684(cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2685Locker::FreeLock | Locker::TearDownSession);26862687SynchronicityHandler synch_handler(debugger_sp, synchronicity);26882689StructuredData::ArraySP args_arr_sp(new StructuredData::Array());26902691for (const Args::ArgEntry &entry : args) {2692args_arr_sp->AddStringItem(entry.ref());2693}2694StructuredDataImpl args_impl(args_arr_sp);26952696ret_val = SWIGBridge::LLDBSwigPythonCallParsedCommandObject(2697static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp,2698args_impl, cmd_retobj, exe_ctx_ref_sp);2699}27002701if (!ret_val)2702error.SetErrorString("unable to execute script function");2703else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2704return false;27052706error.Clear();2707return ret_val;2708}27092710std::optional<std::string>2711ScriptInterpreterPythonImpl::GetRepeatCommandForScriptedCommand(2712StructuredData::GenericSP impl_obj_sp, Args &args) {2713if (!impl_obj_sp || !impl_obj_sp->IsValid())2714return std::nullopt;27152716lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();27172718if (!debugger_sp.get())2719return std::nullopt;27202721std::optional<std::string> ret_val;27222723{2724Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,2725Locker::FreeLock);27262727StructuredData::ArraySP args_arr_sp(new StructuredData::Array());27282729// For scripting commands, we send the command string:2730std::string command;2731args.GetQuotedCommandString(command);2732ret_val = SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand(2733static_cast<PyObject *>(impl_obj_sp->GetValue()), command);2734}2735return ret_val;2736}27372738/// In Python, a special attribute __doc__ contains the docstring for an object2739/// (function, method, class, ...) if any is defined Otherwise, the attribute's2740/// value is None.2741bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,2742std::string &dest) {2743dest.clear();27442745if (!item || !*item)2746return false;27472748std::string command(item);2749command += ".__doc__";27502751// Python is going to point this to valid data if ExecuteOneLineWithReturn2752// returns successfully.2753char *result_ptr = nullptr;27542755if (ExecuteOneLineWithReturn(2756command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,2757&result_ptr,2758ExecuteScriptOptions().SetEnableIO(false))) {2759if (result_ptr)2760dest.assign(result_ptr);2761return true;2762}27632764StreamString str_stream;2765str_stream << "Function " << item2766<< " was not found. Containing module might be missing.";2767dest = std::string(str_stream.GetString());27682769return false;2770}27712772bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject(2773StructuredData::GenericSP cmd_obj_sp, std::string &dest) {2774dest.clear();27752776Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);27772778if (!cmd_obj_sp)2779return false;27802781PythonObject implementor(PyRefType::Borrowed,2782(PyObject *)cmd_obj_sp->GetValue());27832784if (!implementor.IsAllocated())2785return false;27862787llvm::Expected<PythonObject> expected_py_return =2788implementor.CallMethod("get_short_help");27892790if (!expected_py_return) {2791llvm::consumeError(expected_py_return.takeError());2792return false;2793}27942795PythonObject py_return = std::move(expected_py_return.get());27962797if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {2798PythonString py_string(PyRefType::Borrowed, py_return.get());2799llvm::StringRef return_data(py_string.GetString());2800dest.assign(return_data.data(), return_data.size());2801return true;2802}28032804return false;2805}28062807uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject(2808StructuredData::GenericSP cmd_obj_sp) {2809uint32_t result = 0;28102811Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);28122813static char callee_name[] = "get_flags";28142815if (!cmd_obj_sp)2816return result;28172818PythonObject implementor(PyRefType::Borrowed,2819(PyObject *)cmd_obj_sp->GetValue());28202821if (!implementor.IsAllocated())2822return result;28232824PythonObject pmeth(PyRefType::Owned,2825PyObject_GetAttrString(implementor.get(), callee_name));28262827if (PyErr_Occurred())2828PyErr_Clear();28292830if (!pmeth.IsAllocated())2831return result;28322833if (PyCallable_Check(pmeth.get()) == 0) {2834if (PyErr_Occurred())2835PyErr_Clear();2836return result;2837}28382839if (PyErr_Occurred())2840PyErr_Clear();28412842long long py_return = unwrapOrSetPythonException(2843As<long long>(implementor.CallMethod(callee_name)));28442845// if it fails, print the error but otherwise go on2846if (PyErr_Occurred()) {2847PyErr_Print();2848PyErr_Clear();2849} else {2850result = py_return;2851}28522853return result;2854}28552856StructuredData::ObjectSP2857ScriptInterpreterPythonImpl::GetOptionsForCommandObject(2858StructuredData::GenericSP cmd_obj_sp) {2859StructuredData::ObjectSP result = {};28602861Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);28622863static char callee_name[] = "get_options_definition";28642865if (!cmd_obj_sp)2866return result;28672868PythonObject implementor(PyRefType::Borrowed,2869(PyObject *)cmd_obj_sp->GetValue());28702871if (!implementor.IsAllocated())2872return result;28732874PythonObject pmeth(PyRefType::Owned,2875PyObject_GetAttrString(implementor.get(), callee_name));28762877if (PyErr_Occurred())2878PyErr_Clear();28792880if (!pmeth.IsAllocated())2881return result;28822883if (PyCallable_Check(pmeth.get()) == 0) {2884if (PyErr_Occurred())2885PyErr_Clear();2886return result;2887}28882889if (PyErr_Occurred())2890PyErr_Clear();28912892PythonDictionary py_return = unwrapOrSetPythonException(2893As<PythonDictionary>(implementor.CallMethod(callee_name)));28942895// if it fails, print the error but otherwise go on2896if (PyErr_Occurred()) {2897PyErr_Print();2898PyErr_Clear();2899return {};2900}2901return py_return.CreateStructuredObject();2902}29032904StructuredData::ObjectSP2905ScriptInterpreterPythonImpl::GetArgumentsForCommandObject(2906StructuredData::GenericSP cmd_obj_sp) {2907StructuredData::ObjectSP result = {};29082909Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);29102911static char callee_name[] = "get_args_definition";29122913if (!cmd_obj_sp)2914return result;29152916PythonObject implementor(PyRefType::Borrowed,2917(PyObject *)cmd_obj_sp->GetValue());29182919if (!implementor.IsAllocated())2920return result;29212922PythonObject pmeth(PyRefType::Owned,2923PyObject_GetAttrString(implementor.get(), callee_name));29242925if (PyErr_Occurred())2926PyErr_Clear();29272928if (!pmeth.IsAllocated())2929return result;29302931if (PyCallable_Check(pmeth.get()) == 0) {2932if (PyErr_Occurred())2933PyErr_Clear();2934return result;2935}29362937if (PyErr_Occurred())2938PyErr_Clear();29392940PythonList py_return = unwrapOrSetPythonException(2941As<PythonList>(implementor.CallMethod(callee_name)));29422943// if it fails, print the error but otherwise go on2944if (PyErr_Occurred()) {2945PyErr_Print();2946PyErr_Clear();2947return {};2948}2949return py_return.CreateStructuredObject();2950}29512952void2953ScriptInterpreterPythonImpl::OptionParsingStartedForCommandObject(2954StructuredData::GenericSP cmd_obj_sp) {29552956Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);29572958static char callee_name[] = "option_parsing_started";29592960if (!cmd_obj_sp)2961return ;29622963PythonObject implementor(PyRefType::Borrowed,2964(PyObject *)cmd_obj_sp->GetValue());29652966if (!implementor.IsAllocated())2967return;29682969PythonObject pmeth(PyRefType::Owned,2970PyObject_GetAttrString(implementor.get(), callee_name));29712972if (PyErr_Occurred())2973PyErr_Clear();29742975if (!pmeth.IsAllocated())2976return;29772978if (PyCallable_Check(pmeth.get()) == 0) {2979if (PyErr_Occurred())2980PyErr_Clear();2981return;2982}29832984if (PyErr_Occurred())2985PyErr_Clear();29862987// option_parsing_starting doesn't return anything, ignore anything but2988// python errors.2989unwrapOrSetPythonException(2990As<bool>(implementor.CallMethod(callee_name)));29912992// if it fails, print the error but otherwise go on2993if (PyErr_Occurred()) {2994PyErr_Print();2995PyErr_Clear();2996return;2997}2998}29993000bool3001ScriptInterpreterPythonImpl::SetOptionValueForCommandObject(3002StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx,3003llvm::StringRef long_option, llvm::StringRef value) {3004StructuredData::ObjectSP result = {};30053006Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);30073008static char callee_name[] = "set_option_value";30093010if (!cmd_obj_sp)3011return false;30123013PythonObject implementor(PyRefType::Borrowed,3014(PyObject *)cmd_obj_sp->GetValue());30153016if (!implementor.IsAllocated())3017return false;30183019PythonObject pmeth(PyRefType::Owned,3020PyObject_GetAttrString(implementor.get(), callee_name));30213022if (PyErr_Occurred())3023PyErr_Clear();30243025if (!pmeth.IsAllocated())3026return false;30273028if (PyCallable_Check(pmeth.get()) == 0) {3029if (PyErr_Occurred())3030PyErr_Clear();3031return false;3032}30333034if (PyErr_Occurred())3035PyErr_Clear();30363037lldb::ExecutionContextRefSP exe_ctx_ref_sp;3038if (exe_ctx)3039exe_ctx_ref_sp.reset(new ExecutionContextRef(exe_ctx));3040PythonObject ctx_ref_obj = SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp);30413042bool py_return = unwrapOrSetPythonException(3043As<bool>(implementor.CallMethod(callee_name, ctx_ref_obj, long_option.str().c_str(),3044value.str().c_str())));30453046// if it fails, print the error but otherwise go on3047if (PyErr_Occurred()) {3048PyErr_Print();3049PyErr_Clear();3050return false;3051}3052return py_return;3053}30543055bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject(3056StructuredData::GenericSP cmd_obj_sp, std::string &dest) {3057dest.clear();30583059Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);30603061if (!cmd_obj_sp)3062return false;30633064PythonObject implementor(PyRefType::Borrowed,3065(PyObject *)cmd_obj_sp->GetValue());30663067if (!implementor.IsAllocated())3068return false;30693070llvm::Expected<PythonObject> expected_py_return =3071implementor.CallMethod("get_long_help");30723073if (!expected_py_return) {3074llvm::consumeError(expected_py_return.takeError());3075return false;3076}30773078PythonObject py_return = std::move(expected_py_return.get());30793080bool got_string = false;3081if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {3082PythonString str(PyRefType::Borrowed, py_return.get());3083llvm::StringRef str_data(str.GetString());3084dest.assign(str_data.data(), str_data.size());3085got_string = true;3086}30873088return got_string;3089}30903091std::unique_ptr<ScriptInterpreterLocker>3092ScriptInterpreterPythonImpl::AcquireInterpreterLock() {3093std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(3094this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,3095Locker::FreeLock | Locker::TearDownSession));3096return py_lock;3097}30983099void ScriptInterpreterPythonImpl::Initialize() {3100LLDB_SCOPED_TIMER();31013102// RAII-based initialization which correctly handles multiple-initialization,3103// version- specific differences among Python 2 and Python 3, and saving and3104// restoring various other pieces of state that can get mucked with during3105// initialization.3106InitializePythonRAII initialize_guard;31073108LLDBSwigPyInit();31093110// Update the path python uses to search for modules to include the current3111// directory.31123113PyRun_SimpleString("import sys");3114AddToSysPath(AddLocation::End, ".");31153116// Don't denormalize paths when calling file_spec.GetPath(). On platforms3117// that use a backslash as the path separator, this will result in executing3118// python code containing paths with unescaped backslashes. But Python also3119// accepts forward slashes, so to make life easier we just use that.3120if (FileSpec file_spec = GetPythonDir())3121AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));3122if (FileSpec file_spec = HostInfo::GetShlibDir())3123AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));31243125PyRun_SimpleString("sys.dont_write_bytecode = 1; import "3126"lldb.embedded_interpreter; from "3127"lldb.embedded_interpreter import run_python_interpreter; "3128"from lldb.embedded_interpreter import run_one_line");31293130#if LLDB_USE_PYTHON_SET_INTERRUPT3131// Python will not just overwrite its internal SIGINT handler but also the3132// one from the process. Backup the current SIGINT handler to prevent that3133// Python deletes it.3134RestoreSignalHandlerScope save_sigint(SIGINT);31353136// Setup a default SIGINT signal handler that works the same way as the3137// normal Python REPL signal handler which raises a KeyboardInterrupt.3138// Also make sure to not pollute the user's REPL with the signal module nor3139// our utility function.3140PyRun_SimpleString("def lldb_setup_sigint_handler():\n"3141" import signal;\n"3142" def signal_handler(sig, frame):\n"3143" raise KeyboardInterrupt()\n"3144" signal.signal(signal.SIGINT, signal_handler);\n"3145"lldb_setup_sigint_handler();\n"3146"del lldb_setup_sigint_handler\n");3147#endif3148}31493150void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,3151std::string path) {3152std::string path_copy;31533154std::string statement;3155if (location == AddLocation::Beginning) {3156statement.assign("sys.path.insert(0,\"");3157statement.append(path);3158statement.append("\")");3159} else {3160statement.assign("sys.path.append(\"");3161statement.append(path);3162statement.append("\")");3163}3164PyRun_SimpleString(statement.c_str());3165}31663167// We are intentionally NOT calling Py_Finalize here (this would be the logical3168// place to call it). Calling Py_Finalize here causes test suite runs to seg3169// fault: The test suite runs in Python. It registers SBDebugger::Terminate to3170// be called 'at_exit'. When the test suite Python harness finishes up, it3171// calls Py_Finalize, which calls all the 'at_exit' registered functions.3172// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,3173// which calls ScriptInterpreter::Terminate, which calls3174// ScriptInterpreterPythonImpl::Terminate. So if we call Py_Finalize here, we3175// end up with Py_Finalize being called from within Py_Finalize, which results3176// in a seg fault. Since this function only gets called when lldb is shutting3177// down and going away anyway, the fact that we don't actually call Py_Finalize3178// should not cause any problems (everything should shut down/go away anyway3179// when the process exits).3180//3181// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }31823183#endif318431853186