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