File: | build/source/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp |
Warning: | line 109, column 7 Value stored to 'ReadlinePatched' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- ScriptInterpreterPython.cpp ---------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Host/Config.h" |
10 | #include "lldb/lldb-enumerations.h" |
11 | |
12 | #if LLDB_ENABLE_PYTHON1 |
13 | |
14 | // LLDB Python header must be included first |
15 | #include "lldb-python.h" |
16 | |
17 | #include "PythonDataObjects.h" |
18 | #include "PythonReadline.h" |
19 | #include "SWIGPythonBridge.h" |
20 | #include "ScriptInterpreterPythonImpl.h" |
21 | #include "ScriptedPlatformPythonInterface.h" |
22 | #include "ScriptedProcessPythonInterface.h" |
23 | |
24 | #include "lldb/API/SBError.h" |
25 | #include "lldb/API/SBFrame.h" |
26 | #include "lldb/API/SBValue.h" |
27 | #include "lldb/Breakpoint/StoppointCallbackContext.h" |
28 | #include "lldb/Breakpoint/WatchpointOptions.h" |
29 | #include "lldb/Core/Debugger.h" |
30 | #include "lldb/Core/PluginManager.h" |
31 | #include "lldb/Core/ThreadedCommunication.h" |
32 | #include "lldb/Core/ValueObject.h" |
33 | #include "lldb/DataFormatters/TypeSummary.h" |
34 | #include "lldb/Host/FileSystem.h" |
35 | #include "lldb/Host/HostInfo.h" |
36 | #include "lldb/Host/Pipe.h" |
37 | #include "lldb/Interpreter/CommandInterpreter.h" |
38 | #include "lldb/Interpreter/CommandReturnObject.h" |
39 | #include "lldb/Target/Thread.h" |
40 | #include "lldb/Target/ThreadPlan.h" |
41 | #include "lldb/Utility/Instrumentation.h" |
42 | #include "lldb/Utility/LLDBLog.h" |
43 | #include "lldb/Utility/Timer.h" |
44 | #include "llvm/ADT/STLExtras.h" |
45 | #include "llvm/ADT/StringRef.h" |
46 | #include "llvm/Support/Error.h" |
47 | #include "llvm/Support/FileSystem.h" |
48 | #include "llvm/Support/FormatAdapters.h" |
49 | |
50 | #include <cstdio> |
51 | #include <cstdlib> |
52 | #include <memory> |
53 | #include <mutex> |
54 | #include <optional> |
55 | #include <string> |
56 | |
57 | using namespace lldb; |
58 | using namespace lldb_private; |
59 | using namespace lldb_private::python; |
60 | using llvm::Expected; |
61 | |
62 | LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)namespace lldb_private { void lldb_initialize_ScriptInterpreterPython () { ScriptInterpreterPython::Initialize(); } void lldb_terminate_ScriptInterpreterPython () { ScriptInterpreterPython::Terminate(); } } |
63 | |
64 | // Defined in the SWIG source file |
65 | extern "C" PyObject *PyInit__lldb(void); |
66 | |
67 | #define LLDBSwigPyInitPyInit__lldb PyInit__lldb |
68 | |
69 | #if defined(_WIN32) |
70 | // Don't mess with the signal handlers on Windows. |
71 | #define LLDB_USE_PYTHON_SET_INTERRUPT(3 == 3 && 9 >= 2) || (3 > 3) 0 |
72 | #else |
73 | // PyErr_SetInterrupt was introduced in 3.2. |
74 | #define LLDB_USE_PYTHON_SET_INTERRUPT(3 == 3 && 9 >= 2) || (3 > 3) \ |
75 | (PY_MAJOR_VERSION3 == 3 && PY_MINOR_VERSION9 >= 2) || (PY_MAJOR_VERSION3 > 3) |
76 | #endif |
77 | |
78 | static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { |
79 | ScriptInterpreter *script_interpreter = |
80 | debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython); |
81 | return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); |
82 | } |
83 | |
84 | namespace { |
85 | |
86 | // Initializing Python is not a straightforward process. We cannot control |
87 | // what external code may have done before getting to this point in LLDB, |
88 | // including potentially having already initialized Python, so we need to do a |
89 | // lot of work to ensure that the existing state of the system is maintained |
90 | // across our initialization. We do this by using an RAII pattern where we |
91 | // save off initial state at the beginning, and restore it at the end |
92 | struct InitializePythonRAII { |
93 | public: |
94 | InitializePythonRAII() { |
95 | InitializePythonHome(); |
96 | |
97 | #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE1 |
98 | // Python's readline is incompatible with libedit being linked into lldb. |
99 | // Provide a patched version local to the embedded interpreter. |
100 | bool ReadlinePatched = false; |
101 | for (auto *p = PyImport_Inittab; p->name != nullptr; p++) { |
102 | if (strcmp(p->name, "readline") == 0) { |
103 | p->initfunc = initlldb_readline; |
104 | break; |
105 | } |
106 | } |
107 | if (!ReadlinePatched) { |
108 | PyImport_AppendInittab("readline", initlldb_readline); |
109 | ReadlinePatched = true; |
Value stored to 'ReadlinePatched' is never read | |
110 | } |
111 | #endif |
112 | |
113 | // Register _lldb as a built-in module. |
114 | PyImport_AppendInittab("_lldb", LLDBSwigPyInitPyInit__lldb); |
115 | |
116 | // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for |
117 | // calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you |
118 | // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last. |
119 | #if (PY_MAJOR_VERSION3 == 3 && PY_MINOR_VERSION9 >= 2) || (PY_MAJOR_VERSION3 > 3) |
120 | Py_InitializeEx(0); |
121 | InitializeThreadsPrivate(); |
122 | #else |
123 | InitializeThreadsPrivate(); |
124 | Py_InitializeEx(0); |
125 | #endif |
126 | } |
127 | |
128 | ~InitializePythonRAII() { |
129 | if (m_was_already_initialized) { |
130 | Log *log = GetLog(LLDBLog::Script); |
131 | LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Releasing PyGILState. Returning to state = {0}locked" , m_gil_state == PyGILState_UNLOCKED ? "un" : ""); } while (0 ) |
132 | m_gil_state == PyGILState_UNLOCKED ? "un" : "")do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Releasing PyGILState. Returning to state = {0}locked" , m_gil_state == PyGILState_UNLOCKED ? "un" : ""); } while (0 ); |
133 | PyGILState_Release(m_gil_state); |
134 | } else { |
135 | // We initialized the threads in this function, just unlock the GIL. |
136 | PyEval_SaveThread(); |
137 | } |
138 | } |
139 | |
140 | private: |
141 | void InitializePythonHome() { |
142 | #if LLDB_EMBED_PYTHON_HOME0 |
143 | typedef wchar_t *str_type; |
144 | static str_type g_python_home = []() -> str_type { |
145 | const char *lldb_python_home = LLDB_PYTHON_HOME; |
146 | const char *absolute_python_home = nullptr; |
147 | llvm::SmallString<64> path; |
148 | if (llvm::sys::path::is_absolute(lldb_python_home)) { |
149 | absolute_python_home = lldb_python_home; |
150 | } else { |
151 | FileSpec spec = HostInfo::GetShlibDir(); |
152 | if (!spec) |
153 | return nullptr; |
154 | spec.GetPath(path); |
155 | llvm::sys::path::append(path, lldb_python_home); |
156 | absolute_python_home = path.c_str(); |
157 | } |
158 | size_t size = 0; |
159 | return Py_DecodeLocale(absolute_python_home, &size); |
160 | }(); |
161 | if (g_python_home != nullptr) { |
162 | Py_SetPythonHome(g_python_home); |
163 | } |
164 | #endif |
165 | } |
166 | |
167 | void InitializeThreadsPrivate() { |
168 | // Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside itself, |
169 | // so there is no way to determine whether the embedded interpreter |
170 | // was already initialized by some external code. `PyEval_ThreadsInitialized` |
171 | // would always return `true` and `PyGILState_Ensure/Release` flow would be |
172 | // executed instead of unlocking GIL with `PyEval_SaveThread`. When |
173 | // an another thread calls `PyGILState_Ensure` it would get stuck in deadlock. |
174 | #if (PY_MAJOR_VERSION3 == 3 && PY_MINOR_VERSION9 >= 7) || (PY_MAJOR_VERSION3 > 3) |
175 | // The only case we should go further and acquire the GIL: it is unlocked. |
176 | if (PyGILState_Check()) |
177 | return; |
178 | #endif |
179 | |
180 | if (PyEval_ThreadsInitialized()) { |
181 | Log *log = GetLog(LLDBLog::Script); |
182 | |
183 | m_was_already_initialized = true; |
184 | m_gil_state = PyGILState_Ensure(); |
185 | LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n",do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Ensured PyGILState. Previous state = {0}locked\n" , m_gil_state == PyGILState_UNLOCKED ? "un" : ""); } while (0 ) |
186 | m_gil_state == PyGILState_UNLOCKED ? "un" : "")do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Ensured PyGILState. Previous state = {0}locked\n" , m_gil_state == PyGILState_UNLOCKED ? "un" : ""); } while (0 ); |
187 | return; |
188 | } |
189 | |
190 | // InitThreads acquires the GIL if it hasn't been called before. |
191 | PyEval_InitThreads(); |
192 | } |
193 | |
194 | PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; |
195 | bool m_was_already_initialized = false; |
196 | }; |
197 | |
198 | #if LLDB_USE_PYTHON_SET_INTERRUPT(3 == 3 && 9 >= 2) || (3 > 3) |
199 | /// Saves the current signal handler for the specified signal and restores |
200 | /// it at the end of the current scope. |
201 | struct RestoreSignalHandlerScope { |
202 | /// The signal handler. |
203 | struct sigaction m_prev_handler; |
204 | int m_signal_code; |
205 | RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) { |
206 | // Initialize sigaction to their default state. |
207 | std::memset(&m_prev_handler, 0, sizeof(m_prev_handler)); |
208 | // Don't install a new handler, just read back the old one. |
209 | struct sigaction *new_handler = nullptr; |
210 | int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler); |
211 | lldbassert(signal_err == 0 && "sigaction failed to read handler")lldb_private::lldb_assert(static_cast<bool>(signal_err == 0 && "sigaction failed to read handler"), "signal_err == 0 && \"sigaction failed to read handler\"" , __FUNCTION__, "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 211); |
212 | } |
213 | ~RestoreSignalHandlerScope() { |
214 | int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr); |
215 | lldbassert(signal_err == 0 && "sigaction failed to restore old handler")lldb_private::lldb_assert(static_cast<bool>(signal_err == 0 && "sigaction failed to restore old handler"), "signal_err == 0 && \"sigaction failed to restore old handler\"" , __FUNCTION__, "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 215); |
216 | } |
217 | }; |
218 | #endif |
219 | } // namespace |
220 | |
221 | void ScriptInterpreterPython::ComputePythonDirForApple( |
222 | llvm::SmallVectorImpl<char> &path) { |
223 | auto style = llvm::sys::path::Style::posix; |
224 | |
225 | llvm::StringRef path_ref(path.begin(), path.size()); |
226 | auto rbegin = llvm::sys::path::rbegin(path_ref, style); |
227 | auto rend = llvm::sys::path::rend(path_ref); |
228 | auto framework = std::find(rbegin, rend, "LLDB.framework"); |
229 | if (framework == rend) { |
230 | ComputePythonDir(path); |
231 | return; |
232 | } |
233 | path.resize(framework - rend); |
234 | llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python"); |
235 | } |
236 | |
237 | void ScriptInterpreterPython::ComputePythonDir( |
238 | llvm::SmallVectorImpl<char> &path) { |
239 | // Build the path by backing out of the lib dir, then building with whatever |
240 | // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL |
241 | // x86_64, or bin on Windows). |
242 | llvm::sys::path::remove_filename(path); |
243 | llvm::sys::path::append(path, "/llvm-" + std::to_string(LLVM_VERSION_MAJOR17)); |
244 | llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR"lib/python3/dist-packages"); |
245 | |
246 | #if defined(_WIN32) |
247 | // This will be injected directly through FileSpec.SetDirectory(), |
248 | // so we need to normalize manually. |
249 | std::replace(path.begin(), path.end(), '\\', '/'); |
250 | #endif |
251 | } |
252 | |
253 | FileSpec ScriptInterpreterPython::GetPythonDir() { |
254 | static FileSpec g_spec = []() { |
255 | FileSpec spec = HostInfo::GetShlibDir(); |
256 | if (!spec) |
257 | return FileSpec(); |
258 | llvm::SmallString<64> path; |
259 | spec.GetPath(path); |
260 | |
261 | #if defined(__APPLE__) |
262 | ComputePythonDirForApple(path); |
263 | #else |
264 | ComputePythonDir(path); |
265 | #endif |
266 | spec.SetDirectory(path); |
267 | return spec; |
268 | }(); |
269 | return g_spec; |
270 | } |
271 | |
272 | static const char GetInterpreterInfoScript[] = R"( |
273 | import os |
274 | import sys |
275 | |
276 | def main(lldb_python_dir, python_exe_relative_path): |
277 | info = { |
278 | "lldb-pythonpath": lldb_python_dir, |
279 | "language": "python", |
280 | "prefix": sys.prefix, |
281 | "executable": os.path.join(sys.prefix, python_exe_relative_path) |
282 | } |
283 | return info |
284 | )"; |
285 | |
286 | static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH"bin/python3.9"; |
287 | |
288 | StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() { |
289 | GIL gil; |
290 | FileSpec python_dir_spec = GetPythonDir(); |
291 | if (!python_dir_spec) |
292 | return nullptr; |
293 | PythonScript get_info(GetInterpreterInfoScript); |
294 | auto info_json = unwrapIgnoringErrors( |
295 | As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()), |
296 | PythonString(python_exe_relative_path)))); |
297 | if (!info_json) |
298 | return nullptr; |
299 | return info_json.CreateStructuredDictionary(); |
300 | } |
301 | |
302 | void ScriptInterpreterPython::SharedLibraryDirectoryHelper( |
303 | FileSpec &this_file) { |
304 | // When we're loaded from python, this_file will point to the file inside the |
305 | // python package directory. Replace it with the one in the lib directory. |
306 | #ifdef _WIN32 |
307 | // On windows, we need to manually back out of the python tree, and go into |
308 | // the bin directory. This is pretty much the inverse of what ComputePythonDir |
309 | // does. |
310 | if (this_file.GetFileNameExtension() == ".pyd") { |
311 | this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd |
312 | this_file.RemoveLastPathComponent(); // lldb |
313 | llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR"lib/python3/dist-packages"; |
314 | for (auto it = llvm::sys::path::begin(libdir), |
315 | end = llvm::sys::path::end(libdir); |
316 | it != end; ++it) |
317 | this_file.RemoveLastPathComponent(); |
318 | this_file.AppendPathComponent("bin"); |
319 | this_file.AppendPathComponent("liblldb.dll"); |
320 | } |
321 | #else |
322 | // The python file is a symlink, so we can find the real library by resolving |
323 | // it. We can do this unconditionally. |
324 | FileSystem::Instance().ResolveSymbolicLink(this_file, this_file); |
325 | #endif |
326 | } |
327 | |
328 | llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() { |
329 | return "Embedded Python interpreter"; |
330 | } |
331 | |
332 | void ScriptInterpreterPython::Initialize() { |
333 | static llvm::once_flag g_once_flag; |
334 | llvm::call_once(g_once_flag, []() { |
335 | PluginManager::RegisterPlugin(GetPluginNameStatic(), |
336 | GetPluginDescriptionStatic(), |
337 | lldb::eScriptLanguagePython, |
338 | ScriptInterpreterPythonImpl::CreateInstance); |
339 | ScriptInterpreterPythonImpl::Initialize(); |
340 | }); |
341 | } |
342 | |
343 | void ScriptInterpreterPython::Terminate() {} |
344 | |
345 | ScriptInterpreterPythonImpl::Locker::Locker( |
346 | ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry, |
347 | uint16_t on_leave, FileSP in, FileSP out, FileSP err) |
348 | : ScriptInterpreterLocker(), |
349 | m_teardown_session((on_leave & TearDownSession) == TearDownSession), |
350 | m_python_interpreter(py_interpreter) { |
351 | DoAcquireLock(); |
352 | if ((on_entry & InitSession) == InitSession) { |
353 | if (!DoInitSession(on_entry, in, out, err)) { |
354 | // Don't teardown the session if we didn't init it. |
355 | m_teardown_session = false; |
356 | } |
357 | } |
358 | } |
359 | |
360 | bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() { |
361 | Log *log = GetLog(LLDBLog::Script); |
362 | m_GILState = PyGILState_Ensure(); |
363 | LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked",do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Ensured PyGILState. Previous state = {0}locked", m_GILState == PyGILState_UNLOCKED ? "un" : ""); } while (0) |
364 | m_GILState == PyGILState_UNLOCKED ? "un" : "")do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Ensured PyGILState. Previous state = {0}locked", m_GILState == PyGILState_UNLOCKED ? "un" : ""); } while (0); |
365 | |
366 | // we need to save the thread state when we first start the command because |
367 | // we might decide to interrupt it while some action is taking place outside |
368 | // of Python (e.g. printing to screen, waiting for the network, ...) in that |
369 | // case, _PyThreadState_Current will be NULL - and we would be unable to set |
370 | // the asynchronous exception - not a desirable situation |
371 | m_python_interpreter->SetThreadState(PyThreadState_Get()); |
372 | m_python_interpreter->IncrementLockCount(); |
373 | return true; |
374 | } |
375 | |
376 | bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags, |
377 | FileSP in, FileSP out, |
378 | FileSP err) { |
379 | if (!m_python_interpreter) |
380 | return false; |
381 | return m_python_interpreter->EnterSession(on_entry_flags, in, out, err); |
382 | } |
383 | |
384 | bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() { |
385 | Log *log = GetLog(LLDBLog::Script); |
386 | LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Releasing PyGILState. Returning to state = {0}locked" , m_GILState == PyGILState_UNLOCKED ? "un" : ""); } while (0) |
387 | m_GILState == PyGILState_UNLOCKED ? "un" : "")do { ::lldb_private::Log *log_private = (log); if (log_private && log_private->GetVerbose()) log_private->Format ("lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , __func__, "Releasing PyGILState. Returning to state = {0}locked" , m_GILState == PyGILState_UNLOCKED ? "un" : ""); } while (0); |
388 | PyGILState_Release(m_GILState); |
389 | m_python_interpreter->DecrementLockCount(); |
390 | return true; |
391 | } |
392 | |
393 | bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() { |
394 | if (!m_python_interpreter) |
395 | return false; |
396 | m_python_interpreter->LeaveSession(); |
397 | return true; |
398 | } |
399 | |
400 | ScriptInterpreterPythonImpl::Locker::~Locker() { |
401 | if (m_teardown_session) |
402 | DoTearDownSession(); |
403 | DoFreeLock(); |
404 | } |
405 | |
406 | ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) |
407 | : ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(), |
408 | m_saved_stderr(), m_main_module(), |
409 | m_session_dict(PyInitialValue::Invalid), |
410 | m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), |
411 | m_run_one_line_str_global(), |
412 | m_dictionary_name(m_debugger.GetInstanceName().AsCString()), |
413 | m_active_io_handler(eIOHandlerNone), m_session_is_active(false), |
414 | m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), |
415 | m_command_thread_state(nullptr) { |
416 | m_scripted_platform_interface_up = |
417 | std::make_unique<ScriptedPlatformPythonInterface>(*this); |
418 | |
419 | m_dictionary_name.append("_dict"); |
420 | StreamString run_string; |
421 | run_string.Printf("%s = dict()", m_dictionary_name.c_str()); |
422 | |
423 | Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock); |
424 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
425 | |
426 | run_string.Clear(); |
427 | run_string.Printf( |
428 | "run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", |
429 | m_dictionary_name.c_str()); |
430 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
431 | |
432 | // Reloading modules requires a different syntax in Python 2 and Python 3. |
433 | // This provides a consistent syntax no matter what version of Python. |
434 | run_string.Clear(); |
435 | run_string.Printf("run_one_line (%s, 'from importlib import reload as reload_module')", |
436 | m_dictionary_name.c_str()); |
437 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
438 | |
439 | // WARNING: temporary code that loads Cocoa formatters - this should be done |
440 | // on a per-platform basis rather than loading the whole set and letting the |
441 | // individual formatter classes exploit APIs to check whether they can/cannot |
442 | // do their task |
443 | run_string.Clear(); |
444 | run_string.Printf( |
445 | "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')", |
446 | m_dictionary_name.c_str()); |
447 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
448 | run_string.Clear(); |
449 | |
450 | run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from " |
451 | "lldb.embedded_interpreter import run_python_interpreter; " |
452 | "from lldb.embedded_interpreter import run_one_line')", |
453 | m_dictionary_name.c_str()); |
454 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
455 | run_string.Clear(); |
456 | |
457 | run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64"l" "u" |
458 | "')", |
459 | m_dictionary_name.c_str(), m_debugger.GetID()); |
460 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
461 | } |
462 | |
463 | ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() { |
464 | // the session dictionary may hold objects with complex state which means |
465 | // that they may need to be torn down with some level of smarts and that, in |
466 | // turn, requires a valid thread state force Python to procure itself such a |
467 | // thread state, nuke the session dictionary and then release it for others |
468 | // to use and proceed with the rest of the shutdown |
469 | auto gil_state = PyGILState_Ensure(); |
470 | m_session_dict.Reset(); |
471 | PyGILState_Release(gil_state); |
472 | } |
473 | |
474 | void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler, |
475 | bool interactive) { |
476 | const char *instructions = nullptr; |
477 | |
478 | switch (m_active_io_handler) { |
479 | case eIOHandlerNone: |
480 | break; |
481 | case eIOHandlerBreakpoint: |
482 | instructions = R"(Enter your Python command(s). Type 'DONE' to end. |
483 | def function (frame, bp_loc, internal_dict): |
484 | """frame: the lldb.SBFrame for the location at which you stopped |
485 | bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information |
486 | internal_dict: an LLDB support object not to be used""" |
487 | )"; |
488 | break; |
489 | case eIOHandlerWatchpoint: |
490 | instructions = "Enter your Python command(s). Type 'DONE' to end.\n"; |
491 | break; |
492 | } |
493 | |
494 | if (instructions) { |
495 | StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); |
496 | if (output_sp && interactive) { |
497 | output_sp->PutCString(instructions); |
498 | output_sp->Flush(); |
499 | } |
500 | } |
501 | } |
502 | |
503 | void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, |
504 | std::string &data) { |
505 | io_handler.SetIsDone(true); |
506 | bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode(); |
507 | |
508 | switch (m_active_io_handler) { |
509 | case eIOHandlerNone: |
510 | break; |
511 | case eIOHandlerBreakpoint: { |
512 | std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec = |
513 | (std::vector<std::reference_wrapper<BreakpointOptions>> *) |
514 | io_handler.GetUserData(); |
515 | for (BreakpointOptions &bp_options : *bp_options_vec) { |
516 | |
517 | auto data_up = std::make_unique<CommandDataPython>(); |
518 | if (!data_up) |
519 | break; |
520 | data_up->user_source.SplitIntoLines(data); |
521 | |
522 | StructuredData::ObjectSP empty_args_sp; |
523 | if (GenerateBreakpointCommandCallbackData(data_up->user_source, |
524 | data_up->script_source, |
525 | /*has_extra_args=*/false, |
526 | /*is_callback=*/false) |
527 | .Success()) { |
528 | auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>( |
529 | std::move(data_up)); |
530 | bp_options.SetCallback( |
531 | ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); |
532 | } else if (!batch_mode) { |
533 | StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); |
534 | if (error_sp) { |
535 | error_sp->Printf("Warning: No command attached to breakpoint.\n"); |
536 | error_sp->Flush(); |
537 | } |
538 | } |
539 | } |
540 | m_active_io_handler = eIOHandlerNone; |
541 | } break; |
542 | case eIOHandlerWatchpoint: { |
543 | WatchpointOptions *wp_options = |
544 | (WatchpointOptions *)io_handler.GetUserData(); |
545 | auto data_up = std::make_unique<WatchpointOptions::CommandData>(); |
546 | data_up->user_source.SplitIntoLines(data); |
547 | |
548 | if (GenerateWatchpointCommandCallbackData(data_up->user_source, |
549 | data_up->script_source, |
550 | /*is_callback=*/false)) { |
551 | auto baton_sp = |
552 | std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); |
553 | wp_options->SetCallback( |
554 | ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); |
555 | } else if (!batch_mode) { |
556 | StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); |
557 | if (error_sp) { |
558 | error_sp->Printf("Warning: No command attached to breakpoint.\n"); |
559 | error_sp->Flush(); |
560 | } |
561 | } |
562 | m_active_io_handler = eIOHandlerNone; |
563 | } break; |
564 | } |
565 | } |
566 | |
567 | lldb::ScriptInterpreterSP |
568 | ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) { |
569 | return std::make_shared<ScriptInterpreterPythonImpl>(debugger); |
570 | } |
571 | |
572 | void ScriptInterpreterPythonImpl::LeaveSession() { |
573 | Log *log = GetLog(LLDBLog::Script); |
574 | if (log) |
575 | log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()"); |
576 | |
577 | // Unset the LLDB global variables. |
578 | PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "PyRun_SimpleStringFlags("lldb.debugger = None; lldb.target = None; lldb.process " "= None; lldb.thread = None; lldb.frame = None", __null) |
579 | "= None; lldb.thread = None; lldb.frame = None")PyRun_SimpleStringFlags("lldb.debugger = None; lldb.target = None; lldb.process " "= None; lldb.thread = None; lldb.frame = None", __null); |
580 | |
581 | // checking that we have a valid thread state - since we use our own |
582 | // threading and locking in some (rare) cases during cleanup Python may end |
583 | // up believing we have no thread state and PyImport_AddModule will crash if |
584 | // that is the case - since that seems to only happen when destroying the |
585 | // SBDebugger, we can make do without clearing up stdout and stderr |
586 | |
587 | // rdar://problem/11292882 |
588 | // When the current thread state is NULL, PyThreadState_Get() issues a fatal |
589 | // error. |
590 | if (PyThreadState_GetDict()) { |
591 | PythonDictionary &sys_module_dict = GetSysModuleDictionary(); |
592 | if (sys_module_dict.IsValid()) { |
593 | if (m_saved_stdin.IsValid()) { |
594 | sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin); |
595 | m_saved_stdin.Reset(); |
596 | } |
597 | if (m_saved_stdout.IsValid()) { |
598 | sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout); |
599 | m_saved_stdout.Reset(); |
600 | } |
601 | if (m_saved_stderr.IsValid()) { |
602 | sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr); |
603 | m_saved_stderr.Reset(); |
604 | } |
605 | } |
606 | } |
607 | |
608 | m_session_is_active = false; |
609 | } |
610 | |
611 | bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp, |
612 | const char *py_name, |
613 | PythonObject &save_file, |
614 | const char *mode) { |
615 | if (!file_sp || !*file_sp) { |
616 | save_file.Reset(); |
617 | return false; |
618 | } |
619 | File &file = *file_sp; |
620 | |
621 | // Flush the file before giving it to python to avoid interleaved output. |
622 | file.Flush(); |
623 | |
624 | PythonDictionary &sys_module_dict = GetSysModuleDictionary(); |
625 | |
626 | auto new_file = PythonFile::FromFile(file, mode); |
627 | if (!new_file) { |
628 | llvm::consumeError(new_file.takeError()); |
629 | return false; |
630 | } |
631 | |
632 | save_file = sys_module_dict.GetItemForKey(PythonString(py_name)); |
633 | |
634 | sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get()); |
635 | return true; |
636 | } |
637 | |
638 | bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, |
639 | FileSP in_sp, FileSP out_sp, |
640 | FileSP err_sp) { |
641 | // If we have already entered the session, without having officially 'left' |
642 | // it, then there is no need to 'enter' it again. |
643 | Log *log = GetLog(LLDBLog::Script); |
644 | if (m_session_is_active) { |
645 | LLDB_LOGF(do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ") session is already active, returning without doing anything" , on_entry_flags); } while (0) |
646 | log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ") session is already active, returning without doing anything" , on_entry_flags); } while (0) |
647 | "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ") session is already active, returning without doing anything" , on_entry_flags); } while (0) |
648 | ") session is already active, returning without doing anything",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ") session is already active, returning without doing anything" , on_entry_flags); } while (0) |
649 | on_entry_flags)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ") session is already active, returning without doing anything" , on_entry_flags); } while (0); |
650 | return false; |
651 | } |
652 | |
653 | LLDB_LOGF(do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ")", on_entry_flags); } while (0) |
654 | log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ")", on_entry_flags); } while (0) |
655 | "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ")", on_entry_flags); } while (0) |
656 | on_entry_flags)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" "x" ")", on_entry_flags); } while (0); |
657 | |
658 | m_session_is_active = true; |
659 | |
660 | StreamString run_string; |
661 | |
662 | if (on_entry_flags & Locker::InitGlobals) { |
663 | run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64"l" "u", |
664 | m_dictionary_name.c_str(), m_debugger.GetID()); |
665 | run_string.Printf( |
666 | "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64"l" "u" ")", |
667 | m_debugger.GetID()); |
668 | run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()"); |
669 | run_string.PutCString("; lldb.process = lldb.target.GetProcess()"); |
670 | run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()"); |
671 | run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()"); |
672 | run_string.PutCString("')"); |
673 | } else { |
674 | // If we aren't initing the globals, we should still always set the |
675 | // debugger (since that is always unique.) |
676 | run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64"l" "u", |
677 | m_dictionary_name.c_str(), m_debugger.GetID()); |
678 | run_string.Printf( |
679 | "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64"l" "u" ")", |
680 | m_debugger.GetID()); |
681 | run_string.PutCString("')"); |
682 | } |
683 | |
684 | PyRun_SimpleString(run_string.GetData())PyRun_SimpleStringFlags(run_string.GetData(), __null); |
685 | run_string.Clear(); |
686 | |
687 | PythonDictionary &sys_module_dict = GetSysModuleDictionary(); |
688 | if (sys_module_dict.IsValid()) { |
689 | lldb::FileSP top_in_sp; |
690 | lldb::StreamFileSP top_out_sp, top_err_sp; |
691 | if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp) |
692 | m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp, |
693 | top_err_sp); |
694 | |
695 | if (on_entry_flags & Locker::NoSTDIN) { |
696 | m_saved_stdin.Reset(); |
697 | } else { |
698 | if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) { |
699 | if (top_in_sp) |
700 | SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r"); |
701 | } |
702 | } |
703 | |
704 | if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) { |
705 | if (top_out_sp) |
706 | SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w"); |
707 | } |
708 | |
709 | if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) { |
710 | if (top_err_sp) |
711 | SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w"); |
712 | } |
713 | } |
714 | |
715 | if (PyErr_Occurred()) |
716 | PyErr_Clear(); |
717 | |
718 | return true; |
719 | } |
720 | |
721 | PythonModule &ScriptInterpreterPythonImpl::GetMainModule() { |
722 | if (!m_main_module.IsValid()) |
723 | m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__")); |
724 | return m_main_module; |
725 | } |
726 | |
727 | PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() { |
728 | if (m_session_dict.IsValid()) |
729 | return m_session_dict; |
730 | |
731 | PythonObject &main_module = GetMainModule(); |
732 | if (!main_module.IsValid()) |
733 | return m_session_dict; |
734 | |
735 | PythonDictionary main_dict(PyRefType::Borrowed, |
736 | PyModule_GetDict(main_module.get())); |
737 | if (!main_dict.IsValid()) |
738 | return m_session_dict; |
739 | |
740 | m_session_dict = unwrapIgnoringErrors( |
741 | As<PythonDictionary>(main_dict.GetItem(m_dictionary_name))); |
742 | return m_session_dict; |
743 | } |
744 | |
745 | PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() { |
746 | if (m_sys_module_dict.IsValid()) |
747 | return m_sys_module_dict; |
748 | PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys")); |
749 | m_sys_module_dict = sys_module.GetDictionary(); |
750 | return m_sys_module_dict; |
751 | } |
752 | |
753 | llvm::Expected<unsigned> |
754 | ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable( |
755 | const llvm::StringRef &callable_name) { |
756 | if (callable_name.empty()) { |
757 | return llvm::createStringError( |
758 | llvm::inconvertibleErrorCode(), |
759 | "called with empty callable name."); |
760 | } |
761 | Locker py_lock(this, Locker::AcquireLock | |
762 | Locker::InitSession | |
763 | Locker::NoSTDIN); |
764 | auto dict = PythonModule::MainModule() |
765 | .ResolveName<PythonDictionary>(m_dictionary_name); |
766 | auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>( |
767 | callable_name, dict); |
768 | if (!pfunc.IsAllocated()) { |
769 | return llvm::createStringError( |
770 | llvm::inconvertibleErrorCode(), |
771 | "can't find callable: %s", callable_name.str().c_str()); |
772 | } |
773 | llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo(); |
774 | if (!arg_info) |
775 | return arg_info.takeError(); |
776 | return arg_info.get().max_positional_args; |
777 | } |
778 | |
779 | static std::string GenerateUniqueName(const char *base_name_wanted, |
780 | uint32_t &functions_counter, |
781 | const void *name_token = nullptr) { |
782 | StreamString sstr; |
783 | |
784 | if (!base_name_wanted) |
785 | return std::string(); |
786 | |
787 | if (!name_token) |
788 | sstr.Printf("%s_%d", base_name_wanted, functions_counter++); |
789 | else |
790 | sstr.Printf("%s_%p", base_name_wanted, name_token); |
791 | |
792 | return std::string(sstr.GetString()); |
793 | } |
794 | |
795 | bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() { |
796 | if (m_run_one_line_function.IsValid()) |
797 | return true; |
798 | |
799 | PythonObject module(PyRefType::Borrowed, |
800 | PyImport_AddModule("lldb.embedded_interpreter")); |
801 | if (!module.IsValid()) |
802 | return false; |
803 | |
804 | PythonDictionary module_dict(PyRefType::Borrowed, |
805 | PyModule_GetDict(module.get())); |
806 | if (!module_dict.IsValid()) |
807 | return false; |
808 | |
809 | m_run_one_line_function = |
810 | module_dict.GetItemForKey(PythonString("run_one_line")); |
811 | m_run_one_line_str_global = |
812 | module_dict.GetItemForKey(PythonString("g_run_one_line_str")); |
813 | return m_run_one_line_function.IsValid(); |
814 | } |
815 | |
816 | bool ScriptInterpreterPythonImpl::ExecuteOneLine( |
817 | llvm::StringRef command, CommandReturnObject *result, |
818 | const ExecuteScriptOptions &options) { |
819 | std::string command_str = command.str(); |
820 | |
821 | if (!m_valid_session) |
822 | return false; |
823 | |
824 | if (!command.empty()) { |
825 | // We want to call run_one_line, passing in the dictionary and the command |
826 | // string. We cannot do this through PyRun_SimpleString here because the |
827 | // command string may contain escaped characters, and putting it inside |
828 | // another string to pass to PyRun_SimpleString messes up the escaping. So |
829 | // we use the following more complicated method to pass the command string |
830 | // directly down to Python. |
831 | llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> |
832 | io_redirect_or_error = ScriptInterpreterIORedirect::Create( |
833 | options.GetEnableIO(), m_debugger, result); |
834 | if (!io_redirect_or_error) { |
835 | if (result) |
836 | result->AppendErrorWithFormatv( |
837 | "failed to redirect I/O: {0}\n", |
838 | llvm::fmt_consume(io_redirect_or_error.takeError())); |
839 | else |
840 | llvm::consumeError(io_redirect_or_error.takeError()); |
841 | return false; |
842 | } |
843 | |
844 | ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; |
845 | |
846 | bool success = false; |
847 | { |
848 | // WARNING! It's imperative that this RAII scope be as tight as |
849 | // possible. In particular, the scope must end *before* we try to join |
850 | // the read thread. The reason for this is that a pre-requisite for |
851 | // joining the read thread is that we close the write handle (to break |
852 | // the pipe and cause it to wake up and exit). But acquiring the GIL as |
853 | // below will redirect Python's stdio to use this same handle. If we |
854 | // close the handle while Python is still using it, bad things will |
855 | // happen. |
856 | Locker locker( |
857 | this, |
858 | Locker::AcquireLock | Locker::InitSession | |
859 | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | |
860 | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), |
861 | Locker::FreeAcquiredLock | Locker::TearDownSession, |
862 | io_redirect.GetInputFile(), io_redirect.GetOutputFile(), |
863 | io_redirect.GetErrorFile()); |
864 | |
865 | // Find the correct script interpreter dictionary in the main module. |
866 | PythonDictionary &session_dict = GetSessionDictionary(); |
867 | if (session_dict.IsValid()) { |
868 | if (GetEmbeddedInterpreterModuleObjects()) { |
869 | if (PyCallable_Check(m_run_one_line_function.get())) { |
870 | PythonObject pargs( |
871 | PyRefType::Owned, |
872 | Py_BuildValue("(Os)", session_dict.get(), command_str.c_str())); |
873 | if (pargs.IsValid()) { |
874 | PythonObject return_value( |
875 | PyRefType::Owned, |
876 | PyObject_CallObject(m_run_one_line_function.get(), |
877 | pargs.get())); |
878 | if (return_value.IsValid()) |
879 | success = true; |
880 | else if (options.GetMaskoutErrors() && PyErr_Occurred()) { |
881 | PyErr_Print(); |
882 | PyErr_Clear(); |
883 | } |
884 | } |
885 | } |
886 | } |
887 | } |
888 | |
889 | io_redirect.Flush(); |
890 | } |
891 | |
892 | if (success) |
893 | return true; |
894 | |
895 | // The one-liner failed. Append the error message. |
896 | if (result) { |
897 | result->AppendErrorWithFormat( |
898 | "python failed attempting to evaluate '%s'\n", command_str.c_str()); |
899 | } |
900 | return false; |
901 | } |
902 | |
903 | if (result) |
904 | result->AppendError("empty command passed to python\n"); |
905 | return false; |
906 | } |
907 | |
908 | void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { |
909 | LLDB_SCOPED_TIMER()static ::lldb_private::Timer::Category _cat(__PRETTY_FUNCTION__ ); ::lldb_private::Timer _scoped_timer(_cat, "%s", __PRETTY_FUNCTION__ ); |
910 | |
911 | Debugger &debugger = m_debugger; |
912 | |
913 | // At the moment, the only time the debugger does not have an input file |
914 | // handle is when this is called directly from Python, in which case it is |
915 | // both dangerous and unnecessary (not to mention confusing) to try to embed |
916 | // a running interpreter loop inside the already running Python interpreter |
917 | // loop, so we won't do it. |
918 | |
919 | if (!debugger.GetInputFile().IsValid()) |
920 | return; |
921 | |
922 | IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this)); |
923 | if (io_handler_sp) { |
924 | debugger.RunIOHandlerAsync(io_handler_sp); |
925 | } |
926 | } |
927 | |
928 | bool ScriptInterpreterPythonImpl::Interrupt() { |
929 | #if LLDB_USE_PYTHON_SET_INTERRUPT(3 == 3 && 9 >= 2) || (3 > 3) |
930 | // If the interpreter isn't evaluating any Python at the moment then return |
931 | // false to signal that this function didn't handle the interrupt and the |
932 | // next component should try handling it. |
933 | if (!IsExecutingPython()) |
934 | return false; |
935 | |
936 | // Tell Python that it should pretend to have received a SIGINT. |
937 | PyErr_SetInterrupt(); |
938 | // PyErr_SetInterrupt has no way to return an error so we can only pretend the |
939 | // signal got successfully handled and return true. |
940 | // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but |
941 | // the error handling is limited to checking the arguments which would be |
942 | // just our (hardcoded) input signal code SIGINT, so that's not useful at all. |
943 | return true; |
944 | #else |
945 | Log *log = GetLog(LLDBLog::Script); |
946 | |
947 | if (IsExecutingPython()) { |
948 | PyThreadState *state = PyThreadState_GET()PyThreadState_Get(); |
949 | if (!state) |
950 | state = GetThreadState(); |
951 | if (state) { |
952 | long tid = state->thread_id; |
953 | PyThreadState_Swap(state); |
954 | int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); |
955 | LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid , num_threads); } while (0) |
956 | "ScriptInterpreterPythonImpl::Interrupt() sending "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid , num_threads); } while (0) |
957 | "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid , num_threads); } while (0) |
958 | tid, num_threads)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid , num_threads); } while (0); |
959 | return true; |
960 | } |
961 | } |
962 | LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() python code not running, " "can't interrupt"); } while (0) |
963 | "ScriptInterpreterPythonImpl::Interrupt() python code not running, "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() python code not running, " "can't interrupt"); } while (0) |
964 | "can't interrupt")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Printf("ScriptInterpreterPythonImpl::Interrupt() python code not running, " "can't interrupt"); } while (0); |
965 | return false; |
966 | #endif |
967 | } |
968 | |
969 | bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( |
970 | llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, |
971 | void *ret_value, const ExecuteScriptOptions &options) { |
972 | |
973 | llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> |
974 | io_redirect_or_error = ScriptInterpreterIORedirect::Create( |
975 | options.GetEnableIO(), m_debugger, /*result=*/nullptr); |
976 | |
977 | if (!io_redirect_or_error) { |
978 | llvm::consumeError(io_redirect_or_error.takeError()); |
979 | return false; |
980 | } |
981 | |
982 | ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; |
983 | |
984 | Locker locker(this, |
985 | Locker::AcquireLock | Locker::InitSession | |
986 | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | |
987 | Locker::NoSTDIN, |
988 | Locker::FreeAcquiredLock | Locker::TearDownSession, |
989 | io_redirect.GetInputFile(), io_redirect.GetOutputFile(), |
990 | io_redirect.GetErrorFile()); |
991 | |
992 | PythonModule &main_module = GetMainModule(); |
993 | PythonDictionary globals = main_module.GetDictionary(); |
994 | |
995 | PythonDictionary locals = GetSessionDictionary(); |
996 | if (!locals.IsValid()) |
997 | locals = unwrapIgnoringErrors( |
998 | As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); |
999 | if (!locals.IsValid()) |
1000 | locals = globals; |
1001 | |
1002 | Expected<PythonObject> maybe_py_return = |
1003 | runStringOneLine(in_string, globals, locals); |
1004 | |
1005 | if (!maybe_py_return) { |
1006 | llvm::handleAllErrors( |
1007 | maybe_py_return.takeError(), |
1008 | [&](PythonException &E) { |
1009 | E.Restore(); |
1010 | if (options.GetMaskoutErrors()) { |
1011 | if (E.Matches(PyExc_SyntaxError)) { |
1012 | PyErr_Print(); |
1013 | } |
1014 | PyErr_Clear(); |
1015 | } |
1016 | }, |
1017 | [](const llvm::ErrorInfoBase &E) {}); |
1018 | return false; |
1019 | } |
1020 | |
1021 | PythonObject py_return = std::move(maybe_py_return.get()); |
1022 | assert(py_return.IsValid())(static_cast <bool> (py_return.IsValid()) ? void (0) : __assert_fail ("py_return.IsValid()", "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 1022, __extension__ __PRETTY_FUNCTION__)); |
1023 | |
1024 | switch (return_type) { |
1025 | case eScriptReturnTypeCharPtr: // "char *" |
1026 | { |
1027 | const char format[3] = "s#"; |
1028 | return PyArg_Parse(py_return.get(), format, (char **)ret_value); |
1029 | } |
1030 | case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == |
1031 | // Py_None |
1032 | { |
1033 | const char format[3] = "z"; |
1034 | return PyArg_Parse(py_return.get(), format, (char **)ret_value); |
1035 | } |
1036 | case eScriptReturnTypeBool: { |
1037 | const char format[2] = "b"; |
1038 | return PyArg_Parse(py_return.get(), format, (bool *)ret_value); |
1039 | } |
1040 | case eScriptReturnTypeShortInt: { |
1041 | const char format[2] = "h"; |
1042 | return PyArg_Parse(py_return.get(), format, (short *)ret_value); |
1043 | } |
1044 | case eScriptReturnTypeShortIntUnsigned: { |
1045 | const char format[2] = "H"; |
1046 | return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); |
1047 | } |
1048 | case eScriptReturnTypeInt: { |
1049 | const char format[2] = "i"; |
1050 | return PyArg_Parse(py_return.get(), format, (int *)ret_value); |
1051 | } |
1052 | case eScriptReturnTypeIntUnsigned: { |
1053 | const char format[2] = "I"; |
1054 | return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); |
1055 | } |
1056 | case eScriptReturnTypeLongInt: { |
1057 | const char format[2] = "l"; |
1058 | return PyArg_Parse(py_return.get(), format, (long *)ret_value); |
1059 | } |
1060 | case eScriptReturnTypeLongIntUnsigned: { |
1061 | const char format[2] = "k"; |
1062 | return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); |
1063 | } |
1064 | case eScriptReturnTypeLongLong: { |
1065 | const char format[2] = "L"; |
1066 | return PyArg_Parse(py_return.get(), format, (long long *)ret_value); |
1067 | } |
1068 | case eScriptReturnTypeLongLongUnsigned: { |
1069 | const char format[2] = "K"; |
1070 | return PyArg_Parse(py_return.get(), format, |
1071 | (unsigned long long *)ret_value); |
1072 | } |
1073 | case eScriptReturnTypeFloat: { |
1074 | const char format[2] = "f"; |
1075 | return PyArg_Parse(py_return.get(), format, (float *)ret_value); |
1076 | } |
1077 | case eScriptReturnTypeDouble: { |
1078 | const char format[2] = "d"; |
1079 | return PyArg_Parse(py_return.get(), format, (double *)ret_value); |
1080 | } |
1081 | case eScriptReturnTypeChar: { |
1082 | const char format[2] = "c"; |
1083 | return PyArg_Parse(py_return.get(), format, (char *)ret_value); |
1084 | } |
1085 | case eScriptReturnTypeOpaqueObject: { |
1086 | *((PyObject **)ret_value) = py_return.release(); |
1087 | return true; |
1088 | } |
1089 | } |
1090 | llvm_unreachable("Fully covered switch!")::llvm::llvm_unreachable_internal("Fully covered switch!", "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 1090); |
1091 | } |
1092 | |
1093 | Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( |
1094 | const char *in_string, const ExecuteScriptOptions &options) { |
1095 | |
1096 | if (in_string == nullptr) |
1097 | return Status(); |
1098 | |
1099 | llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> |
1100 | io_redirect_or_error = ScriptInterpreterIORedirect::Create( |
1101 | options.GetEnableIO(), m_debugger, /*result=*/nullptr); |
1102 | |
1103 | if (!io_redirect_or_error) |
1104 | return Status(io_redirect_or_error.takeError()); |
1105 | |
1106 | ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; |
1107 | |
1108 | Locker locker(this, |
1109 | Locker::AcquireLock | Locker::InitSession | |
1110 | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | |
1111 | Locker::NoSTDIN, |
1112 | Locker::FreeAcquiredLock | Locker::TearDownSession, |
1113 | io_redirect.GetInputFile(), io_redirect.GetOutputFile(), |
1114 | io_redirect.GetErrorFile()); |
1115 | |
1116 | PythonModule &main_module = GetMainModule(); |
1117 | PythonDictionary globals = main_module.GetDictionary(); |
1118 | |
1119 | PythonDictionary locals = GetSessionDictionary(); |
1120 | if (!locals.IsValid()) |
1121 | locals = unwrapIgnoringErrors( |
1122 | As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); |
1123 | if (!locals.IsValid()) |
1124 | locals = globals; |
1125 | |
1126 | Expected<PythonObject> return_value = |
1127 | runStringMultiLine(in_string, globals, locals); |
1128 | |
1129 | if (!return_value) { |
1130 | llvm::Error error = |
1131 | llvm::handleErrors(return_value.takeError(), [&](PythonException &E) { |
1132 | llvm::Error error = llvm::createStringError( |
1133 | llvm::inconvertibleErrorCode(), E.ReadBacktrace()); |
1134 | if (!options.GetMaskoutErrors()) |
1135 | E.Restore(); |
1136 | return error; |
1137 | }); |
1138 | return Status(std::move(error)); |
1139 | } |
1140 | |
1141 | return Status(); |
1142 | } |
1143 | |
1144 | void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( |
1145 | std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, |
1146 | CommandReturnObject &result) { |
1147 | m_active_io_handler = eIOHandlerBreakpoint; |
1148 | m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler( |
1149 | " ", *this, &bp_options_vec); |
1150 | } |
1151 | |
1152 | void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback( |
1153 | WatchpointOptions *wp_options, CommandReturnObject &result) { |
1154 | m_active_io_handler = eIOHandlerWatchpoint; |
1155 | m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler( |
1156 | " ", *this, wp_options); |
1157 | } |
1158 | |
1159 | Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( |
1160 | BreakpointOptions &bp_options, const char *function_name, |
1161 | StructuredData::ObjectSP extra_args_sp) { |
1162 | Status error; |
1163 | // For now just cons up a oneliner that calls the provided function. |
1164 | std::string function_signature = function_name; |
1165 | |
1166 | llvm::Expected<unsigned> maybe_args = |
1167 | GetMaxPositionalArgumentsForCallable(function_name); |
1168 | if (!maybe_args) { |
1169 | error.SetErrorStringWithFormat( |
1170 | "could not get num args: %s", |
1171 | llvm::toString(maybe_args.takeError()).c_str()); |
1172 | return error; |
1173 | } |
1174 | size_t max_args = *maybe_args; |
1175 | |
1176 | bool uses_extra_args = false; |
1177 | if (max_args >= 4) { |
1178 | uses_extra_args = true; |
1179 | function_signature += "(frame, bp_loc, extra_args, internal_dict)"; |
1180 | } else if (max_args >= 3) { |
1181 | if (extra_args_sp) { |
1182 | error.SetErrorString("cannot pass extra_args to a three argument callback" |
1183 | ); |
1184 | return error; |
1185 | } |
1186 | uses_extra_args = false; |
1187 | function_signature += "(frame, bp_loc, internal_dict)"; |
1188 | } else { |
1189 | error.SetErrorStringWithFormat("expected 3 or 4 argument " |
1190 | "function, %s can only take %zu", |
1191 | function_name, max_args); |
1192 | return error; |
1193 | } |
1194 | |
1195 | SetBreakpointCommandCallback(bp_options, function_signature.c_str(), |
1196 | extra_args_sp, uses_extra_args, |
1197 | /*is_callback=*/true); |
1198 | return error; |
1199 | } |
1200 | |
1201 | Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( |
1202 | BreakpointOptions &bp_options, |
1203 | std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) { |
1204 | Status error; |
1205 | error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source, |
1206 | cmd_data_up->script_source, |
1207 | /*has_extra_args=*/false, |
1208 | /*is_callback=*/false); |
1209 | if (error.Fail()) { |
1210 | return error; |
1211 | } |
1212 | auto baton_sp = |
1213 | std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up)); |
1214 | bp_options.SetCallback( |
1215 | ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); |
1216 | return error; |
1217 | } |
1218 | |
1219 | Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( |
1220 | BreakpointOptions &bp_options, const char *command_body_text, |
1221 | bool is_callback) { |
1222 | return SetBreakpointCommandCallback(bp_options, command_body_text, {}, |
1223 | /*uses_extra_args=*/false, is_callback); |
1224 | } |
1225 | |
1226 | // Set a Python one-liner as the callback for the breakpoint. |
1227 | Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( |
1228 | BreakpointOptions &bp_options, const char *command_body_text, |
1229 | StructuredData::ObjectSP extra_args_sp, bool uses_extra_args, |
1230 | bool is_callback) { |
1231 | auto data_up = std::make_unique<CommandDataPython>(extra_args_sp); |
1232 | // Split the command_body_text into lines, and pass that to |
1233 | // GenerateBreakpointCommandCallbackData. That will wrap the body in an |
1234 | // auto-generated function, and return the function name in script_source. |
1235 | // That is what the callback will actually invoke. |
1236 | |
1237 | data_up->user_source.SplitIntoLines(command_body_text); |
1238 | Status error = GenerateBreakpointCommandCallbackData( |
1239 | data_up->user_source, data_up->script_source, uses_extra_args, |
1240 | is_callback); |
1241 | if (error.Success()) { |
1242 | auto baton_sp = |
1243 | std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up)); |
1244 | bp_options.SetCallback( |
1245 | ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); |
1246 | return error; |
1247 | } |
1248 | return error; |
1249 | } |
1250 | |
1251 | // Set a Python one-liner as the callback for the watchpoint. |
1252 | void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( |
1253 | WatchpointOptions *wp_options, const char *user_input, |
1254 | bool is_callback) { |
1255 | auto data_up = std::make_unique<WatchpointOptions::CommandData>(); |
1256 | |
1257 | // It's necessary to set both user_source and script_source to the oneliner. |
1258 | // The former is used to generate callback description (as in watchpoint |
1259 | // command list) while the latter is used for Python to interpret during the |
1260 | // actual callback. |
1261 | |
1262 | data_up->user_source.AppendString(user_input); |
1263 | data_up->script_source.assign(user_input); |
1264 | |
1265 | if (GenerateWatchpointCommandCallbackData( |
1266 | data_up->user_source, data_up->script_source, is_callback)) { |
1267 | auto baton_sp = |
1268 | std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); |
1269 | wp_options->SetCallback( |
1270 | ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); |
1271 | } |
1272 | } |
1273 | |
1274 | Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( |
1275 | StringList &function_def) { |
1276 | // Convert StringList to one long, newline delimited, const char *. |
1277 | std::string function_def_string(function_def.CopyList()); |
1278 | |
1279 | Status error = ExecuteMultipleLines( |
1280 | function_def_string.c_str(), |
1281 | ExecuteScriptOptions().SetEnableIO(false)); |
1282 | return error; |
1283 | } |
1284 | |
1285 | Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature, |
1286 | const StringList &input, |
1287 | bool is_callback) { |
1288 | Status error; |
1289 | int num_lines = input.GetSize(); |
1290 | if (num_lines == 0) { |
1291 | error.SetErrorString("No input data."); |
1292 | return error; |
1293 | } |
1294 | |
1295 | if (!signature || *signature == 0) { |
1296 | error.SetErrorString("No output function name."); |
1297 | return error; |
1298 | } |
1299 | |
1300 | StreamString sstr; |
1301 | StringList auto_generated_function; |
1302 | auto_generated_function.AppendString(signature); |
1303 | auto_generated_function.AppendString( |
1304 | " global_dict = globals()"); // Grab the global dictionary |
1305 | auto_generated_function.AppendString( |
1306 | " new_keys = internal_dict.keys()"); // Make a list of keys in the |
1307 | // session dict |
1308 | auto_generated_function.AppendString( |
1309 | " old_keys = global_dict.keys()"); // Save list of keys in global dict |
1310 | auto_generated_function.AppendString( |
1311 | " global_dict.update(internal_dict)"); // Add the session dictionary |
1312 | // to the global dictionary. |
1313 | |
1314 | if (is_callback) { |
1315 | // If the user input is a callback to a python function, make sure the input |
1316 | // is only 1 line, otherwise appending the user input would break the |
1317 | // generated wrapped function |
1318 | if (num_lines == 1) { |
1319 | sstr.Clear(); |
1320 | sstr.Printf(" __return_val = %s", input.GetStringAtIndex(0)); |
1321 | auto_generated_function.AppendString(sstr.GetData()); |
1322 | } else { |
1323 | return Status("ScriptInterpreterPythonImpl::GenerateFunction(is_callback=" |
1324 | "true) = ERROR: python function is multiline."); |
1325 | } |
1326 | } else { |
1327 | auto_generated_function.AppendString( |
1328 | " __return_val = None"); // Initialize user callback return value. |
1329 | auto_generated_function.AppendString( |
1330 | " def __user_code():"); // Create a nested function that will wrap |
1331 | // the user input. This is necessary to |
1332 | // capture the return value of the user input |
1333 | // and prevent early returns. |
1334 | for (int i = 0; i < num_lines; ++i) { |
1335 | sstr.Clear(); |
1336 | sstr.Printf(" %s", input.GetStringAtIndex(i)); |
1337 | auto_generated_function.AppendString(sstr.GetData()); |
1338 | } |
1339 | auto_generated_function.AppendString( |
1340 | " __return_val = __user_code()"); // Call user code and capture |
1341 | // return value |
1342 | } |
1343 | auto_generated_function.AppendString( |
1344 | " for key in new_keys:"); // Iterate over all the keys from session |
1345 | // dict |
1346 | auto_generated_function.AppendString( |
1347 | " internal_dict[key] = global_dict[key]"); // Update session dict |
1348 | // values |
1349 | auto_generated_function.AppendString( |
1350 | " if key not in old_keys:"); // If key was not originally in |
1351 | // global dict |
1352 | auto_generated_function.AppendString( |
1353 | " del global_dict[key]"); // ...then remove key/value from |
1354 | // global dict |
1355 | auto_generated_function.AppendString( |
1356 | " return __return_val"); // Return the user callback return value. |
1357 | |
1358 | // Verify that the results are valid Python. |
1359 | error = ExportFunctionDefinitionToInterpreter(auto_generated_function); |
1360 | |
1361 | return error; |
1362 | } |
1363 | |
1364 | bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( |
1365 | StringList &user_input, std::string &output, const void *name_token) { |
1366 | static uint32_t num_created_functions = 0; |
1367 | user_input.RemoveBlankLines(); |
1368 | StreamString sstr; |
1369 | |
1370 | // Check to see if we have any data; if not, just return. |
1371 | if (user_input.GetSize() == 0) |
1372 | return false; |
1373 | |
1374 | // Take what the user wrote, wrap it all up inside one big auto-generated |
1375 | // Python function, passing in the ValueObject as parameter to the function. |
1376 | |
1377 | std::string auto_generated_function_name( |
1378 | GenerateUniqueName("lldb_autogen_python_type_print_func", |
1379 | num_created_functions, name_token)); |
1380 | sstr.Printf("def %s (valobj, internal_dict):", |
1381 | auto_generated_function_name.c_str()); |
1382 | |
1383 | if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false) |
1384 | .Success()) |
1385 | return false; |
1386 | |
1387 | // Store the name of the auto-generated function to be called. |
1388 | output.assign(auto_generated_function_name); |
1389 | return true; |
1390 | } |
1391 | |
1392 | bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( |
1393 | StringList &user_input, std::string &output) { |
1394 | static uint32_t num_created_functions = 0; |
1395 | user_input.RemoveBlankLines(); |
1396 | StreamString sstr; |
1397 | |
1398 | // Check to see if we have any data; if not, just return. |
1399 | if (user_input.GetSize() == 0) |
1400 | return false; |
1401 | |
1402 | std::string auto_generated_function_name(GenerateUniqueName( |
1403 | "lldb_autogen_python_cmd_alias_func", num_created_functions)); |
1404 | |
1405 | sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):", |
1406 | auto_generated_function_name.c_str()); |
1407 | |
1408 | if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/true) |
1409 | .Success()) |
1410 | return false; |
1411 | |
1412 | // Store the name of the auto-generated function to be called. |
1413 | output.assign(auto_generated_function_name); |
1414 | return true; |
1415 | } |
1416 | |
1417 | bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass( |
1418 | StringList &user_input, std::string &output, const void *name_token) { |
1419 | static uint32_t num_created_classes = 0; |
1420 | user_input.RemoveBlankLines(); |
1421 | int num_lines = user_input.GetSize(); |
1422 | StreamString sstr; |
1423 | |
1424 | // Check to see if we have any data; if not, just return. |
1425 | if (user_input.GetSize() == 0) |
1426 | return false; |
1427 | |
1428 | // Wrap all user input into a Python class |
1429 | |
1430 | std::string auto_generated_class_name(GenerateUniqueName( |
1431 | "lldb_autogen_python_type_synth_class", num_created_classes, name_token)); |
1432 | |
1433 | StringList auto_generated_class; |
1434 | |
1435 | // Create the function name & definition string. |
1436 | |
1437 | sstr.Printf("class %s:", auto_generated_class_name.c_str()); |
1438 | auto_generated_class.AppendString(sstr.GetString()); |
1439 | |
1440 | // Wrap everything up inside the class, increasing the indentation. we don't |
1441 | // need to play any fancy indentation tricks here because there is no |
1442 | // surrounding code whose indentation we need to honor |
1443 | for (int i = 0; i < num_lines; ++i) { |
1444 | sstr.Clear(); |
1445 | sstr.Printf(" %s", user_input.GetStringAtIndex(i)); |
1446 | auto_generated_class.AppendString(sstr.GetString()); |
1447 | } |
1448 | |
1449 | // Verify that the results are valid Python. (even though the method is |
1450 | // ExportFunctionDefinitionToInterpreter, a class will actually be exported) |
1451 | // (TODO: rename that method to ExportDefinitionToInterpreter) |
1452 | if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success()) |
1453 | return false; |
1454 | |
1455 | // Store the name of the auto-generated class |
1456 | |
1457 | output.assign(auto_generated_class_name); |
1458 | return true; |
1459 | } |
1460 | |
1461 | StructuredData::GenericSP |
1462 | ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) { |
1463 | if (class_name == nullptr || class_name[0] == '\0') |
1464 | return StructuredData::GenericSP(); |
1465 | |
1466 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1467 | PythonObject ret_val = LLDBSWIGPython_CreateFrameRecognizer( |
1468 | class_name, m_dictionary_name.c_str()); |
1469 | |
1470 | return StructuredData::GenericSP( |
1471 | new StructuredPythonObject(std::move(ret_val))); |
1472 | } |
1473 | |
1474 | lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( |
1475 | const StructuredData::ObjectSP &os_plugin_object_sp, |
1476 | lldb::StackFrameSP frame_sp) { |
1477 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1478 | |
1479 | if (!os_plugin_object_sp) |
1480 | return ValueObjectListSP(); |
1481 | |
1482 | StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); |
1483 | if (!generic) |
1484 | return nullptr; |
1485 | |
1486 | PythonObject implementor(PyRefType::Borrowed, |
1487 | (PyObject *)generic->GetValue()); |
1488 | |
1489 | if (!implementor.IsAllocated()) |
1490 | return ValueObjectListSP(); |
1491 | |
1492 | PythonObject py_return( |
1493 | PyRefType::Owned, |
1494 | LLDBSwigPython_GetRecognizedArguments(implementor.get(), frame_sp)); |
1495 | |
1496 | // if it fails, print the error but otherwise go on |
1497 | if (PyErr_Occurred()) { |
1498 | PyErr_Print(); |
1499 | PyErr_Clear(); |
1500 | } |
1501 | if (py_return.get()) { |
1502 | PythonList result_list(PyRefType::Borrowed, py_return.get()); |
1503 | ValueObjectListSP result = ValueObjectListSP(new ValueObjectList()); |
1504 | for (size_t i = 0; i < result_list.GetSize(); i++) { |
1505 | PyObject *item = result_list.GetItemAtIndex(i).get(); |
1506 | lldb::SBValue *sb_value_ptr = |
1507 | (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item); |
1508 | auto valobj_sp = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); |
1509 | if (valobj_sp) |
1510 | result->Append(valobj_sp); |
1511 | } |
1512 | return result; |
1513 | } |
1514 | return ValueObjectListSP(); |
1515 | } |
1516 | |
1517 | ScriptedProcessInterfaceUP |
1518 | ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() { |
1519 | return std::make_unique<ScriptedProcessPythonInterface>(*this); |
1520 | } |
1521 | |
1522 | StructuredData::GenericSP |
1523 | ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( |
1524 | const char *class_name, lldb::ProcessSP process_sp) { |
1525 | if (class_name == nullptr || class_name[0] == '\0') |
1526 | return StructuredData::GenericSP(); |
1527 | |
1528 | if (!process_sp) |
1529 | return StructuredData::GenericSP(); |
1530 | |
1531 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1532 | PythonObject ret_val = LLDBSWIGPythonCreateOSPlugin( |
1533 | class_name, m_dictionary_name.c_str(), process_sp); |
1534 | |
1535 | return StructuredData::GenericSP( |
1536 | new StructuredPythonObject(std::move(ret_val))); |
1537 | } |
1538 | |
1539 | StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( |
1540 | StructuredData::ObjectSP os_plugin_object_sp) { |
1541 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1542 | |
1543 | if (!os_plugin_object_sp) |
1544 | return {}; |
1545 | |
1546 | StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); |
1547 | if (!generic) |
1548 | return {}; |
1549 | |
1550 | PythonObject implementor(PyRefType::Borrowed, |
1551 | (PyObject *)generic->GetValue()); |
1552 | |
1553 | if (!implementor.IsAllocated()) |
1554 | return {}; |
1555 | |
1556 | llvm::Expected<PythonObject> expected_py_return = |
1557 | implementor.CallMethod("get_register_info"); |
1558 | |
1559 | if (!expected_py_return) { |
1560 | llvm::consumeError(expected_py_return.takeError()); |
1561 | return {}; |
1562 | } |
1563 | |
1564 | PythonObject py_return = std::move(expected_py_return.get()); |
1565 | |
1566 | if (py_return.get()) { |
1567 | PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); |
1568 | return result_dict.CreateStructuredDictionary(); |
1569 | } |
1570 | return StructuredData::DictionarySP(); |
1571 | } |
1572 | |
1573 | StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( |
1574 | StructuredData::ObjectSP os_plugin_object_sp) { |
1575 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1576 | if (!os_plugin_object_sp) |
1577 | return {}; |
1578 | |
1579 | StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); |
1580 | if (!generic) |
1581 | return {}; |
1582 | |
1583 | PythonObject implementor(PyRefType::Borrowed, |
1584 | (PyObject *)generic->GetValue()); |
1585 | |
1586 | if (!implementor.IsAllocated()) |
1587 | return {}; |
1588 | |
1589 | llvm::Expected<PythonObject> expected_py_return = |
1590 | implementor.CallMethod("get_thread_info"); |
1591 | |
1592 | if (!expected_py_return) { |
1593 | llvm::consumeError(expected_py_return.takeError()); |
1594 | return {}; |
1595 | } |
1596 | |
1597 | PythonObject py_return = std::move(expected_py_return.get()); |
1598 | |
1599 | if (py_return.get()) { |
1600 | PythonList result_list(PyRefType::Borrowed, py_return.get()); |
1601 | return result_list.CreateStructuredArray(); |
1602 | } |
1603 | return StructuredData::ArraySP(); |
1604 | } |
1605 | |
1606 | StructuredData::StringSP |
1607 | ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( |
1608 | StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { |
1609 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1610 | |
1611 | if (!os_plugin_object_sp) |
1612 | return {}; |
1613 | |
1614 | StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); |
1615 | if (!generic) |
1616 | return {}; |
1617 | PythonObject implementor(PyRefType::Borrowed, |
1618 | (PyObject *)generic->GetValue()); |
1619 | |
1620 | if (!implementor.IsAllocated()) |
1621 | return {}; |
1622 | |
1623 | llvm::Expected<PythonObject> expected_py_return = |
1624 | implementor.CallMethod("get_register_data", tid); |
1625 | |
1626 | if (!expected_py_return) { |
1627 | llvm::consumeError(expected_py_return.takeError()); |
1628 | return {}; |
1629 | } |
1630 | |
1631 | PythonObject py_return = std::move(expected_py_return.get()); |
1632 | |
1633 | if (py_return.get()) { |
1634 | PythonBytes result(PyRefType::Borrowed, py_return.get()); |
1635 | return result.CreateStructuredString(); |
1636 | } |
1637 | return {}; |
1638 | } |
1639 | |
1640 | StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( |
1641 | StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, |
1642 | lldb::addr_t context) { |
1643 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
1644 | |
1645 | if (!os_plugin_object_sp) |
1646 | return {}; |
1647 | |
1648 | StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); |
1649 | if (!generic) |
1650 | return {}; |
1651 | |
1652 | PythonObject implementor(PyRefType::Borrowed, |
1653 | (PyObject *)generic->GetValue()); |
1654 | |
1655 | if (!implementor.IsAllocated()) |
1656 | return {}; |
1657 | |
1658 | llvm::Expected<PythonObject> expected_py_return = |
1659 | implementor.CallMethod("create_thread", tid, context); |
1660 | |
1661 | if (!expected_py_return) { |
1662 | llvm::consumeError(expected_py_return.takeError()); |
1663 | return {}; |
1664 | } |
1665 | |
1666 | PythonObject py_return = std::move(expected_py_return.get()); |
1667 | |
1668 | if (py_return.get()) { |
1669 | PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); |
1670 | return result_dict.CreateStructuredDictionary(); |
1671 | } |
1672 | return StructuredData::DictionarySP(); |
1673 | } |
1674 | |
1675 | StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( |
1676 | const char *class_name, const StructuredDataImpl &args_data, |
1677 | std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) { |
1678 | if (class_name == nullptr || class_name[0] == '\0') |
1679 | return StructuredData::ObjectSP(); |
1680 | |
1681 | if (!thread_plan_sp.get()) |
1682 | return {}; |
1683 | |
1684 | Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); |
1685 | ScriptInterpreterPythonImpl *python_interpreter = |
1686 | GetPythonInterpreter(debugger); |
1687 | |
1688 | if (!python_interpreter) |
1689 | return {}; |
1690 | |
1691 | Locker py_lock(this, |
1692 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1693 | PythonObject ret_val = LLDBSwigPythonCreateScriptedThreadPlan( |
1694 | class_name, python_interpreter->m_dictionary_name.c_str(), args_data, |
1695 | error_str, thread_plan_sp); |
1696 | if (!ret_val) |
1697 | return {}; |
1698 | |
1699 | return StructuredData::ObjectSP( |
1700 | new StructuredPythonObject(std::move(ret_val))); |
1701 | } |
1702 | |
1703 | bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop( |
1704 | StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { |
1705 | bool explains_stop = true; |
1706 | StructuredData::Generic *generic = nullptr; |
1707 | if (implementor_sp) |
1708 | generic = implementor_sp->GetAsGeneric(); |
1709 | if (generic) { |
1710 | Locker py_lock(this, |
1711 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1712 | explains_stop = LLDBSWIGPythonCallThreadPlan( |
1713 | generic->GetValue(), "explains_stop", event, script_error); |
1714 | if (script_error) |
1715 | return true; |
1716 | } |
1717 | return explains_stop; |
1718 | } |
1719 | |
1720 | bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop( |
1721 | StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { |
1722 | bool should_stop = true; |
1723 | StructuredData::Generic *generic = nullptr; |
1724 | if (implementor_sp) |
1725 | generic = implementor_sp->GetAsGeneric(); |
1726 | if (generic) { |
1727 | Locker py_lock(this, |
1728 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1729 | should_stop = LLDBSWIGPythonCallThreadPlan( |
1730 | generic->GetValue(), "should_stop", event, script_error); |
1731 | if (script_error) |
1732 | return true; |
1733 | } |
1734 | return should_stop; |
1735 | } |
1736 | |
1737 | bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale( |
1738 | StructuredData::ObjectSP implementor_sp, bool &script_error) { |
1739 | bool is_stale = true; |
1740 | StructuredData::Generic *generic = nullptr; |
1741 | if (implementor_sp) |
1742 | generic = implementor_sp->GetAsGeneric(); |
1743 | if (generic) { |
1744 | Locker py_lock(this, |
1745 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1746 | is_stale = LLDBSWIGPythonCallThreadPlan(generic->GetValue(), "is_stale", |
1747 | (Event *) nullptr, script_error); |
1748 | if (script_error) |
1749 | return true; |
1750 | } |
1751 | return is_stale; |
1752 | } |
1753 | |
1754 | lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( |
1755 | StructuredData::ObjectSP implementor_sp, bool &script_error) { |
1756 | bool should_step = false; |
1757 | StructuredData::Generic *generic = nullptr; |
1758 | if (implementor_sp) |
1759 | generic = implementor_sp->GetAsGeneric(); |
1760 | if (generic) { |
1761 | Locker py_lock(this, |
1762 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1763 | should_step = LLDBSWIGPythonCallThreadPlan( |
1764 | generic->GetValue(), "should_step", (Event *) nullptr, script_error); |
1765 | if (script_error) |
1766 | should_step = true; |
1767 | } |
1768 | if (should_step) |
1769 | return lldb::eStateStepping; |
1770 | return lldb::eStateRunning; |
1771 | } |
1772 | |
1773 | bool |
1774 | ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription( |
1775 | StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, |
1776 | bool &script_error) { |
1777 | StructuredData::Generic *generic = nullptr; |
1778 | if (implementor_sp) |
1779 | generic = implementor_sp->GetAsGeneric(); |
1780 | if (!generic) { |
1781 | script_error = true; |
1782 | return false; |
1783 | } |
1784 | Locker py_lock(this, |
1785 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1786 | return LLDBSWIGPythonCallThreadPlan(generic->GetValue(), "stop_description", |
1787 | stream, script_error); |
1788 | } |
1789 | |
1790 | |
1791 | StructuredData::GenericSP |
1792 | ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( |
1793 | const char *class_name, const StructuredDataImpl &args_data, |
1794 | lldb::BreakpointSP &bkpt_sp) { |
1795 | |
1796 | if (class_name == nullptr || class_name[0] == '\0') |
1797 | return StructuredData::GenericSP(); |
1798 | |
1799 | if (!bkpt_sp.get()) |
1800 | return StructuredData::GenericSP(); |
1801 | |
1802 | Debugger &debugger = bkpt_sp->GetTarget().GetDebugger(); |
1803 | ScriptInterpreterPythonImpl *python_interpreter = |
1804 | GetPythonInterpreter(debugger); |
1805 | |
1806 | if (!python_interpreter) |
1807 | return StructuredData::GenericSP(); |
1808 | |
1809 | Locker py_lock(this, |
1810 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1811 | |
1812 | PythonObject ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( |
1813 | class_name, python_interpreter->m_dictionary_name.c_str(), args_data, |
1814 | bkpt_sp); |
1815 | |
1816 | return StructuredData::GenericSP( |
1817 | new StructuredPythonObject(std::move(ret_val))); |
1818 | } |
1819 | |
1820 | bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( |
1821 | StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) { |
1822 | bool should_continue = false; |
1823 | |
1824 | if (implementor_sp) { |
1825 | Locker py_lock(this, |
1826 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1827 | should_continue = LLDBSwigPythonCallBreakpointResolver( |
1828 | implementor_sp->GetValue(), "__callback__", sym_ctx); |
1829 | if (PyErr_Occurred()) { |
1830 | PyErr_Print(); |
1831 | PyErr_Clear(); |
1832 | } |
1833 | } |
1834 | return should_continue; |
1835 | } |
1836 | |
1837 | lldb::SearchDepth |
1838 | ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( |
1839 | StructuredData::GenericSP implementor_sp) { |
1840 | int depth_as_int = lldb::eSearchDepthModule; |
1841 | if (implementor_sp) { |
1842 | Locker py_lock(this, |
1843 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1844 | depth_as_int = LLDBSwigPythonCallBreakpointResolver( |
1845 | implementor_sp->GetValue(), "__get_depth__", nullptr); |
1846 | if (PyErr_Occurred()) { |
1847 | PyErr_Print(); |
1848 | PyErr_Clear(); |
1849 | } |
1850 | } |
1851 | if (depth_as_int == lldb::eSearchDepthInvalid) |
1852 | return lldb::eSearchDepthModule; |
1853 | |
1854 | if (depth_as_int <= lldb::kLastSearchDepthKind) |
1855 | return (lldb::SearchDepth)depth_as_int; |
1856 | return lldb::eSearchDepthModule; |
1857 | } |
1858 | |
1859 | StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( |
1860 | TargetSP target_sp, const char *class_name, |
1861 | const StructuredDataImpl &args_data, Status &error) { |
1862 | |
1863 | if (!target_sp) { |
1864 | error.SetErrorString("No target for scripted stop-hook."); |
1865 | return StructuredData::GenericSP(); |
1866 | } |
1867 | |
1868 | if (class_name == nullptr || class_name[0] == '\0') { |
1869 | error.SetErrorString("No class name for scripted stop-hook."); |
1870 | return StructuredData::GenericSP(); |
1871 | } |
1872 | |
1873 | ScriptInterpreterPythonImpl *python_interpreter = |
1874 | GetPythonInterpreter(m_debugger); |
1875 | |
1876 | if (!python_interpreter) { |
1877 | error.SetErrorString("No script interpreter for scripted stop-hook."); |
1878 | return StructuredData::GenericSP(); |
1879 | } |
1880 | |
1881 | Locker py_lock(this, |
1882 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1883 | |
1884 | PythonObject ret_val = LLDBSwigPythonCreateScriptedStopHook( |
1885 | target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), |
1886 | args_data, error); |
1887 | |
1888 | return StructuredData::GenericSP( |
1889 | new StructuredPythonObject(std::move(ret_val))); |
1890 | } |
1891 | |
1892 | bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( |
1893 | StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx, |
1894 | lldb::StreamSP stream_sp) { |
1895 | assert(implementor_sp &&(static_cast <bool> (implementor_sp && "can't call a stop hook with an invalid implementor" ) ? void (0) : __assert_fail ("implementor_sp && \"can't call a stop hook with an invalid implementor\"" , "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 1896, __extension__ __PRETTY_FUNCTION__)) |
1896 | "can't call a stop hook with an invalid implementor")(static_cast <bool> (implementor_sp && "can't call a stop hook with an invalid implementor" ) ? void (0) : __assert_fail ("implementor_sp && \"can't call a stop hook with an invalid implementor\"" , "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 1896, __extension__ __PRETTY_FUNCTION__)); |
1897 | assert(stream_sp && "can't call a stop hook with an invalid stream")(static_cast <bool> (stream_sp && "can't call a stop hook with an invalid stream" ) ? void (0) : __assert_fail ("stream_sp && \"can't call a stop hook with an invalid stream\"" , "lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp" , 1897, __extension__ __PRETTY_FUNCTION__)); |
1898 | |
1899 | Locker py_lock(this, |
1900 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1901 | |
1902 | lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx)); |
1903 | |
1904 | bool ret_val = LLDBSwigPythonStopHookCallHandleStop( |
1905 | implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp); |
1906 | return ret_val; |
1907 | } |
1908 | |
1909 | StructuredData::ObjectSP |
1910 | ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, |
1911 | lldb_private::Status &error) { |
1912 | if (!FileSystem::Instance().Exists(file_spec)) { |
1913 | error.SetErrorString("no such file"); |
1914 | return StructuredData::ObjectSP(); |
1915 | } |
1916 | |
1917 | StructuredData::ObjectSP module_sp; |
1918 | |
1919 | LoadScriptOptions load_script_options = |
1920 | LoadScriptOptions().SetInitSession(true).SetSilent(false); |
1921 | if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options, |
1922 | error, &module_sp)) |
1923 | return module_sp; |
1924 | |
1925 | return StructuredData::ObjectSP(); |
1926 | } |
1927 | |
1928 | StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings( |
1929 | StructuredData::ObjectSP plugin_module_sp, Target *target, |
1930 | const char *setting_name, lldb_private::Status &error) { |
1931 | if (!plugin_module_sp || !target || !setting_name || !setting_name[0]) |
1932 | return StructuredData::DictionarySP(); |
1933 | StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); |
1934 | if (!generic) |
1935 | return StructuredData::DictionarySP(); |
1936 | |
1937 | Locker py_lock(this, |
1938 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1939 | TargetSP target_sp(target->shared_from_this()); |
1940 | |
1941 | auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting( |
1942 | generic->GetValue(), setting_name, target_sp); |
1943 | |
1944 | if (!setting) |
1945 | return StructuredData::DictionarySP(); |
1946 | |
1947 | PythonDictionary py_dict = |
1948 | unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting))); |
1949 | |
1950 | if (!py_dict) |
1951 | return StructuredData::DictionarySP(); |
1952 | |
1953 | return py_dict.CreateStructuredDictionary(); |
1954 | } |
1955 | |
1956 | StructuredData::ObjectSP |
1957 | ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( |
1958 | const char *class_name, lldb::ValueObjectSP valobj) { |
1959 | if (class_name == nullptr || class_name[0] == '\0') |
1960 | return StructuredData::ObjectSP(); |
1961 | |
1962 | if (!valobj.get()) |
1963 | return StructuredData::ObjectSP(); |
1964 | |
1965 | ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); |
1966 | Target *target = exe_ctx.GetTargetPtr(); |
1967 | |
1968 | if (!target) |
1969 | return StructuredData::ObjectSP(); |
1970 | |
1971 | Debugger &debugger = target->GetDebugger(); |
1972 | ScriptInterpreterPythonImpl *python_interpreter = |
1973 | GetPythonInterpreter(debugger); |
1974 | |
1975 | if (!python_interpreter) |
1976 | return StructuredData::ObjectSP(); |
1977 | |
1978 | Locker py_lock(this, |
1979 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1980 | PythonObject ret_val = LLDBSwigPythonCreateSyntheticProvider( |
1981 | class_name, python_interpreter->m_dictionary_name.c_str(), valobj); |
1982 | |
1983 | return StructuredData::ObjectSP( |
1984 | new StructuredPythonObject(std::move(ret_val))); |
1985 | } |
1986 | |
1987 | StructuredData::GenericSP |
1988 | ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { |
1989 | DebuggerSP debugger_sp(m_debugger.shared_from_this()); |
1990 | |
1991 | if (class_name == nullptr || class_name[0] == '\0') |
1992 | return StructuredData::GenericSP(); |
1993 | |
1994 | if (!debugger_sp.get()) |
1995 | return StructuredData::GenericSP(); |
1996 | |
1997 | Locker py_lock(this, |
1998 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
1999 | PythonObject ret_val = LLDBSwigPythonCreateCommandObject( |
2000 | class_name, m_dictionary_name.c_str(), debugger_sp); |
2001 | |
2002 | if (ret_val.IsValid()) |
2003 | return StructuredData::GenericSP( |
2004 | new StructuredPythonObject(std::move(ret_val))); |
2005 | else |
2006 | return {}; |
2007 | } |
2008 | |
2009 | bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( |
2010 | const char *oneliner, std::string &output, const void *name_token) { |
2011 | StringList input; |
2012 | input.SplitIntoLines(oneliner, strlen(oneliner)); |
2013 | return GenerateTypeScriptFunction(input, output, name_token); |
2014 | } |
2015 | |
2016 | bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass( |
2017 | const char *oneliner, std::string &output, const void *name_token) { |
2018 | StringList input; |
2019 | input.SplitIntoLines(oneliner, strlen(oneliner)); |
2020 | return GenerateTypeSynthClass(input, output, name_token); |
2021 | } |
2022 | |
2023 | Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData( |
2024 | StringList &user_input, std::string &output, bool has_extra_args, |
2025 | bool is_callback) { |
2026 | static uint32_t num_created_functions = 0; |
2027 | user_input.RemoveBlankLines(); |
2028 | StreamString sstr; |
2029 | Status error; |
2030 | if (user_input.GetSize() == 0) { |
2031 | error.SetErrorString("No input data."); |
2032 | return error; |
2033 | } |
2034 | |
2035 | std::string auto_generated_function_name(GenerateUniqueName( |
2036 | "lldb_autogen_python_bp_callback_func_", num_created_functions)); |
2037 | if (has_extra_args) |
2038 | sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):", |
2039 | auto_generated_function_name.c_str()); |
2040 | else |
2041 | sstr.Printf("def %s (frame, bp_loc, internal_dict):", |
2042 | auto_generated_function_name.c_str()); |
2043 | |
2044 | error = GenerateFunction(sstr.GetData(), user_input, is_callback); |
2045 | if (!error.Success()) |
2046 | return error; |
2047 | |
2048 | // Store the name of the auto-generated function to be called. |
2049 | output.assign(auto_generated_function_name); |
2050 | return error; |
2051 | } |
2052 | |
2053 | bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData( |
2054 | StringList &user_input, std::string &output, bool is_callback) { |
2055 | static uint32_t num_created_functions = 0; |
2056 | user_input.RemoveBlankLines(); |
2057 | StreamString sstr; |
2058 | |
2059 | if (user_input.GetSize() == 0) |
2060 | return false; |
2061 | |
2062 | std::string auto_generated_function_name(GenerateUniqueName( |
2063 | "lldb_autogen_python_wp_callback_func_", num_created_functions)); |
2064 | sstr.Printf("def %s (frame, wp, internal_dict):", |
2065 | auto_generated_function_name.c_str()); |
2066 | |
2067 | if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success()) |
2068 | return false; |
2069 | |
2070 | // Store the name of the auto-generated function to be called. |
2071 | output.assign(auto_generated_function_name); |
2072 | return true; |
2073 | } |
2074 | |
2075 | bool ScriptInterpreterPythonImpl::GetScriptedSummary( |
2076 | const char *python_function_name, lldb::ValueObjectSP valobj, |
2077 | StructuredData::ObjectSP &callee_wrapper_sp, |
2078 | const TypeSummaryOptions &options, std::string &retval) { |
2079 | |
2080 | LLDB_SCOPED_TIMER()static ::lldb_private::Timer::Category _cat(__PRETTY_FUNCTION__ ); ::lldb_private::Timer _scoped_timer(_cat, "%s", __PRETTY_FUNCTION__ ); |
2081 | |
2082 | if (!valobj.get()) { |
2083 | retval.assign("<no object>"); |
2084 | return false; |
2085 | } |
2086 | |
2087 | void *old_callee = nullptr; |
2088 | StructuredData::Generic *generic = nullptr; |
2089 | if (callee_wrapper_sp) { |
2090 | generic = callee_wrapper_sp->GetAsGeneric(); |
2091 | if (generic) |
2092 | old_callee = generic->GetValue(); |
2093 | } |
2094 | void *new_callee = old_callee; |
2095 | |
2096 | bool ret_val; |
2097 | if (python_function_name && *python_function_name) { |
2098 | { |
2099 | Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | |
2100 | Locker::NoSTDIN); |
2101 | { |
2102 | TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); |
2103 | |
2104 | static Timer::Category func_cat("LLDBSwigPythonCallTypeScript"); |
2105 | Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript"); |
2106 | ret_val = LLDBSwigPythonCallTypeScript( |
2107 | python_function_name, GetSessionDictionary().get(), valobj, |
2108 | &new_callee, options_sp, retval); |
2109 | } |
2110 | } |
2111 | } else { |
2112 | retval.assign("<no function name>"); |
2113 | return false; |
2114 | } |
2115 | |
2116 | if (new_callee && old_callee != new_callee) { |
2117 | Locker py_lock(this, |
2118 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2119 | callee_wrapper_sp = std::make_shared<StructuredPythonObject>( |
2120 | PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee))); |
2121 | } |
2122 | |
2123 | return ret_val; |
2124 | } |
2125 | |
2126 | bool ScriptInterpreterPythonImpl::FormatterCallbackFunction( |
2127 | const char *python_function_name, TypeImplSP type_impl_sp) { |
2128 | Locker py_lock(this, |
2129 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2130 | return LLDBSwigPythonFormatterCallbackFunction( |
2131 | python_function_name, m_dictionary_name.c_str(), type_impl_sp); |
2132 | } |
2133 | |
2134 | bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( |
2135 | void *baton, StoppointCallbackContext *context, user_id_t break_id, |
2136 | user_id_t break_loc_id) { |
2137 | CommandDataPython *bp_option_data = (CommandDataPython *)baton; |
2138 | const char *python_function_name = bp_option_data->script_source.c_str(); |
2139 | |
2140 | if (!context) |
2141 | return true; |
2142 | |
2143 | ExecutionContext exe_ctx(context->exe_ctx_ref); |
2144 | Target *target = exe_ctx.GetTargetPtr(); |
2145 | |
2146 | if (!target) |
2147 | return true; |
2148 | |
2149 | Debugger &debugger = target->GetDebugger(); |
2150 | ScriptInterpreterPythonImpl *python_interpreter = |
2151 | GetPythonInterpreter(debugger); |
2152 | |
2153 | if (!python_interpreter) |
2154 | return true; |
2155 | |
2156 | if (python_function_name && python_function_name[0]) { |
2157 | const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP()); |
2158 | BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id); |
2159 | if (breakpoint_sp) { |
2160 | const BreakpointLocationSP bp_loc_sp( |
2161 | breakpoint_sp->FindLocationByID(break_loc_id)); |
2162 | |
2163 | if (stop_frame_sp && bp_loc_sp) { |
2164 | bool ret_val = true; |
2165 | { |
2166 | Locker py_lock(python_interpreter, Locker::AcquireLock | |
2167 | Locker::InitSession | |
2168 | Locker::NoSTDIN); |
2169 | Expected<bool> maybe_ret_val = |
2170 | LLDBSwigPythonBreakpointCallbackFunction( |
2171 | python_function_name, |
2172 | python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, |
2173 | bp_loc_sp, bp_option_data->m_extra_args); |
2174 | |
2175 | if (!maybe_ret_val) { |
2176 | |
2177 | llvm::handleAllErrors( |
2178 | maybe_ret_val.takeError(), |
2179 | [&](PythonException &E) { |
2180 | debugger.GetErrorStream() << E.ReadBacktrace(); |
2181 | }, |
2182 | [&](const llvm::ErrorInfoBase &E) { |
2183 | debugger.GetErrorStream() << E.message(); |
2184 | }); |
2185 | |
2186 | } else { |
2187 | ret_val = maybe_ret_val.get(); |
2188 | } |
2189 | } |
2190 | return ret_val; |
2191 | } |
2192 | } |
2193 | } |
2194 | // We currently always true so we stop in case anything goes wrong when |
2195 | // trying to call the script function |
2196 | return true; |
2197 | } |
2198 | |
2199 | bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction( |
2200 | void *baton, StoppointCallbackContext *context, user_id_t watch_id) { |
2201 | WatchpointOptions::CommandData *wp_option_data = |
2202 | (WatchpointOptions::CommandData *)baton; |
2203 | const char *python_function_name = wp_option_data->script_source.c_str(); |
2204 | |
2205 | if (!context) |
2206 | return true; |
2207 | |
2208 | ExecutionContext exe_ctx(context->exe_ctx_ref); |
2209 | Target *target = exe_ctx.GetTargetPtr(); |
2210 | |
2211 | if (!target) |
2212 | return true; |
2213 | |
2214 | Debugger &debugger = target->GetDebugger(); |
2215 | ScriptInterpreterPythonImpl *python_interpreter = |
2216 | GetPythonInterpreter(debugger); |
2217 | |
2218 | if (!python_interpreter) |
2219 | return true; |
2220 | |
2221 | if (python_function_name && python_function_name[0]) { |
2222 | const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP()); |
2223 | WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id); |
2224 | if (wp_sp) { |
2225 | if (stop_frame_sp && wp_sp) { |
2226 | bool ret_val = true; |
2227 | { |
2228 | Locker py_lock(python_interpreter, Locker::AcquireLock | |
2229 | Locker::InitSession | |
2230 | Locker::NoSTDIN); |
2231 | ret_val = LLDBSwigPythonWatchpointCallbackFunction( |
2232 | python_function_name, |
2233 | python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, |
2234 | wp_sp); |
2235 | } |
2236 | return ret_val; |
2237 | } |
2238 | } |
2239 | } |
2240 | // We currently always true so we stop in case anything goes wrong when |
2241 | // trying to call the script function |
2242 | return true; |
2243 | } |
2244 | |
2245 | size_t ScriptInterpreterPythonImpl::CalculateNumChildren( |
2246 | const StructuredData::ObjectSP &implementor_sp, uint32_t max) { |
2247 | if (!implementor_sp) |
2248 | return 0; |
2249 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2250 | if (!generic) |
2251 | return 0; |
2252 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2253 | if (!implementor) |
2254 | return 0; |
2255 | |
2256 | size_t ret_val = 0; |
2257 | |
2258 | { |
2259 | Locker py_lock(this, |
2260 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2261 | ret_val = LLDBSwigPython_CalculateNumChildren(implementor, max); |
2262 | } |
2263 | |
2264 | return ret_val; |
2265 | } |
2266 | |
2267 | lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex( |
2268 | const StructuredData::ObjectSP &implementor_sp, uint32_t idx) { |
2269 | if (!implementor_sp) |
2270 | return lldb::ValueObjectSP(); |
2271 | |
2272 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2273 | if (!generic) |
2274 | return lldb::ValueObjectSP(); |
2275 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2276 | if (!implementor) |
2277 | return lldb::ValueObjectSP(); |
2278 | |
2279 | lldb::ValueObjectSP ret_val; |
2280 | { |
2281 | Locker py_lock(this, |
2282 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2283 | PyObject *child_ptr = LLDBSwigPython_GetChildAtIndex(implementor, idx); |
2284 | if (child_ptr != nullptr && child_ptr != Py_None(&_Py_NoneStruct)) { |
2285 | lldb::SBValue *sb_value_ptr = |
2286 | (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); |
2287 | if (sb_value_ptr == nullptr) |
2288 | Py_XDECREF(child_ptr)_Py_XDECREF(((PyObject*)(child_ptr))); |
2289 | else |
2290 | ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); |
2291 | } else { |
2292 | Py_XDECREF(child_ptr)_Py_XDECREF(((PyObject*)(child_ptr))); |
2293 | } |
2294 | } |
2295 | |
2296 | return ret_val; |
2297 | } |
2298 | |
2299 | int ScriptInterpreterPythonImpl::GetIndexOfChildWithName( |
2300 | const StructuredData::ObjectSP &implementor_sp, const char *child_name) { |
2301 | if (!implementor_sp) |
2302 | return UINT32_MAX(4294967295U); |
2303 | |
2304 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2305 | if (!generic) |
2306 | return UINT32_MAX(4294967295U); |
2307 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2308 | if (!implementor) |
2309 | return UINT32_MAX(4294967295U); |
2310 | |
2311 | int ret_val = UINT32_MAX(4294967295U); |
2312 | |
2313 | { |
2314 | Locker py_lock(this, |
2315 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2316 | ret_val = LLDBSwigPython_GetIndexOfChildWithName(implementor, child_name); |
2317 | } |
2318 | |
2319 | return ret_val; |
2320 | } |
2321 | |
2322 | bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance( |
2323 | const StructuredData::ObjectSP &implementor_sp) { |
2324 | bool ret_val = false; |
2325 | |
2326 | if (!implementor_sp) |
2327 | return ret_val; |
2328 | |
2329 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2330 | if (!generic) |
2331 | return ret_val; |
2332 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2333 | if (!implementor) |
2334 | return ret_val; |
2335 | |
2336 | { |
2337 | Locker py_lock(this, |
2338 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2339 | ret_val = LLDBSwigPython_UpdateSynthProviderInstance(implementor); |
2340 | } |
2341 | |
2342 | return ret_val; |
2343 | } |
2344 | |
2345 | bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance( |
2346 | const StructuredData::ObjectSP &implementor_sp) { |
2347 | bool ret_val = false; |
2348 | |
2349 | if (!implementor_sp) |
2350 | return ret_val; |
2351 | |
2352 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2353 | if (!generic) |
2354 | return ret_val; |
2355 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2356 | if (!implementor) |
2357 | return ret_val; |
2358 | |
2359 | { |
2360 | Locker py_lock(this, |
2361 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2362 | ret_val = |
2363 | LLDBSwigPython_MightHaveChildrenSynthProviderInstance(implementor); |
2364 | } |
2365 | |
2366 | return ret_val; |
2367 | } |
2368 | |
2369 | lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue( |
2370 | const StructuredData::ObjectSP &implementor_sp) { |
2371 | lldb::ValueObjectSP ret_val(nullptr); |
2372 | |
2373 | if (!implementor_sp) |
2374 | return ret_val; |
2375 | |
2376 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2377 | if (!generic) |
2378 | return ret_val; |
2379 | auto *implementor = static_cast<PyObject *>(generic->GetValue()); |
2380 | if (!implementor) |
2381 | return ret_val; |
2382 | |
2383 | { |
2384 | Locker py_lock(this, |
2385 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2386 | PyObject *child_ptr = |
2387 | LLDBSwigPython_GetValueSynthProviderInstance(implementor); |
2388 | if (child_ptr != nullptr && child_ptr != Py_None(&_Py_NoneStruct)) { |
2389 | lldb::SBValue *sb_value_ptr = |
2390 | (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); |
2391 | if (sb_value_ptr == nullptr) |
2392 | Py_XDECREF(child_ptr)_Py_XDECREF(((PyObject*)(child_ptr))); |
2393 | else |
2394 | ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); |
2395 | } else { |
2396 | Py_XDECREF(child_ptr)_Py_XDECREF(((PyObject*)(child_ptr))); |
2397 | } |
2398 | } |
2399 | |
2400 | return ret_val; |
2401 | } |
2402 | |
2403 | ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( |
2404 | const StructuredData::ObjectSP &implementor_sp) { |
2405 | Locker py_lock(this, |
2406 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2407 | |
2408 | if (!implementor_sp) |
2409 | return {}; |
2410 | |
2411 | StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); |
2412 | if (!generic) |
2413 | return {}; |
2414 | |
2415 | PythonObject implementor(PyRefType::Borrowed, |
2416 | (PyObject *)generic->GetValue()); |
2417 | if (!implementor.IsAllocated()) |
2418 | return {}; |
2419 | |
2420 | llvm::Expected<PythonObject> expected_py_return = |
2421 | implementor.CallMethod("get_type_name"); |
2422 | |
2423 | if (!expected_py_return) { |
2424 | llvm::consumeError(expected_py_return.takeError()); |
2425 | return {}; |
2426 | } |
2427 | |
2428 | PythonObject py_return = std::move(expected_py_return.get()); |
2429 | |
2430 | ConstString ret_val; |
2431 | bool got_string = false; |
2432 | std::string buffer; |
2433 | |
2434 | if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { |
2435 | PythonString py_string(PyRefType::Borrowed, py_return.get()); |
2436 | llvm::StringRef return_data(py_string.GetString()); |
2437 | if (!return_data.empty()) { |
2438 | buffer.assign(return_data.data(), return_data.size()); |
2439 | got_string = true; |
2440 | } |
2441 | } |
2442 | |
2443 | if (got_string) |
2444 | ret_val.SetCStringWithLength(buffer.c_str(), buffer.size()); |
2445 | |
2446 | return ret_val; |
2447 | } |
2448 | |
2449 | bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( |
2450 | const char *impl_function, Process *process, std::string &output, |
2451 | Status &error) { |
2452 | bool ret_val; |
2453 | if (!process) { |
2454 | error.SetErrorString("no process"); |
2455 | return false; |
2456 | } |
2457 | if (!impl_function || !impl_function[0]) { |
2458 | error.SetErrorString("no function to execute"); |
2459 | return false; |
2460 | } |
2461 | |
2462 | { |
2463 | Locker py_lock(this, |
2464 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2465 | ret_val = LLDBSWIGPythonRunScriptKeywordProcess( |
2466 | impl_function, m_dictionary_name.c_str(), process->shared_from_this(), |
2467 | output); |
2468 | if (!ret_val) |
2469 | error.SetErrorString("python script evaluation failed"); |
2470 | } |
2471 | return ret_val; |
2472 | } |
2473 | |
2474 | bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( |
2475 | const char *impl_function, Thread *thread, std::string &output, |
2476 | Status &error) { |
2477 | if (!thread) { |
2478 | error.SetErrorString("no thread"); |
2479 | return false; |
2480 | } |
2481 | if (!impl_function || !impl_function[0]) { |
2482 | error.SetErrorString("no function to execute"); |
2483 | return false; |
2484 | } |
2485 | |
2486 | Locker py_lock(this, |
2487 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2488 | if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( |
2489 | impl_function, m_dictionary_name.c_str(), |
2490 | thread->shared_from_this())) { |
2491 | output = std::move(*result); |
2492 | return true; |
2493 | } |
2494 | error.SetErrorString("python script evaluation failed"); |
2495 | return false; |
2496 | } |
2497 | |
2498 | bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( |
2499 | const char *impl_function, Target *target, std::string &output, |
2500 | Status &error) { |
2501 | bool ret_val; |
2502 | if (!target) { |
2503 | error.SetErrorString("no thread"); |
2504 | return false; |
2505 | } |
2506 | if (!impl_function || !impl_function[0]) { |
2507 | error.SetErrorString("no function to execute"); |
2508 | return false; |
2509 | } |
2510 | |
2511 | { |
2512 | TargetSP target_sp(target->shared_from_this()); |
2513 | Locker py_lock(this, |
2514 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2515 | ret_val = LLDBSWIGPythonRunScriptKeywordTarget( |
2516 | impl_function, m_dictionary_name.c_str(), target_sp, output); |
2517 | if (!ret_val) |
2518 | error.SetErrorString("python script evaluation failed"); |
2519 | } |
2520 | return ret_val; |
2521 | } |
2522 | |
2523 | bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( |
2524 | const char *impl_function, StackFrame *frame, std::string &output, |
2525 | Status &error) { |
2526 | if (!frame) { |
2527 | error.SetErrorString("no frame"); |
2528 | return false; |
2529 | } |
2530 | if (!impl_function || !impl_function[0]) { |
2531 | error.SetErrorString("no function to execute"); |
2532 | return false; |
2533 | } |
2534 | |
2535 | Locker py_lock(this, |
2536 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2537 | if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( |
2538 | impl_function, m_dictionary_name.c_str(), |
2539 | frame->shared_from_this())) { |
2540 | output = std::move(*result); |
2541 | return true; |
2542 | } |
2543 | error.SetErrorString("python script evaluation failed"); |
2544 | return false; |
2545 | } |
2546 | |
2547 | bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( |
2548 | const char *impl_function, ValueObject *value, std::string &output, |
2549 | Status &error) { |
2550 | bool ret_val; |
2551 | if (!value) { |
2552 | error.SetErrorString("no value"); |
2553 | return false; |
2554 | } |
2555 | if (!impl_function || !impl_function[0]) { |
2556 | error.SetErrorString("no function to execute"); |
2557 | return false; |
2558 | } |
2559 | |
2560 | { |
2561 | Locker py_lock(this, |
2562 | Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); |
2563 | ret_val = LLDBSWIGPythonRunScriptKeywordValue( |
2564 | impl_function, m_dictionary_name.c_str(), value->GetSP(), output); |
2565 | if (!ret_val) |
2566 | error.SetErrorString("python script evaluation failed"); |
2567 | } |
2568 | return ret_val; |
2569 | } |
2570 | |
2571 | uint64_t replace_all(std::string &str, const std::string &oldStr, |
2572 | const std::string &newStr) { |
2573 | size_t pos = 0; |
2574 | uint64_t matches = 0; |
2575 | while ((pos = str.find(oldStr, pos)) != std::string::npos) { |
2576 | matches++; |
2577 | str.replace(pos, oldStr.length(), newStr); |
2578 | pos += newStr.length(); |
2579 | } |
2580 | return matches; |
2581 | } |
2582 | |
2583 | bool ScriptInterpreterPythonImpl::LoadScriptingModule( |
2584 | const char *pathname, const LoadScriptOptions &options, |
2585 | lldb_private::Status &error, StructuredData::ObjectSP *module_sp, |
2586 | FileSpec extra_search_dir) { |
2587 | namespace fs = llvm::sys::fs; |
2588 | namespace path = llvm::sys::path; |
2589 | |
2590 | ExecuteScriptOptions exc_options = ExecuteScriptOptions() |
2591 | .SetEnableIO(!options.GetSilent()) |
2592 | .SetSetLLDBGlobals(false); |
2593 | |
2594 | if (!pathname || !pathname[0]) { |
2595 | error.SetErrorString("empty path"); |
2596 | return false; |
2597 | } |
2598 | |
2599 | llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> |
2600 | io_redirect_or_error = ScriptInterpreterIORedirect::Create( |
2601 | exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr); |
2602 | |
2603 | if (!io_redirect_or_error) { |
2604 | error = io_redirect_or_error.takeError(); |
2605 | return false; |
2606 | } |
2607 | |
2608 | ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; |
2609 | |
2610 | // Before executing Python code, lock the GIL. |
2611 | Locker py_lock(this, |
2612 | Locker::AcquireLock | |
2613 | (options.GetInitSession() ? Locker::InitSession : 0) | |
2614 | Locker::NoSTDIN, |
2615 | Locker::FreeAcquiredLock | |
2616 | (options.GetInitSession() ? Locker::TearDownSession : 0), |
2617 | io_redirect.GetInputFile(), io_redirect.GetOutputFile(), |
2618 | io_redirect.GetErrorFile()); |
2619 | |
2620 | auto ExtendSysPath = [&](std::string directory) -> llvm::Error { |
2621 | if (directory.empty()) { |
2622 | return llvm::make_error<llvm::StringError>( |
2623 | "invalid directory name", llvm::inconvertibleErrorCode()); |
2624 | } |
2625 | |
2626 | replace_all(directory, "\\", "\\\\"); |
2627 | replace_all(directory, "'", "\\'"); |
2628 | |
2629 | // Make sure that Python has "directory" in the search path. |
2630 | StreamString command_stream; |
2631 | command_stream.Printf("if not (sys.path.__contains__('%s')):\n " |
2632 | "sys.path.insert(1,'%s');\n\n", |
2633 | directory.c_str(), directory.c_str()); |
2634 | bool syspath_retval = |
2635 | ExecuteMultipleLines(command_stream.GetData(), exc_options).Success(); |
2636 | if (!syspath_retval) { |
2637 | return llvm::make_error<llvm::StringError>( |
2638 | "Python sys.path handling failed", llvm::inconvertibleErrorCode()); |
2639 | } |
2640 | |
2641 | return llvm::Error::success(); |
2642 | }; |
2643 | |
2644 | std::string module_name(pathname); |
2645 | bool possible_package = false; |
2646 | |
2647 | if (extra_search_dir) { |
2648 | if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) { |
2649 | error = std::move(e); |
2650 | return false; |
2651 | } |
2652 | } else { |
2653 | FileSpec module_file(pathname); |
2654 | FileSystem::Instance().Resolve(module_file); |
2655 | |
2656 | fs::file_status st; |
2657 | std::error_code ec = status(module_file.GetPath(), st); |
2658 | |
2659 | if (ec || st.type() == fs::file_type::status_error || |
2660 | st.type() == fs::file_type::type_unknown || |
2661 | st.type() == fs::file_type::file_not_found) { |
2662 | // if not a valid file of any sort, check if it might be a filename still |
2663 | // dot can't be used but / and \ can, and if either is found, reject |
2664 | if (strchr(pathname, '\\') || strchr(pathname, '/')) { |
2665 | error.SetErrorStringWithFormatv("invalid pathname '{0}'", pathname); |
2666 | return false; |
2667 | } |
2668 | // Not a filename, probably a package of some sort, let it go through. |
2669 | possible_package = true; |
2670 | } else if (is_directory(st) || is_regular_file(st)) { |
2671 | if (module_file.GetDirectory().IsEmpty()) { |
2672 | error.SetErrorStringWithFormatv("invalid directory name '{0}'", pathname); |
2673 | return false; |
2674 | } |
2675 | if (llvm::Error e = |
2676 | ExtendSysPath(module_file.GetDirectory().GetCString())) { |
2677 | error = std::move(e); |
2678 | return false; |
2679 | } |
2680 | module_name = module_file.GetFilename().GetCString(); |
2681 | } else { |
2682 | error.SetErrorString("no known way to import this module specification"); |
2683 | return false; |
2684 | } |
2685 | } |
2686 | |
2687 | // Strip .py or .pyc extension |
2688 | llvm::StringRef extension = llvm::sys::path::extension(module_name); |
2689 | if (!extension.empty()) { |
2690 | if (extension == ".py") |
2691 | module_name.resize(module_name.length() - 3); |
2692 | else if (extension == ".pyc") |
2693 | module_name.resize(module_name.length() - 4); |
2694 | } |
2695 | |
2696 | if (!possible_package && module_name.find('.') != llvm::StringRef::npos) { |
2697 | error.SetErrorStringWithFormat( |
2698 | "Python does not allow dots in module names: %s", module_name.c_str()); |
2699 | return false; |
2700 | } |
2701 | |
2702 | if (module_name.find('-') != llvm::StringRef::npos) { |
2703 | error.SetErrorStringWithFormat( |
2704 | "Python discourages dashes in module names: %s", module_name.c_str()); |
2705 | return false; |
2706 | } |
2707 | |
2708 | // Check if the module is already imported. |
2709 | StreamString command_stream; |
2710 | command_stream.Clear(); |
2711 | command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str()); |
2712 | bool does_contain = false; |
2713 | // This call will succeed if the module was ever imported in any Debugger in |
2714 | // the lifetime of the process in which this LLDB framework is living. |
2715 | const bool does_contain_executed = ExecuteOneLineWithReturn( |
2716 | command_stream.GetData(), |
2717 | ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options); |
2718 | |
2719 | const bool was_imported_globally = does_contain_executed && does_contain; |
2720 | const bool was_imported_locally = |
2721 | GetSessionDictionary() |
2722 | .GetItemForKey(PythonString(module_name)) |
2723 | .IsAllocated(); |
2724 | |
2725 | // now actually do the import |
2726 | command_stream.Clear(); |
2727 | |
2728 | if (was_imported_globally || was_imported_locally) { |
2729 | if (!was_imported_locally) |
2730 | command_stream.Printf("import %s ; reload_module(%s)", |
2731 | module_name.c_str(), module_name.c_str()); |
2732 | else |
2733 | command_stream.Printf("reload_module(%s)", module_name.c_str()); |
2734 | } else |
2735 | command_stream.Printf("import %s", module_name.c_str()); |
2736 | |
2737 | error = ExecuteMultipleLines(command_stream.GetData(), exc_options); |
2738 | if (error.Fail()) |
2739 | return false; |
2740 | |
2741 | // if we are here, everything worked |
2742 | // call __lldb_init_module(debugger,dict) |
2743 | if (!LLDBSwigPythonCallModuleInit(module_name.c_str(), |
2744 | m_dictionary_name.c_str(), |
2745 | m_debugger.shared_from_this())) { |
2746 | error.SetErrorString("calling __lldb_init_module failed"); |
2747 | return false; |
2748 | } |
2749 | |
2750 | if (module_sp) { |
2751 | // everything went just great, now set the module object |
2752 | command_stream.Clear(); |
2753 | command_stream.Printf("%s", module_name.c_str()); |
2754 | void *module_pyobj = nullptr; |
2755 | if (ExecuteOneLineWithReturn( |
2756 | command_stream.GetData(), |
2757 | ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj, |
2758 | exc_options) && |
2759 | module_pyobj) |
2760 | *module_sp = std::make_shared<StructuredPythonObject>(PythonObject( |
2761 | PyRefType::Owned, static_cast<PyObject *>(module_pyobj))); |
2762 | } |
2763 | |
2764 | return true; |
2765 | } |
2766 | |
2767 | bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) { |
2768 | if (!word || !word[0]) |
2769 | return false; |
2770 | |
2771 | llvm::StringRef word_sr(word); |
2772 | |
2773 | // filter out a few characters that would just confuse us and that are |
2774 | // clearly not keyword material anyway |
2775 | if (word_sr.find('"') != llvm::StringRef::npos || |
2776 | word_sr.find('\'') != llvm::StringRef::npos) |
2777 | return false; |
2778 | |
2779 | StreamString command_stream; |
2780 | command_stream.Printf("keyword.iskeyword('%s')", word); |
2781 | bool result; |
2782 | ExecuteScriptOptions options; |
2783 | options.SetEnableIO(false); |
2784 | options.SetMaskoutErrors(true); |
2785 | options.SetSetLLDBGlobals(false); |
2786 | if (ExecuteOneLineWithReturn(command_stream.GetData(), |
2787 | ScriptInterpreter::eScriptReturnTypeBool, |
2788 | &result, options)) |
2789 | return result; |
2790 | return false; |
2791 | } |
2792 | |
2793 | ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler( |
2794 | lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro) |
2795 | : m_debugger_sp(debugger_sp), m_synch_wanted(synchro), |
2796 | m_old_asynch(debugger_sp->GetAsyncExecution()) { |
2797 | if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous) |
2798 | m_debugger_sp->SetAsyncExecution(false); |
2799 | else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous) |
2800 | m_debugger_sp->SetAsyncExecution(true); |
2801 | } |
2802 | |
2803 | ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() { |
2804 | if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) |
2805 | m_debugger_sp->SetAsyncExecution(m_old_asynch); |
2806 | } |
2807 | |
2808 | bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( |
2809 | const char *impl_function, llvm::StringRef args, |
2810 | ScriptedCommandSynchronicity synchronicity, |
2811 | lldb_private::CommandReturnObject &cmd_retobj, Status &error, |
2812 | const lldb_private::ExecutionContext &exe_ctx) { |
2813 | if (!impl_function) { |
2814 | error.SetErrorString("no function to execute"); |
2815 | return false; |
2816 | } |
2817 | |
2818 | lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); |
2819 | lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); |
2820 | |
2821 | if (!debugger_sp.get()) { |
2822 | error.SetErrorString("invalid Debugger pointer"); |
2823 | return false; |
2824 | } |
2825 | |
2826 | bool ret_val = false; |
2827 | |
2828 | std::string err_msg; |
2829 | |
2830 | { |
2831 | Locker py_lock(this, |
2832 | Locker::AcquireLock | Locker::InitSession | |
2833 | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), |
2834 | Locker::FreeLock | Locker::TearDownSession); |
2835 | |
2836 | SynchronicityHandler synch_handler(debugger_sp, synchronicity); |
2837 | |
2838 | std::string args_str = args.str(); |
2839 | ret_val = LLDBSwigPythonCallCommand( |
2840 | impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(), |
2841 | cmd_retobj, exe_ctx_ref_sp); |
2842 | } |
2843 | |
2844 | if (!ret_val) |
2845 | error.SetErrorString("unable to execute script function"); |
2846 | else if (cmd_retobj.GetStatus() == eReturnStatusFailed) |
2847 | return false; |
2848 | |
2849 | error.Clear(); |
2850 | return ret_val; |
2851 | } |
2852 | |
2853 | bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( |
2854 | StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, |
2855 | ScriptedCommandSynchronicity synchronicity, |
2856 | lldb_private::CommandReturnObject &cmd_retobj, Status &error, |
2857 | const lldb_private::ExecutionContext &exe_ctx) { |
2858 | if (!impl_obj_sp || !impl_obj_sp->IsValid()) { |
2859 | error.SetErrorString("no function to execute"); |
2860 | return false; |
2861 | } |
2862 | |
2863 | lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); |
2864 | lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); |
2865 | |
2866 | if (!debugger_sp.get()) { |
2867 | error.SetErrorString("invalid Debugger pointer"); |
2868 | return false; |
2869 | } |
2870 | |
2871 | bool ret_val = false; |
2872 | |
2873 | std::string err_msg; |
2874 | |
2875 | { |
2876 | Locker py_lock(this, |
2877 | Locker::AcquireLock | Locker::InitSession | |
2878 | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), |
2879 | Locker::FreeLock | Locker::TearDownSession); |
2880 | |
2881 | SynchronicityHandler synch_handler(debugger_sp, synchronicity); |
2882 | |
2883 | std::string args_str = args.str(); |
2884 | ret_val = LLDBSwigPythonCallCommandObject( |
2885 | static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp, |
2886 | args_str.c_str(), cmd_retobj, exe_ctx_ref_sp); |
2887 | } |
2888 | |
2889 | if (!ret_val) |
2890 | error.SetErrorString("unable to execute script function"); |
2891 | else if (cmd_retobj.GetStatus() == eReturnStatusFailed) |
2892 | return false; |
2893 | |
2894 | error.Clear(); |
2895 | return ret_val; |
2896 | } |
2897 | |
2898 | /// In Python, a special attribute __doc__ contains the docstring for an object |
2899 | /// (function, method, class, ...) if any is defined Otherwise, the attribute's |
2900 | /// value is None. |
2901 | bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item, |
2902 | std::string &dest) { |
2903 | dest.clear(); |
2904 | |
2905 | if (!item || !*item) |
2906 | return false; |
2907 | |
2908 | std::string command(item); |
2909 | command += ".__doc__"; |
2910 | |
2911 | // Python is going to point this to valid data if ExecuteOneLineWithReturn |
2912 | // returns successfully. |
2913 | char *result_ptr = nullptr; |
2914 | |
2915 | if (ExecuteOneLineWithReturn( |
2916 | command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone, |
2917 | &result_ptr, |
2918 | ExecuteScriptOptions().SetEnableIO(false))) { |
2919 | if (result_ptr) |
2920 | dest.assign(result_ptr); |
2921 | return true; |
2922 | } |
2923 | |
2924 | StreamString str_stream; |
2925 | str_stream << "Function " << item |
2926 | << " was not found. Containing module might be missing."; |
2927 | dest = std::string(str_stream.GetString()); |
2928 | |
2929 | return false; |
2930 | } |
2931 | |
2932 | bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( |
2933 | StructuredData::GenericSP cmd_obj_sp, std::string &dest) { |
2934 | dest.clear(); |
2935 | |
2936 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
2937 | |
2938 | if (!cmd_obj_sp) |
2939 | return false; |
2940 | |
2941 | PythonObject implementor(PyRefType::Borrowed, |
2942 | (PyObject *)cmd_obj_sp->GetValue()); |
2943 | |
2944 | if (!implementor.IsAllocated()) |
2945 | return false; |
2946 | |
2947 | llvm::Expected<PythonObject> expected_py_return = |
2948 | implementor.CallMethod("get_short_help"); |
2949 | |
2950 | if (!expected_py_return) { |
2951 | llvm::consumeError(expected_py_return.takeError()); |
2952 | return false; |
2953 | } |
2954 | |
2955 | PythonObject py_return = std::move(expected_py_return.get()); |
2956 | |
2957 | if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { |
2958 | PythonString py_string(PyRefType::Borrowed, py_return.get()); |
2959 | llvm::StringRef return_data(py_string.GetString()); |
2960 | dest.assign(return_data.data(), return_data.size()); |
2961 | return true; |
2962 | } |
2963 | |
2964 | return false; |
2965 | } |
2966 | |
2967 | uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject( |
2968 | StructuredData::GenericSP cmd_obj_sp) { |
2969 | uint32_t result = 0; |
2970 | |
2971 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
2972 | |
2973 | static char callee_name[] = "get_flags"; |
2974 | |
2975 | if (!cmd_obj_sp) |
2976 | return result; |
2977 | |
2978 | PythonObject implementor(PyRefType::Borrowed, |
2979 | (PyObject *)cmd_obj_sp->GetValue()); |
2980 | |
2981 | if (!implementor.IsAllocated()) |
2982 | return result; |
2983 | |
2984 | PythonObject pmeth(PyRefType::Owned, |
2985 | PyObject_GetAttrString(implementor.get(), callee_name)); |
2986 | |
2987 | if (PyErr_Occurred()) |
2988 | PyErr_Clear(); |
2989 | |
2990 | if (!pmeth.IsAllocated()) |
2991 | return result; |
2992 | |
2993 | if (PyCallable_Check(pmeth.get()) == 0) { |
2994 | if (PyErr_Occurred()) |
2995 | PyErr_Clear(); |
2996 | return result; |
2997 | } |
2998 | |
2999 | if (PyErr_Occurred()) |
3000 | PyErr_Clear(); |
3001 | |
3002 | long long py_return = unwrapOrSetPythonException( |
3003 | As<long long>(implementor.CallMethod(callee_name))); |
3004 | |
3005 | // if it fails, print the error but otherwise go on |
3006 | if (PyErr_Occurred()) { |
3007 | PyErr_Print(); |
3008 | PyErr_Clear(); |
3009 | } else { |
3010 | result = py_return; |
3011 | } |
3012 | |
3013 | return result; |
3014 | } |
3015 | |
3016 | bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( |
3017 | StructuredData::GenericSP cmd_obj_sp, std::string &dest) { |
3018 | dest.clear(); |
3019 | |
3020 | Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); |
3021 | |
3022 | if (!cmd_obj_sp) |
3023 | return false; |
3024 | |
3025 | PythonObject implementor(PyRefType::Borrowed, |
3026 | (PyObject *)cmd_obj_sp->GetValue()); |
3027 | |
3028 | if (!implementor.IsAllocated()) |
3029 | return false; |
3030 | |
3031 | llvm::Expected<PythonObject> expected_py_return = |
3032 | implementor.CallMethod("get_long_help"); |
3033 | |
3034 | if (!expected_py_return) { |
3035 | llvm::consumeError(expected_py_return.takeError()); |
3036 | return false; |
3037 | } |
3038 | |
3039 | PythonObject py_return = std::move(expected_py_return.get()); |
3040 | |
3041 | bool got_string = false; |
3042 | if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { |
3043 | PythonString str(PyRefType::Borrowed, py_return.get()); |
3044 | llvm::StringRef str_data(str.GetString()); |
3045 | dest.assign(str_data.data(), str_data.size()); |
3046 | got_string = true; |
3047 | } |
3048 | |
3049 | return got_string; |
3050 | } |
3051 | |
3052 | std::unique_ptr<ScriptInterpreterLocker> |
3053 | ScriptInterpreterPythonImpl::AcquireInterpreterLock() { |
3054 | std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker( |
3055 | this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, |
3056 | Locker::FreeLock | Locker::TearDownSession)); |
3057 | return py_lock; |
3058 | } |
3059 | |
3060 | void ScriptInterpreterPythonImpl::Initialize() { |
3061 | LLDB_SCOPED_TIMER()static ::lldb_private::Timer::Category _cat(__PRETTY_FUNCTION__ ); ::lldb_private::Timer _scoped_timer(_cat, "%s", __PRETTY_FUNCTION__ ); |
3062 | |
3063 | // RAII-based initialization which correctly handles multiple-initialization, |
3064 | // version- specific differences among Python 2 and Python 3, and saving and |
3065 | // restoring various other pieces of state that can get mucked with during |
3066 | // initialization. |
3067 | InitializePythonRAII initialize_guard; |
3068 | |
3069 | LLDBSwigPyInitPyInit__lldb(); |
3070 | |
3071 | // Update the path python uses to search for modules to include the current |
3072 | // directory. |
3073 | |
3074 | PyRun_SimpleString("import sys")PyRun_SimpleStringFlags("import sys", __null); |
3075 | AddToSysPath(AddLocation::End, "."); |
3076 | |
3077 | // Don't denormalize paths when calling file_spec.GetPath(). On platforms |
3078 | // that use a backslash as the path separator, this will result in executing |
3079 | // python code containing paths with unescaped backslashes. But Python also |
3080 | // accepts forward slashes, so to make life easier we just use that. |
3081 | if (FileSpec file_spec = GetPythonDir()) |
3082 | AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); |
3083 | if (FileSpec file_spec = HostInfo::GetShlibDir()) |
3084 | AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); |
3085 | |
3086 | PyRun_SimpleString("sys.dont_write_bytecode = 1; import "PyRun_SimpleStringFlags("sys.dont_write_bytecode = 1; import " "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line", __null ) |
3087 | "lldb.embedded_interpreter; from "PyRun_SimpleStringFlags("sys.dont_write_bytecode = 1; import " "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line", __null ) |
3088 | "lldb.embedded_interpreter import run_python_interpreter; "PyRun_SimpleStringFlags("sys.dont_write_bytecode = 1; import " "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line", __null ) |
3089 | "from lldb.embedded_interpreter import run_one_line")PyRun_SimpleStringFlags("sys.dont_write_bytecode = 1; import " "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line", __null ); |
3090 | |
3091 | #if LLDB_USE_PYTHON_SET_INTERRUPT(3 == 3 && 9 >= 2) || (3 > 3) |
3092 | // Python will not just overwrite its internal SIGINT handler but also the |
3093 | // one from the process. Backup the current SIGINT handler to prevent that |
3094 | // Python deletes it. |
3095 | RestoreSignalHandlerScope save_sigint(SIGINT2); |
3096 | |
3097 | // Setup a default SIGINT signal handler that works the same way as the |
3098 | // normal Python REPL signal handler which raises a KeyboardInterrupt. |
3099 | // Also make sure to not pollute the user's REPL with the signal module nor |
3100 | // our utility function. |
3101 | PyRun_SimpleString("def lldb_setup_sigint_handler():\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3102 | " import signal;\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3103 | " def signal_handler(sig, frame):\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3104 | " raise KeyboardInterrupt()\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3105 | " signal.signal(signal.SIGINT, signal_handler);\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3106 | "lldb_setup_sigint_handler();\n"PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null) |
3107 | "del lldb_setup_sigint_handler\n")PyRun_SimpleStringFlags("def lldb_setup_sigint_handler():\n" " import signal;\n" " def signal_handler(sig, frame):\n" " raise KeyboardInterrupt()\n" " signal.signal(signal.SIGINT, signal_handler);\n" "lldb_setup_sigint_handler();\n" "del lldb_setup_sigint_handler\n", __null); |
3108 | #endif |
3109 | } |
3110 | |
3111 | void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location, |
3112 | std::string path) { |
3113 | std::string path_copy; |
3114 | |
3115 | std::string statement; |
3116 | if (location == AddLocation::Beginning) { |
3117 | statement.assign("sys.path.insert(0,\""); |
3118 | statement.append(path); |
3119 | statement.append("\")"); |
3120 | } else { |
3121 | statement.assign("sys.path.append(\""); |
3122 | statement.append(path); |
3123 | statement.append("\")"); |
3124 | } |
3125 | PyRun_SimpleString(statement.c_str())PyRun_SimpleStringFlags(statement.c_str(), __null); |
3126 | } |
3127 | |
3128 | // We are intentionally NOT calling Py_Finalize here (this would be the logical |
3129 | // place to call it). Calling Py_Finalize here causes test suite runs to seg |
3130 | // fault: The test suite runs in Python. It registers SBDebugger::Terminate to |
3131 | // be called 'at_exit'. When the test suite Python harness finishes up, it |
3132 | // calls Py_Finalize, which calls all the 'at_exit' registered functions. |
3133 | // SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate, |
3134 | // which calls ScriptInterpreter::Terminate, which calls |
3135 | // ScriptInterpreterPythonImpl::Terminate. So if we call Py_Finalize here, we |
3136 | // end up with Py_Finalize being called from within Py_Finalize, which results |
3137 | // in a seg fault. Since this function only gets called when lldb is shutting |
3138 | // down and going away anyway, the fact that we don't actually call Py_Finalize |
3139 | // should not cause any problems (everything should shut down/go away anyway |
3140 | // when the process exits). |
3141 | // |
3142 | // void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); } |
3143 | |
3144 | #endif |