LLDB mainline
ScriptInterpreterPython.cpp
Go to the documentation of this file.
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-python.h"
10
12#include "PythonDataObjects.h"
13#include "PythonReadline.h"
14#include "SWIGPythonBridge.h"
16
17#include "lldb/API/SBError.h"
19#include "lldb/API/SBFrame.h"
20#include "lldb/API/SBValue.h"
23#include "lldb/Core/Debugger.h"
27#include "lldb/Host/Config.h"
30#include "lldb/Host/HostInfo.h"
31#include "lldb/Host/Pipe.h"
35#include "lldb/Target/Thread.h"
40#include "lldb/Utility/Timer.h"
43#include "lldb/lldb-forward.h"
44#include "llvm/ADT/STLExtras.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/ADT/StringRef.h"
47#include "llvm/Support/Error.h"
48#include "llvm/Support/ErrorExtras.h"
49#include "llvm/Support/FileSystem.h"
50#include "llvm/Support/FormatAdapters.h"
51
52#if defined(_WIN32)
54#endif
55
56#include <cstdio>
57#include <cstdlib>
58#include <memory>
59#include <optional>
60#include <stdlib.h>
61#include <string>
62
63using namespace lldb;
64using namespace lldb_private;
65using namespace lldb_private::python;
66using llvm::Expected;
67
69
70// Defined in the SWIG source file
71extern "C" PyObject *PyInit__lldb(void);
72
73#define LLDBSwigPyInit PyInit__lldb
74
75#if defined(_WIN32)
76// Don't mess with the signal handlers on Windows.
77#define LLDB_USE_PYTHON_SET_INTERRUPT 0
78#else
79#define LLDB_USE_PYTHON_SET_INTERRUPT 1
80#endif
81
83 ScriptInterpreter *script_interpreter =
85 return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
86}
87
88namespace {
89
90// Initializing Python is not a straightforward process. We cannot control
91// what external code may have done before getting to this point in LLDB,
92// including potentially having already initialized Python, so we need to do a
93// lot of work to ensure that the existing state of the system is maintained
94// across our initialization. We do this by using an RAII pattern where we
95// save off initial state at the beginning, and restore it at the end
96struct InitializePythonRAII {
97public:
98 llvm::Error DoInitialize() {
99 const bool was_initialized = Py_IsInitialized();
100
101 // The table of built-in modules can only be extended before Python is
102 // initialized.
103 if (!was_initialized) {
104#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
105 // Python's readline is incompatible with libedit being linked into lldb.
106 // Provide a patched version local to the embedded interpreter.
107 PyImport_AppendInittab("readline", initlldb_readline);
108#endif
109
110 // Register _lldb as a built-in module.
111 PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
112 }
113
114#if LLDB_EMBED_PYTHON_HOME
115 if (!was_initialized) {
116 PyConfig config;
117 PyConfig_InitPythonConfig(&config);
118
119 static std::string g_python_home = []() -> std::string {
120 if (llvm::sys::path::is_absolute(LLDB_PYTHON_HOME))
121 return LLDB_PYTHON_HOME;
122
123 FileSpec spec = HostInfo::GetShlibDir();
124 if (!spec)
125 return {};
126 spec.AppendPathComponent(LLDB_PYTHON_HOME);
127 return spec.GetPath();
128 }();
129 if (!g_python_home.empty()) {
130 PyStatus status = PyConfig_SetBytesString(&config, &config.home,
131 g_python_home.c_str());
132 if (PyStatus_Exception(status)) {
133 PyConfig_Clear(&config);
134 return llvm::createStringError(
135 "failed to set the Python config: '%s'", status.err_msg);
136 }
137 }
138
139 config.install_signal_handlers = 0;
140 PyStatus status = Py_InitializeFromConfig(&config);
141 PyConfig_Clear(&config);
142 if (PyStatus_Exception(status))
143 return llvm::createStringError("Python failed to initialize: '%s'",
144 status.err_msg);
145 }
146#else
147 if (!was_initialized)
148 Py_InitializeEx(/*install_sigs=*/0);
149 if (!Py_IsInitialized())
150 return llvm::createStringError("Python failed to initialize");
151#endif
152
153 m_python_initialized = true;
154
155 // The only case we should go further and acquire the GIL: it is unlocked.
156 PyGILState_STATE gil_state = PyGILState_Ensure();
157 if (gil_state != PyGILState_UNLOCKED)
158 return llvm::Error::success();
159
160 m_was_already_initialized = true;
161 m_gil_state = gil_state;
163 GetLog(LLDBLog::Script), "Ensured PyGILState. Previous state = {0}",
164 m_gil_state == PyGILState_UNLOCKED ? "unlocked" : "locked");
165 return llvm::Error::success();
166 }
167
168 ~InitializePythonRAII() {
169 if (!m_python_initialized)
170 return;
171
172 if (m_was_already_initialized) {
173 LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
174 "Releasing PyGILState. Returning to state = {0}",
175 m_gil_state == PyGILState_UNLOCKED ? "unlocked"
176 : "locked");
177 PyGILState_Release(m_gil_state);
178 } else {
179 // We initialized the threads in this function, just unlock the GIL.
180 PyEval_SaveThread();
181 }
182 }
183
184private:
185 PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
186 bool m_was_already_initialized = false;
187 bool m_python_initialized = false;
188};
189
190#if LLDB_USE_PYTHON_SET_INTERRUPT
191/// Saves the current signal handler for the specified signal and restores
192/// it at the end of the current scope.
193struct RestoreSignalHandlerScope {
194 /// The signal handler.
195 struct sigaction m_prev_handler;
196 int m_signal_code;
197 RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) {
198 // Initialize sigaction to their default state.
199 std::memset(&m_prev_handler, 0, sizeof(m_prev_handler));
200 // Don't install a new handler, just read back the old one.
201 struct sigaction *new_handler = nullptr;
202 int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler);
203 lldbassert(signal_err == 0 && "sigaction failed to read handler");
204 }
205 ~RestoreSignalHandlerScope() {
206 int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr);
207 lldbassert(signal_err == 0 && "sigaction failed to restore old handler");
208 }
209};
210#endif
211} // namespace
212
215 auto style = llvm::sys::path::Style::posix;
216
217 llvm::StringRef path_ref(path.begin(), path.size());
218 auto rbegin = llvm::sys::path::rbegin(path_ref, style);
219 auto rend = llvm::sys::path::rend(path_ref);
220 auto framework = std::find(rbegin, rend, "LLDB.framework");
221 if (framework == rend) {
222 ComputePythonDir(path);
223 return;
224 }
225 path.resize(framework - rend);
226 llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
227}
228
231 // Build the path by backing out of the lib dir, then building with whatever
232 // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL
233 // x86_64, or bin on Windows).
234 llvm::sys::path::remove_filename(path);
235 llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);
236
237#if defined(_WIN32)
238 // This will be injected directly through FileSpec.SetDirectory(),
239 // so we need to normalize manually.
240 std::replace(path.begin(), path.end(), '\\', '/');
241#endif
242}
243
245 static FileSpec g_spec = []() {
246 FileSpec spec = HostInfo::GetShlibDir();
247 if (!spec)
248 return FileSpec();
249 llvm::SmallString<64> path;
250 spec.GetPath(path);
251
252#if defined(__APPLE__)
254#else
255 ComputePythonDir(path);
256#endif
257 spec.SetDirectory(path);
258 return spec;
259 }();
260 return g_spec;
261}
262
263static const char GetInterpreterInfoScript[] = R"(
264import os
265import sys
266
267def main(lldb_python_dir, python_exe_relative_path):
268 info = {
269 "lldb-pythonpath": lldb_python_dir,
270 "language": "python",
271 "prefix": sys.prefix,
272 "executable": os.path.join(sys.prefix, python_exe_relative_path)
273 }
274 return info
275)";
276
277static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;
278
280 GIL gil;
281 FileSpec python_dir_spec = GetPythonDir();
282 if (!python_dir_spec)
283 return nullptr;
285 auto info_json = unwrapIgnoringErrors(
286 As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),
288 if (!info_json)
289 return nullptr;
290 return info_json.CreateStructuredDictionary();
291}
292
294 lldb::ScriptedExtension extension) {
295 switch (extension) {
297 return "lldb.plugins.operating_system";
299 return "lldb.plugins.scripted_platform";
301 return "lldb.plugins.scripted_process";
303 return "lldb.plugins.scripted_hook";
305 return "lldb.plugins.scripted_breakpoint";
307 return "lldb.plugins.scripted_thread_plan";
309 return "lldb.plugins.scripted_frame_provider";
312 return "lldb.plugins.scripted_process";
314 return "lldb.plugins.scripted_stackframe_recognizer";
317 return "lldb.plugins.scripted_command";
319 return "lldb.plugins.scripted_string_summary";
321 return "lldb.plugins.scripted_synthetic_children";
323 return llvm::createStringError("invalid extension name");
324 }
325 return llvm::createStringError("invalid extension name");
326}
327
328llvm::Expected<StructuredData::ObjectSP>
330 const llvm::SmallVector<llvm::StringRef> &extension_path) {
331 lldb::ScriptedExtension extension =
332 ScriptInterpreter::StringToExtension(extension_path.back());
333 auto import_path_or_err = ExtensionToImportPath(extension);
334 if (!import_path_or_err)
335 return import_path_or_err.takeError();
336
337 StreamString command_stream;
338 // __import__(path, fromlist=['']) imports the submodule and returns it
339 // directly (rather than the top-level package), as a single expression --
340 // this keeps the whole call eval-able in one line while guaranteeing the
341 // module is imported first; referencing "<import_path>.<ClassName>"
342 // directly would only work if something else had already imported
343 // <import_path> as a side effect.
344 command_stream.Printf("lldb.embedded_interpreter.generate_extension_schema("
345 "__import__('%s', fromlist=['']).%s)",
346 import_path_or_err->c_str(),
347 ScriptInterpreter::ExtensionToString(extension).data());
348
349 // Use eScriptReturnTypeOpaqueObject: it transfers a real owned reference
350 // we can safely extract the string from. eScriptReturnTypeCharStrOrNone
351 // instead hands back a pointer to a temporary Python object's buffer
352 // that gets destroyed (and, for a freshly created string like this one,
353 // deallocated) as soon as ExecuteOneLineWithReturn returns -- reading
354 // it afterwards is a use-after-free.
355 void *result_obj = nullptr;
357 command_stream.GetData(),
359 ExecuteScriptOptions().SetEnableIO(false)))
360 return llvm::createStringError("invalid extension schema format");
361
362 // ExecuteOneLineWithReturn releases the GIL before returning, so touching
363 // the returned object (Str() below can execute arbitrary Python code) must
364 // re-acquire it first. py_result is scoped so its destructor (a DECREF)
365 // also runs before the GIL is released below, not after.
366 std::string schema_str;
367 {
368 PyGILState_STATE gil_state = PyGILState_Ensure();
369 {
371 static_cast<PyObject *>(result_obj));
372 if (py_result.IsAllocated() && py_result.get() != Py_None)
373 schema_str = py_result.Str().GetString().str();
374 }
375 PyGILState_Release(gil_state);
376 }
377
378 if (schema_str.empty())
379 return llvm::createStringError("empty extension schema");
380 return StructuredData::ParseJSON(schema_str);
381}
382
384 Stream &s, llvm::StringRef output_script_prefix,
385 const llvm::SmallVector<llvm::StringRef> &extension_path,
386 bool generate_non_abstract_methods, std::set<std::string> &typing_imports) {
387 auto schema_or_err = GetExtensionSchema(extension_path);
388 if (!schema_or_err)
389 return schema_or_err.takeError();
390
391 StructuredData::ObjectSP schema = *schema_or_err;
392 if (!schema)
393 return llvm::createStringError("empty extension schema");
394 StructuredData::Dictionary *dict = schema->GetAsDictionary();
395 if (!dict)
396 return llvm::createStringError("extension schema is not a JSON object");
397
398 // Merge each class' typing imports into the caller-owned set so the
399 // final `from typing import ...` line covers every class we emit.
400 StructuredData::Array *schema_typing;
401 if (dict->GetValueForKeyAsArray("typing_imports", schema_typing))
402 schema_typing->ForEach([&](StructuredData::Object *entry) {
403 if (auto *str = entry->GetAsString())
404 typing_imports.insert(str->GetValue().str());
405 return true;
406 });
407
408 llvm::StringRef base_class, import_path;
409 if (!dict->GetValueForKeyAsString("class", base_class))
410 return llvm::createStringError(
411 llvm::formatv("extension schema dictionary is missing 'class' key")
412 .str());
413 if (!dict->GetValueForKeyAsString("module", import_path))
414 return llvm::createStringError(
415 llvm::formatv("extension schema dictionary is missing 'module' key")
416 .str());
417
418 // imports
419 s.Printf("from %s import %s\n", import_path.data(), base_class.data());
420 s.EOL();
421
422 // class definition
423 s.Printf("class %s%s(%s):\n", output_script_prefix.data(), base_class.data(),
424 base_class.data());
425 s.IndentMore();
426
427 // Class docstring: list the non-callable members the base class exposes
428 // so the user sees what's available without having to hop back to the
429 // base class definition.
430 bool has_body = false;
431 StructuredData::Array *attributes;
432 if (dict->GetValueForKeyAsArray("attributes", attributes) &&
433 attributes->GetSize()) {
434 s.Indent();
435 s.PutCString("\"\"\"\n");
436 s.Indent();
437 s.Printf("Attributes inherited from %s:\n", base_class.data());
438 for (size_t i = 0; i < attributes->GetSize(); i++) {
439 auto maybe_dict = attributes->GetItemAtIndexAsDictionary(i);
440 if (!maybe_dict)
441 continue;
442 StructuredData::Dictionary *attr_dict = *maybe_dict;
443 llvm::StringRef attr_name;
444 if (!attr_dict->GetValueForKeyAsString("name", attr_name))
445 continue;
446 llvm::StringRef attr_type;
447 bool has_type = attr_dict->GetValueForKeyAsString("type", attr_type);
448 s.Indent();
449 s.Printf("- %s", attr_name.data());
450 if (has_type)
451 s.Printf(": %s", attr_type.data());
452 s.EOL();
453 }
454 s.Indent();
455 s.PutCString("\"\"\"\n\n");
456 has_body = true;
457 }
458
459 // members
460 StructuredData::Array *members;
461 if (!dict->GetValueForKeyAsArray("members", members))
462 return llvm::createStringError("missing 'members' key in extension schema");
463
464 // If the base class doesn't mark anything `@abstractmethod`, the filter
465 // "only stub abstract methods" would leave the derived class empty --
466 // which isn't a useful starting point. Fall back to emitting every
467 // method in that case so the user has actual code to edit.
468 bool any_abstract = false;
469 for (size_t i = 0; i < members->GetSize(); i++) {
470 auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
471 if (!maybe_dict)
472 continue;
473 bool is_abstract = false;
474 if ((*maybe_dict)->GetValueForKeyAsBoolean("is_abstract", is_abstract) &&
475 is_abstract) {
476 any_abstract = true;
477 break;
478 }
479 }
480 bool emit_all_methods = generate_non_abstract_methods || !any_abstract;
481
482 for (size_t i = 0; i < members->GetSize(); i++) {
483 auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
484 if (!maybe_dict)
485 return llvm::createStringError(
486 llvm::formatv(
487 "member at index {0} in extension schema isn't a dictionary")
488 .str());
489
490 StructuredData::Dictionary *member_dict = *maybe_dict;
491 llvm::StringRef symbol, args;
492 if (!member_dict->GetValueForKeyAsString("name", symbol))
493 return llvm::createStringError(
494 llvm::formatv(
495 "member at index {0} in extension schema is missing 'name' key")
496 .str());
497 if (!member_dict->GetValueForKeyAsString("signature", args))
498 return llvm::createStringError(
499 llvm::formatv("member at index {0} in extension schema is missing "
500 "'signature' key")
501 .str());
502
503 bool is_abstract = false;
504 bool has_is_abstract =
505 member_dict->GetValueForKeyAsBoolean("is_abstract", is_abstract);
506 if (!emit_all_methods)
507 if (!has_is_abstract || !is_abstract)
508 continue;
509
510 s.Indent();
511 s.Printf("def %s%s:\n", symbol.data(), args.data());
512
513 s.IndentMore();
514 llvm::StringRef documentation;
515 if (member_dict->GetValueForKeyAsString("doc", documentation)) {
516 s.Indent();
517 s.PutCString("\"\"\"\n");
518
519 llvm::SmallVector<llvm::StringRef> lines;
520 documentation.split(lines, "\n");
521
522 for (llvm::StringRef line : lines) {
523 s.Indent();
524 s.PutCString(line);
525 s.EOL();
526 }
527
528 s.Indent();
529 s.PutCString("\"\"\"");
530 s.EOL();
531 }
532
533 if (symbol == "__init__") {
534 // The base class' constructor sets up attributes (e.g. self.target,
535 // self.process) that the inherited, non-overridden methods rely on.
536 // Forward the same arguments so that state is still initialized.
537 // Splitting the param list on `,` requires bracket-depth awareness
538 // because annotations like `Union[X, Y]` also contain commas.
539 llvm::StringRef params = args.trim("()");
540 std::vector<std::string> forwarded_args;
541 int depth = 0;
542 size_t start = 0;
543 auto flush = [&](size_t end) {
544 llvm::StringRef param = params.slice(start, end);
545 param = param.split(':').first.split('=').first.trim();
546 if (!param.empty() && param != "self")
547 forwarded_args.push_back(param.str());
548 };
549 for (size_t i = 0; i < params.size(); ++i) {
550 char c = params[i];
551 if (c == '[' || c == '(' || c == '{')
552 ++depth;
553 else if (c == ']' || c == ')' || c == '}')
554 --depth;
555 else if (c == ',' && depth == 0) {
556 flush(i);
557 start = i + 1;
558 }
559 }
560 flush(params.size());
561 s.Indent();
562 s.Printf("super().__init__(%s)\n",
563 llvm::join(forwarded_args, ", ").c_str());
564 }
565
566 s.Indent();
567 s.PutCString("# TODO: Implement\n");
568 s.Indent();
569 s.PutCString("pass\n\n");
570 s.IndentLess();
571 has_body = true;
572 }
573
574 // A class with no body is a Python syntax error, so emit `pass` when the
575 // base class has nothing to stub out (no methods and no attributes to
576 // document).
577 if (!has_body) {
578 s.Indent();
579 s.PutCString("pass\n");
580 }
581
582 return llvm::Error::success();
583}
584
586 const std::string &name, std::vector<ExtensionTemplateRequest> &extensions,
587 bool generate_non_abstract_methods, std::string output_file) {
588 // `ParseExtensionSchema` accumulates every `typing` generic it sees
589 // (`Optional`, `Union`, `List`, ...) into this set so we can emit a
590 // targeted `from typing import ...` line only for what's actually
591 // referenced. The Python schema does the detection so we don't have
592 // to re-scan strings here.
593 std::set<std::string> typing_imports;
594 StreamString bodies;
595 for (const ExtensionTemplateRequest &extension : extensions) {
596 if (llvm::Error err =
597 ParseExtensionSchema(bodies, name, extension.path,
598 generate_non_abstract_methods, typing_imports))
599 return std::move(err);
600 bodies.PutCString("\n\n");
601 }
602
603 StreamString generated_file_stream;
604 generated_file_stream.PutCString("import lldb\n");
605 if (!typing_imports.empty()) {
606 std::vector<std::string> sorted_imports(typing_imports.begin(),
607 typing_imports.end());
608 generated_file_stream.Format("from typing import {0}\n",
609 llvm::join(sorted_imports, ", "));
610 }
611 generated_file_stream.PutCString("\n");
612 generated_file_stream.PutCString(bodies.GetString());
613
614 FileSpec save_location;
615 if (output_file.empty()) {
616 // Sanitize the caller-supplied class prefix so it can't escape the
617 // temp directory (`../`, path separators, ...). Only keep ASCII
618 // alphanumerics; everything else collapses to `_`, and an all-junk
619 // name falls back to a fixed default.
620 std::string sanitized;
621 sanitized.reserve(name.size());
622 for (char c : name)
623 sanitized.push_back(llvm::isAlnum(c) ? static_cast<char>(llvm::toLower(c))
624 : '_');
625 if (sanitized.find_first_not_of('_') == std::string::npos)
626 sanitized = "extension";
627 const std::string file_name = "lldb_" + sanitized + "_extension.py";
628 save_location = HostInfo::GetGlobalTempDir();
629 FileSystem::Instance().Resolve(save_location);
630 save_location.AppendPathComponent(file_name);
631 } else {
632 save_location = FileSpec(output_file);
633 FileSystem::Instance().Resolve(save_location);
634 }
635
639
640 auto opened_file = FileSystem::Instance().Open(save_location, flags);
641
642 if (!opened_file)
643 return opened_file.takeError();
644
645 FileUP file = std::move(opened_file.get());
646
647 size_t byte_size = generated_file_stream.GetSize();
648
649 Status error = file->Write(generated_file_stream.GetData(), byte_size);
650
651 if (error.Fail() || byte_size != generated_file_stream.GetSize())
652 return llvm::createStringError("Unable to write to destination file. Bytes "
653 "written do not match generated file size.");
654 return save_location;
655}
656
658 FileSpec &this_file) {
659 // When we're loaded from python, this_file will point to the file inside the
660 // python package directory. Replace it with the one in the lib directory.
661#ifdef _WIN32
662 // On windows, we need to manually back out of the python tree, and go into
663 // the bin directory. This is pretty much the inverse of what ComputePythonDir
664 // does.
665 if (this_file.GetFileNameExtension() == ".pyd") {
666 this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd
667 this_file.RemoveLastPathComponent(); // native
668 this_file.RemoveLastPathComponent(); // lldb
669 llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;
670 for (auto it = llvm::sys::path::begin(libdir),
671 end = llvm::sys::path::end(libdir);
672 it != end; ++it)
673 this_file.RemoveLastPathComponent();
674 this_file.AppendPathComponent("bin");
675 this_file.AppendPathComponent("liblldb.dll");
676 }
677#else
678 // The python file is a symlink, so we can find the real library by resolving
679 // it. We can do this unconditionally.
680 FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);
681#endif
682}
683
685 return "Embedded Python interpreter";
686}
687
689#if LLDB_ENABLE_MTE
690 // Python's allocator (pymalloc) is not aware of Memory Tagging Extension
691 // (MTE) and crashes.
692 // https://bugs.python.org/issue43593
693 setenv("PYTHONMALLOC", "malloc", /*overwrite=*/true);
694#endif
695
696 // When the plugin is a separate shared library, the SWIG wrapper lives in
697 // the plugin library, so the path helper that redirects lookups back to
698 // liblldb is unnecessary.
699#if !LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS
700 HostInfo::SetSharedLibraryDirectoryHelper(
702#endif
703
704 // Bring the interpreter up before registering, so a Python that refuses to
705 // initialize leaves no plugin claiming eScriptLanguagePython behind.
706 // GetScriptInterpreterForLanguage then hands out ScriptInterpreterNone and
707 // the rest of lldb keeps working without scripting.
709 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
710 return;
711 }
712
718}
719
724
726 ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
727 uint16_t on_leave, FileSP in, FileSP out, FileSP err)
730 m_python_interpreter(py_interpreter) {
732 if ((on_entry & InitSession) == InitSession) {
733 if (!DoInitSession(on_entry, in, out, err)) {
734 // Don't teardown the session if we didn't init it.
735 m_teardown_session = false;
736 }
737 }
738}
739
741 m_GILState = PyGILState_Ensure();
743 "Ensured PyGILState. Previous state = {0}",
744 m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
745
746 // we need to save the thread state when we first start the command because
747 // we might decide to interrupt it while some action is taking place outside
748 // of Python (e.g. printing to screen, waiting for the network, ...) in that
749 // case, _PyThreadState_Current will be NULL - and we would be unable to set
750 // the asynchronous exception - not a desirable situation
751 m_python_interpreter->SetThreadState(PyThreadState_Get());
752 m_python_interpreter->IncrementLockCount();
753 return true;
754}
755
757 FileSP in, FileSP out,
758 FileSP err) {
760 return false;
761 return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
762}
763
766 "Releasing PyGILState. Returning to state = {0}",
767 m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
768 PyGILState_Release(m_GILState);
769 m_python_interpreter->DecrementLockCount();
770 return true;
771}
772
775 return false;
776 m_python_interpreter->LeaveSession();
777 return true;
778}
779
785
792 m_dictionary_name(m_debugger.GetInstanceName()),
795 m_command_thread_state(nullptr) {
796
797 m_dictionary_name.append("_dict");
798 StreamString run_string;
799 run_string.Printf("%s = dict()", m_dictionary_name.c_str());
800
802 RunSimpleString(run_string.GetData());
803
804 run_string.Clear();
805 run_string.Printf("run_one_line (%s, 'import copy, keyword, os, re, sys, "
806 "uuid, lldb, importlib')",
807 m_dictionary_name.c_str());
808 RunSimpleString(run_string.GetData());
809
810 // WARNING: temporary code that loads Cocoa formatters - this should be done
811 // on a per-platform basis rather than loading the whole set and letting the
812 // individual formatter classes exploit APIs to check whether they can/cannot
813 // do their task
814 run_string.Clear();
815 run_string.Printf(
816 "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",
817 m_dictionary_name.c_str());
818 RunSimpleString(run_string.GetData());
819 run_string.Clear();
820
821 run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "
822 "lldb.embedded_interpreter import run_python_interpreter; "
823 "from lldb.embedded_interpreter import run_one_line')",
824 m_dictionary_name.c_str());
825 RunSimpleString(run_string.GetData());
826 run_string.Clear();
827
828 // Configure pydoc (built-in module) to use the "plain" pager. The default one
829 // doesn't play nice with the statusline.
830 run_string.Printf("run_one_line (%s, 'import pydoc; pydoc.pager = "
831 "pydoc.plainpager')",
832 m_dictionary_name.c_str());
833 RunSimpleString(run_string.GetData());
834 run_string.Clear();
835
836 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64
837 "')",
838 m_dictionary_name.c_str(), m_debugger.GetID());
839 RunSimpleString(run_string.GetData());
840}
841
842/// A Python sys.stdout/stderr file backed by a pipe whose read end is drained
843/// by a reader thread that writes to the debugger's terminal under the output
844/// lock (Debugger::PrintAsync). Handing Python the raw terminal descriptor
845/// instead lets a script's print() race the statusline, which redraws on the
846/// event thread under that lock. Its cursor save/restore then rewinds over and
847/// eats the script's output.
849public:
850 static std::unique_ptr<SessionIORedirect> Create(lldb::user_id_t debugger_id,
851 bool is_stdout) {
852 Pipe pipe;
853 if (pipe.CreateNew().Fail())
854 return nullptr;
855
856 std::unique_ptr<SessionIORedirect> redirect(
857 new SessionIORedirect(debugger_id, is_stdout));
858
859#if defined(_WIN32)
860 lldb::file_t read_handle = pipe.GetReadNativeHandle();
862 std::unique_ptr<Connection> conn =
863 std::make_unique<ConnectionGenericFile>(read_handle, true);
864#else
865 std::unique_ptr<Connection> conn =
866 std::make_unique<ConnectionFileDescriptor>(
867 pipe.ReleaseReadFileDescriptor(), /*owns_fd=*/true);
868#endif
869 if (!conn->IsConnected())
870 return nullptr;
871
872 redirect->m_communication.SetConnection(std::move(conn));
873 redirect->m_communication.SetReadThreadBytesReceivedCallback(
874 ReadThreadBytesReceived, redirect.get());
875 if (!redirect->m_communication.StartReadThread())
876 return nullptr;
877 redirect->m_connected = true;
878
879 // The write end is owned here. Python only borrows its descriptor.
880 redirect->m_write_file_sp = std::make_shared<NativeFile>(
883 return redirect;
884 }
885
887 if (!m_connected)
888 return;
889 // Close the write end so the reader sees EOF and exits, then join it.
890 if (m_write_file_sp)
891 m_write_file_sp->Close();
892 m_communication.JoinReadThread();
893 m_communication.Disconnect();
894 }
895
896 int GetWriteDescriptor() const {
897 return m_write_file_sp ? m_write_file_sp->GetDescriptor()
899 }
900
901private:
902 SessionIORedirect(lldb::user_id_t debugger_id, bool is_stdout)
903 : m_debugger_id(debugger_id), m_is_stdout(is_stdout),
904 m_communication("lldb.ScriptInterpreterPython.io-redirect") {}
905
906 static void ReadThreadBytesReceived(void *baton, const void *src,
907 size_t src_len) {
908 if (!src || !src_len)
909 return;
910 auto *self = static_cast<SessionIORedirect *>(baton);
911 if (lldb::DebuggerSP debugger_sp =
912 Debugger::FindDebuggerWithID(self->m_debugger_id))
913 debugger_sp->PrintAsync(static_cast<const char *>(src), src_len,
914 self->m_is_stdout);
915 }
916
921 bool m_connected = false;
922};
923
925 // the session dictionary may hold objects with complex state which means
926 // that they may need to be torn down with some level of smarts and that, in
927 // turn, requires a valid thread state force Python to procure itself such a
928 // thread state, nuke the session dictionary and then release it for others
929 // to use and proceed with the rest of the shutdown
930 auto gil_state = PyGILState_Ensure();
931 m_session_dict.Reset();
932 PyGILState_Release(gil_state);
933}
934
936 bool interactive) {
937 const char *instructions = nullptr;
938
939 switch (m_active_io_handler) {
940 case eIOHandlerNone:
941 break;
943 instructions = R"(Enter your Python command(s). Type 'DONE' to end.
944def function (frame, bp_loc, internal_dict):
945 """frame: the lldb.SBFrame for the location at which you stopped
946 bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
947 internal_dict: an LLDB support object not to be used"""
948)";
949 break;
951 instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
952 break;
953 }
954
955 if (instructions && interactive) {
956 if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {
957 LockedStreamFile locked_stream = stream_sp->Lock();
958 locked_stream.PutCString(instructions);
959 locked_stream.Flush();
960 }
961 }
962}
963
965 std::string &data) {
966 io_handler.SetIsDone(true);
967 bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();
968
969 switch (m_active_io_handler) {
970 case eIOHandlerNone:
971 break;
973 std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
974 (std::vector<std::reference_wrapper<BreakpointOptions>> *)
975 io_handler.GetUserData();
976 for (BreakpointOptions &bp_options : *bp_options_vec) {
977
978 auto data_up = std::make_unique<CommandDataPython>();
979 if (!data_up)
980 break;
981 data_up->user_source.SplitIntoLines(data);
982
983 if (GenerateBreakpointCommandCallbackData(data_up->user_source,
984 data_up->script_source,
985 /*has_extra_args=*/false,
986 /*is_callback=*/false)
987 .Success()) {
988 auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
989 std::move(data_up));
990 bp_options.SetCallback(
992 } else if (!batch_mode) {
993 if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
994 LockedStreamFile locked_stream = error_sp->Lock();
995 locked_stream.Printf("Warning: No command attached to breakpoint.\n");
996 }
997 }
998 }
1000 } break;
1001 case eIOHandlerWatchpoint: {
1002 WatchpointOptions *wp_options =
1003 (WatchpointOptions *)io_handler.GetUserData();
1004 auto data_up = std::make_unique<WatchpointOptions::CommandData>();
1005 data_up->user_source.SplitIntoLines(data);
1006
1007 if (GenerateWatchpointCommandCallbackData(data_up->user_source,
1008 data_up->script_source,
1009 /*is_callback=*/false)) {
1010 auto baton_sp =
1011 std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
1012 wp_options->SetCallback(
1014 } else if (!batch_mode) {
1015 if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
1016 LockedStreamFile locked_stream = error_sp->Lock();
1017 locked_stream.Printf("Warning: No command attached to breakpoint.\n");
1018 }
1019 }
1021 } break;
1022 }
1023}
1024
1027 return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
1028}
1029
1031 Log *log = GetLog(LLDBLog::Script);
1032 if (log)
1033 log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");
1034
1035 // Unset the LLDB global variables.
1036 RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
1037 "= None; lldb.thread = None; lldb.frame = None");
1038
1039 // checking that we have a valid thread state - since we use our own
1040 // threading and locking in some (rare) cases during cleanup Python may end
1041 // up believing we have no thread state and PyImport_AddModule will crash if
1042 // that is the case - since that seems to only happen when destroying the
1043 // SBDebugger, we can make do without clearing up stdout and stderr
1044 if (PyThreadState_GetDict()) {
1045 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1046 if (sys_module_dict.IsValid()) {
1047 // Flush the pipe-backed wrappers while they are still sys.stdout/stderr.
1048 // Line buffering already flushes on each newline, but a trailing
1049 // unterminated line would otherwise be stranded (and later flushed into
1050 // a closed descriptor) once we close the pipe write end below.
1051 auto flush_redirect = [&](const char *py_name,
1052 std::unique_ptr<SessionIORedirect> &redirect) {
1053 if (!redirect)
1054 return;
1055 PythonObject file =
1056 sys_module_dict.GetItemForKey(PythonString(py_name));
1057 if (!file.IsValid())
1058 return;
1059 if (llvm::Expected<PythonObject> result = file.CallMethod("flush"))
1060 (void)result;
1061 else
1062 llvm::consumeError(result.takeError());
1063 };
1064 flush_redirect("stdout", m_stdout_redirect);
1065 flush_redirect("stderr", m_stderr_redirect);
1066
1067 if (m_saved_stdin.IsValid()) {
1068 sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
1070 }
1071 if (m_saved_stdout.IsValid()) {
1072 sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
1073 m_saved_stdout.Reset();
1074 }
1075 if (m_saved_stderr.IsValid()) {
1076 sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
1077 m_saved_stderr.Reset();
1078 }
1079 }
1080 }
1081
1082 // Tear down the pipe redirects (closes each write end and joins its reader).
1083 // The wrappers were flushed above, so nothing buffered is lost.
1084 m_stdout_redirect.reset();
1086
1087 m_session_is_active = false;
1088}
1089
1091 const char *py_name, PythonObject &save_file, const char *mode,
1092 File &file) {
1093 const bool is_stdout = ::strcmp(py_name, "stdout") == 0;
1094 if (!is_stdout && ::strcmp(py_name, "stderr") != 0)
1095 return false;
1096
1097 // The statusline is the only writer that races Python's terminal output.
1098 // When it isn't drawing there is nothing to serialize against, so keep the
1099 // normal wrapping and skip the reader thread and pipe.
1101 return false;
1102
1103 // Only the debugger's own terminal races the statusline. A redirect to a
1104 // pipe or user file (a different descriptor) is wrapped normally.
1105 lldb::FileSP debugger_file =
1107 int fd = file.GetDescriptor();
1108 if (!debugger_file || fd == File::kInvalidDescriptor ||
1109 fd != debugger_file->GetDescriptor())
1110 return false;
1111
1112 std::unique_ptr<SessionIORedirect> &redirect =
1114 redirect = SessionIORedirect::Create(m_debugger.GetID(), is_stdout);
1115 if (!redirect)
1116 return false;
1117
1118 // Line-buffer the wrapper so each print() reaches the reader (and the
1119 // terminal) promptly: the pipe descriptor is not a tty, so the default
1120 // buffering would hold output back until the buffer filled.
1121 PyObject *pipe_file = PyFile_FromFd(
1122 PythonFile::TranslateFdToPython(redirect->GetWriteDescriptor()), nullptr,
1123 mode, /*buffering=*/1,
1124 /*encoding=*/nullptr, /*errors=*/"ignore",
1125 /*newline=*/nullptr,
1126 /*closefd=*/0);
1127 if (!pipe_file) {
1128 // Fall back to the raw descriptor. That reopens the statusline race, so
1129 // leave a breadcrumb rather than failing silently.
1131 "failed to wrap sys.{0} on a synchronized pipe; falling back to "
1132 "the unsynchronized terminal descriptor",
1133 py_name);
1134 PyErr_Clear();
1135 redirect.reset();
1136 return false;
1137 }
1138
1139 PythonObject new_file(PyRefType::Owned, pipe_file);
1140 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1141 save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
1142 sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
1143 return true;
1144}
1145
1147 const char *py_name,
1148 PythonObject &save_file,
1149 const char *mode,
1150 bool serialize_terminal_output) {
1151 if (!file_sp || !*file_sp) {
1152 save_file.Reset();
1153 return false;
1154 }
1155 File &file = *file_sp;
1156
1157 // When stdout/stderr point at the debugger's own terminal, route Python's
1158 // output through a pipe drained under the output lock so a script's print()
1159 // cannot race the statusline. Any other target keeps the normal wrapping.
1160 if (serialize_terminal_output &&
1161 RedirectTerminalHandleThroughLock(py_name, save_file, mode, file))
1162 return true;
1163
1164 // Flush the file before giving it to python to avoid interleaved output.
1165 file.Flush();
1166
1167 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1168
1169 auto new_file = PythonFile::FromFile(file, mode);
1170 if (!new_file) {
1171 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), new_file.takeError(),
1172 "ScriptInterpreterPythonImpl::SetStdHandle failed to wrap "
1173 "sys.{1}: {0}",
1174 py_name);
1175 return false;
1176 }
1177
1178 save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
1180 sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());
1181 return true;
1182}
1183
1184bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
1185 FileSP in_sp, FileSP out_sp,
1186 FileSP err_sp) {
1187 // If we have already entered the session, without having officially 'left'
1188 // it, then there is no need to 'enter' it again.
1189 Log *log = GetLog(LLDBLog::Script);
1190 if (m_session_is_active) {
1191 LLDB_LOGF(
1192 log,
1193 "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
1194 ") session is already active, returning without doing anything",
1195 on_entry_flags);
1196 return false;
1197 }
1198
1199 LLDB_LOGF(
1200 log,
1201 "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",
1202 on_entry_flags);
1203
1204 m_session_is_active = true;
1205
1206 StreamString run_string;
1207
1208 if (on_entry_flags & Locker::InitGlobals) {
1209 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
1211 run_string.Printf(
1212 "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
1213 m_debugger.GetID());
1214 run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");
1215 run_string.PutCString("; lldb.process = lldb.target.GetProcess()");
1216 run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
1217 run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
1218 run_string.PutCString("')");
1219 } else {
1220 // If we aren't initing the globals, we should still always set the
1221 // debugger (since that is always unique.)
1222 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
1223 m_dictionary_name.c_str(), m_debugger.GetID());
1224 run_string.Printf(
1225 "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
1226 m_debugger.GetID());
1227 run_string.PutCString("')");
1228 }
1229
1230 RunSimpleString(run_string.GetData());
1231 run_string.Clear();
1232
1233 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1234 if (sys_module_dict.IsValid()) {
1235 lldb::FileSP top_in_sp;
1236 lldb::LockableStreamFileSP top_out_sp, top_err_sp;
1237 if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
1238 m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
1239 top_err_sp);
1240
1241 if (on_entry_flags & Locker::NoSTDIN) {
1242 m_saved_stdin.Reset();
1243 } else {
1244 if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r",
1245 /*serialize_terminal_output=*/false)) {
1246 if (top_in_sp)
1247 SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r",
1248 /*serialize_terminal_output=*/false);
1249 }
1250 }
1251
1252 // Serialize terminal output for every session except those that opt out
1253 // with NoOutputRedirect (see the flag for why).
1254 const bool serialize_terminal_output =
1255 !(on_entry_flags & Locker::NoOutputRedirect);
1256
1257 if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w",
1258 serialize_terminal_output)) {
1259 if (top_out_sp)
1260 SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,
1261 "w", serialize_terminal_output);
1262 }
1263
1264 if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w",
1265 serialize_terminal_output)) {
1266 if (top_err_sp)
1267 SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,
1268 "w", serialize_terminal_output);
1269 }
1270 }
1271
1272 if (PyErr_Occurred())
1273 PyErr_Clear();
1274
1275 return true;
1276}
1277
1279 if (!m_main_module.IsValid())
1281 return m_main_module;
1282}
1283
1285 if (m_session_dict.IsValid())
1286 return m_session_dict;
1287
1288 PythonObject &main_module = GetMainModule();
1289 if (!main_module.IsValid())
1290 return m_session_dict;
1291
1293 PyModule_GetDict(main_module.get()));
1294 if (!main_dict.IsValid())
1295 return m_session_dict;
1296
1304 return m_sys_module_dict;
1307 return m_sys_module_dict;
1308}
1309
1310llvm::Expected<unsigned>
1312 const llvm::StringRef &callable_name) {
1313 if (callable_name.empty()) {
1314 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1315 "called with empty callable name.");
1316 }
1317 Locker py_lock(this,
1322 callable_name, dict);
1323 if (!pfunc.IsAllocated()) {
1324 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1325 "can't find callable: %s",
1326 callable_name.str().c_str());
1327 }
1328 llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
1329 if (!arg_info) {
1330 // `-f` may point at a builtin, unlike other GetArgInfo() callers.
1331 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), arg_info.takeError(),
1332 "GetArgInfo failed for callable {1}, falling back to "
1333 "inspect.signature: {0}",
1334 callable_name);
1336 }
1337 if (!arg_info)
1338 return arg_info.takeError();
1339 return arg_info.get().max_positional_args;
1340}
1341
1342static std::string GenerateUniqueName(const char *base_name_wanted,
1343 uint32_t &functions_counter,
1344 const void *name_token = nullptr) {
1345 StreamString sstr;
1346
1347 if (!base_name_wanted)
1348 return std::string();
1349
1350 if (!name_token)
1351 sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
1352 else
1353 sstr.Printf("%s_%p", base_name_wanted, name_token);
1354
1355 return std::string(sstr.GetString());
1356}
1357
1360 return true;
1361
1363 PyImport_AddModule("lldb.embedded_interpreter"));
1364 if (!module.IsValid())
1365 return false;
1366
1368 PyModule_GetDict(module.get()));
1369 if (!module_dict.IsValid())
1370 return false;
1371
1373 module_dict.GetItemForKey(PythonString("run_one_line"));
1375 module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
1376 return m_run_one_line_function.IsValid();
1377}
1378
1380 llvm::StringRef command, CommandReturnObject *result,
1381 const ExecuteScriptOptions &options) {
1382 std::string command_str = command.str();
1383
1384 if (!m_valid_session)
1385 return false;
1386
1387 if (!command.empty()) {
1388 // We want to call run_one_line, passing in the dictionary and the command
1389 // string. We cannot do this through RunSimpleString here because the
1390 // command string may contain escaped characters, and putting it inside
1391 // another string to pass to RunSimpleString messes up the escaping. So
1392 // we use the following more complicated method to pass the command string
1393 // directly down to Python.
1394 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1395 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1396 options.GetEnableIO(), m_debugger, result);
1397 if (!io_redirect_or_error) {
1398 if (result)
1399 result->AppendErrorWithFormatv(
1400 "failed to redirect I/O: {0}\n",
1401 llvm::fmt_consume(io_redirect_or_error.takeError()));
1402 else
1403 llvm::consumeError(io_redirect_or_error.takeError());
1404 return false;
1405 }
1406
1407 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1408
1409 bool success = false;
1410 {
1411 // WARNING! It's imperative that this RAII scope be as tight as
1412 // possible. In particular, the scope must end *before* we try to join
1413 // the read thread. The reason for this is that a pre-requisite for
1414 // joining the read thread is that we close the write handle (to break
1415 // the pipe and cause it to wake up and exit). But acquiring the GIL as
1416 // below will redirect Python's stdio to use this same handle. If we
1417 // close the handle while Python is still using it, bad things will
1418 // happen.
1419 Locker locker(
1420 this,
1422 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1423 ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
1425 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1426 io_redirect.GetErrorFile());
1427
1428 // Find the correct script interpreter dictionary in the main module.
1429 PythonDictionary &session_dict = GetSessionDictionary();
1430 if (session_dict.IsValid()) {
1432 if (PyCallable_Check(m_run_one_line_function.get())) {
1433 PythonObject pargs(
1435 Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
1436 if (pargs.IsValid()) {
1437 PythonObject return_value(
1439 PyObject_CallObject(m_run_one_line_function.get(),
1440 pargs.get()));
1441 if (return_value.IsValid())
1442 success = true;
1443 else if (options.GetMaskoutErrors() && PyErr_Occurred()) {
1444 PyErr_Print();
1445 PyErr_Clear();
1446 }
1447 }
1448 }
1449 }
1450 }
1451
1452 io_redirect.Flush();
1453 }
1454
1455 if (success)
1456 return true;
1457
1458 // The one-liner failed. Append the error message.
1459 if (result) {
1460 result->AppendErrorWithFormat("python failed attempting to evaluate '%s'",
1461 command_str.c_str());
1462 }
1463 return false;
1464 }
1465
1466 if (result)
1467 result->AppendError("empty command passed to python\n");
1468 return false;
1469}
1470
1473
1474 Debugger &debugger = m_debugger;
1475
1476 // At the moment, the only time the debugger does not have an input file
1477 // handle is when this is called directly from Python, in which case it is
1478 // both dangerous and unnecessary (not to mention confusing) to try to embed
1479 // a running interpreter loop inside the already running Python interpreter
1480 // loop, so we won't do it.
1481
1482 if (!debugger.GetInputFile().IsValid())
1483 return;
1484
1485 IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
1486 if (io_handler_sp) {
1487 debugger.RunIOHandlerAsync(io_handler_sp);
1488 }
1489}
1490
1492#if LLDB_USE_PYTHON_SET_INTERRUPT
1493 // If the interpreter isn't evaluating any Python at the moment then return
1494 // false to signal that this function didn't handle the interrupt and the
1495 // next component should try handling it.
1496 if (!IsExecutingPython())
1497 return false;
1498
1499 // Tell Python that it should pretend to have received a SIGINT.
1500 PyErr_SetInterrupt();
1501 // PyErr_SetInterrupt has no way to return an error so we can only pretend the
1502 // signal got successfully handled and return true.
1503 // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but
1504 // the error handling is limited to checking the arguments which would be
1505 // just our (hardcoded) input signal code SIGINT, so that's not useful at all.
1506 return true;
1507#else
1508 Log *log = GetLog(LLDBLog::Script);
1509
1510 if (IsExecutingPython()) {
1511 PyThreadState *state = PyThreadState_Get();
1512 if (!state)
1513 state = GetThreadState();
1514 if (state) {
1515 long tid = PyThread_get_thread_ident();
1516 PyThreadState_Swap(state);
1517 int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
1518 LLDB_LOGF(log,
1519 "ScriptInterpreterPythonImpl::Interrupt() sending "
1520 "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
1521 tid, num_threads);
1522 return true;
1523 }
1524 }
1525 LLDB_LOGF(log,
1526 "ScriptInterpreterPythonImpl::Interrupt() python code not running, "
1527 "can't interrupt");
1528 return false;
1529#endif
1530}
1531
1533 llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
1534 void *ret_value, const ExecuteScriptOptions &options) {
1535
1536 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1537 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1538 options.GetEnableIO(), m_debugger, /*result=*/nullptr);
1539
1540 if (!io_redirect_or_error) {
1541 llvm::consumeError(io_redirect_or_error.takeError());
1542 return false;
1543 }
1544
1545 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1546
1547 Locker locker(this,
1549 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1552 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1553 io_redirect.GetErrorFile());
1554
1555 PythonModule &main_module = GetMainModule();
1556 PythonDictionary globals = main_module.GetDictionary();
1557
1559 if (!locals.IsValid())
1560 locals = unwrapIgnoringErrors(
1562 if (!locals.IsValid())
1563 locals = globals;
1564
1565 Expected<PythonObject> maybe_py_return =
1566 runStringOneLine(in_string, globals, locals);
1567
1568 if (!maybe_py_return) {
1569 llvm::handleAllErrors(
1570 maybe_py_return.takeError(),
1571 [&](PythonException &E) {
1572 E.Restore();
1573 if (options.GetMaskoutErrors()) {
1574 if (E.Matches(PyExc_SyntaxError)) {
1575 PyErr_Print();
1576 }
1577 PyErr_Clear();
1578 }
1579 },
1580 [](const llvm::ErrorInfoBase &E) {});
1581 return false;
1582 }
1583
1584 PythonObject py_return = std::move(maybe_py_return.get());
1585 assert(py_return.IsValid());
1586
1587 switch (return_type) {
1588 case eScriptReturnTypeCharPtr: // "char *"
1589 {
1590 const char format[3] = "s#";
1591 return PyArg_Parse(py_return.get(), format, (char **)ret_value);
1592 }
1593 case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
1594 // Py_None
1595 {
1596 const char format[3] = "z";
1597 return PyArg_Parse(py_return.get(), format, (char **)ret_value);
1598 }
1599 case eScriptReturnTypeBool: {
1600 const char format[2] = "b";
1601 return PyArg_Parse(py_return.get(), format, (bool *)ret_value);
1602 }
1603 case eScriptReturnTypeShortInt: {
1604 const char format[2] = "h";
1605 return PyArg_Parse(py_return.get(), format, (short *)ret_value);
1606 }
1607 case eScriptReturnTypeShortIntUnsigned: {
1608 const char format[2] = "H";
1609 return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
1610 }
1611 case eScriptReturnTypeInt: {
1612 const char format[2] = "i";
1613 return PyArg_Parse(py_return.get(), format, (int *)ret_value);
1614 }
1615 case eScriptReturnTypeIntUnsigned: {
1616 const char format[2] = "I";
1617 return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
1618 }
1619 case eScriptReturnTypeLongInt: {
1620 const char format[2] = "l";
1621 return PyArg_Parse(py_return.get(), format, (long *)ret_value);
1622 }
1623 case eScriptReturnTypeLongIntUnsigned: {
1624 const char format[2] = "k";
1625 return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
1626 }
1627 case eScriptReturnTypeLongLong: {
1628 const char format[2] = "L";
1629 return PyArg_Parse(py_return.get(), format, (long long *)ret_value);
1630 }
1631 case eScriptReturnTypeLongLongUnsigned: {
1632 const char format[2] = "K";
1633 return PyArg_Parse(py_return.get(), format,
1634 (unsigned long long *)ret_value);
1635 }
1636 case eScriptReturnTypeFloat: {
1637 const char format[2] = "f";
1638 return PyArg_Parse(py_return.get(), format, (float *)ret_value);
1639 }
1640 case eScriptReturnTypeDouble: {
1641 const char format[2] = "d";
1642 return PyArg_Parse(py_return.get(), format, (double *)ret_value);
1643 }
1644 case eScriptReturnTypeChar: {
1645 const char format[2] = "c";
1646 return PyArg_Parse(py_return.get(), format, (char *)ret_value);
1647 }
1648 case eScriptReturnTypeOpaqueObject: {
1649 *((PyObject **)ret_value) = py_return.release();
1650 return true;
1652 }
1653 llvm_unreachable("Fully covered switch!");
1654}
1655
1657 const char *in_string, const ExecuteScriptOptions &options) {
1658
1659 if (in_string == nullptr)
1660 return Status();
1661
1662 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1663 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1664 options.GetEnableIO(), m_debugger, /*result=*/nullptr);
1665
1666 if (!io_redirect_or_error)
1667 return Status::FromError(io_redirect_or_error.takeError());
1668
1669 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1670
1671 Locker locker(this,
1673 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1676 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1677 io_redirect.GetErrorFile());
1678
1679 PythonModule &main_module = GetMainModule();
1680 PythonDictionary globals = main_module.GetDictionary();
1681
1682 PythonDictionary locals = GetSessionDictionary();
1683 if (!locals.IsValid())
1684 locals = unwrapIgnoringErrors(
1686 if (!locals.IsValid())
1687 locals = globals;
1688
1689 Expected<PythonObject> return_value =
1690 runStringMultiLine(in_string, globals, locals);
1691
1692 if (!return_value) {
1693 llvm::Error error =
1694 llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {
1695 llvm::Error error = llvm::createStringError(
1696 llvm::inconvertibleErrorCode(), E.ReadBacktrace());
1697 if (!options.GetMaskoutErrors())
1698 E.Restore();
1699 return error;
1700 });
1701 return Status::FromError(std::move(error));
1703
1704 return Status();
1705}
1706
1708 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
1709 CommandReturnObject &result) {
1711 m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
1712 " ", *this, &bp_options_vec);
1713}
1714
1716 WatchpointOptions *wp_options, CommandReturnObject &result) {
1718 m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
1719 " ", *this, wp_options);
1720}
1721
1723 BreakpointOptions &bp_options, const char *function_name,
1724 StructuredData::ObjectSP extra_args_sp) {
1725 Status error;
1726 // For now just cons up a oneliner that calls the provided function.
1727 std::string function_signature = function_name;
1728
1729 llvm::Expected<unsigned> maybe_args =
1731 if (!maybe_args) {
1733 "could not get num args: %s",
1734 llvm::toString(maybe_args.takeError()).c_str());
1735 return error;
1736 }
1737 size_t max_args = *maybe_args;
1738
1739 bool uses_extra_args = false;
1740 if (max_args >= 4) {
1741 uses_extra_args = true;
1742 function_signature += "(frame, bp_loc, extra_args, internal_dict)";
1743 } else if (max_args >= 3) {
1744 if (extra_args_sp) {
1746 "cannot pass extra_args to a three argument callback");
1747 return error;
1748 }
1749 uses_extra_args = false;
1750 function_signature += "(frame, bp_loc, internal_dict)";
1751 } else {
1752 error = Status::FromErrorStringWithFormat("expected 3 or 4 argument "
1753 "function, %s can only take %zu",
1754 function_name, max_args);
1755 return error;
1756 }
1757
1758 SetBreakpointCommandCallback(bp_options, function_signature.c_str(),
1759 extra_args_sp, uses_extra_args,
1760 /*is_callback=*/true);
1761 return error;
1762}
1763
1765 BreakpointOptions &bp_options,
1766 std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
1767 Status error;
1768 error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
1769 cmd_data_up->script_source,
1770 /*has_extra_args=*/false,
1771 /*is_callback=*/false);
1772 if (error.Fail()) {
1773 return error;
1774 }
1775 auto baton_sp =
1776 std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
1783 BreakpointOptions &bp_options, const char *command_body_text,
1784 bool is_callback) {
1785 return SetBreakpointCommandCallback(bp_options, command_body_text, {},
1786 /*uses_extra_args=*/false, is_callback);
1787}
1788
1789// Set a Python one-liner as the callback for the breakpoint.
1791 BreakpointOptions &bp_options, const char *command_body_text,
1792 StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,
1793 bool is_callback) {
1794 auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
1795 // Split the command_body_text into lines, and pass that to
1796 // GenerateBreakpointCommandCallbackData. That will wrap the body in an
1797 // auto-generated function, and return the function name in script_source.
1798 // That is what the callback will actually invoke.
1799
1800 data_up->user_source.SplitIntoLines(command_body_text);
1802 data_up->user_source, data_up->script_source, uses_extra_args,
1803 is_callback);
1804 if (error.Success()) {
1805 auto baton_sp =
1806 std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
1807 bp_options.SetCallback(
1809 return error;
1811 return error;
1812}
1813
1814// Set a Python one-liner as the callback for the watchpoint.
1816 WatchpointOptions *wp_options, const char *user_input, bool is_callback) {
1817 auto data_up = std::make_unique<WatchpointOptions::CommandData>();
1818
1819 // It's necessary to set both user_source and script_source to the oneliner.
1820 // The former is used to generate callback description (as in watchpoint
1821 // command list) while the latter is used for Python to interpret during the
1822 // actual callback.
1823
1824 data_up->user_source.AppendString(user_input);
1825 data_up->script_source.assign(user_input);
1826
1828 data_up->user_source, data_up->script_source, is_callback)) {
1829 auto baton_sp =
1830 std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
1831 wp_options->SetCallback(
1833 }
1834}
1835
1837 StringList &function_def) {
1838 // Convert StringList to one long, newline delimited, const char *.
1839 std::string function_def_string(function_def.CopyList());
1840 LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n{0}\n",
1841 function_def_string.c_str());
1842
1844 function_def_string.c_str(), ExecuteScriptOptions().SetEnableIO(false));
1845 return error;
1846}
1847
1849 const StringList &input,
1850 bool is_callback) {
1851 Status error;
1852 int num_lines = input.GetSize();
1853 if (num_lines == 0) {
1854 error = Status::FromErrorString("No input data.");
1855 return error;
1856 }
1857
1858 if (!signature || *signature == 0) {
1859 error = Status::FromErrorString("No output function name.");
1860 return error;
1861 }
1862
1863 StreamString sstr;
1864 StringList auto_generated_function;
1865 auto_generated_function.AppendString(signature);
1866 auto_generated_function.AppendString(
1867 " global_dict = globals()"); // Grab the global dictionary
1868 auto_generated_function.AppendString(
1869 " new_keys = internal_dict.keys()"); // Make a list of keys in the
1870 // session dict
1871 auto_generated_function.AppendString(
1872 " old_keys = global_dict.keys()"); // Save list of keys in global dict
1873 auto_generated_function.AppendString(
1874 " global_dict.update(internal_dict)"); // Add the session dictionary
1875 // to the global dictionary.
1876
1877 if (is_callback) {
1878 // If the user input is a callback to a python function, make sure the input
1879 // is only 1 line, otherwise appending the user input would break the
1880 // generated wrapped function
1881 if (num_lines == 1) {
1882 sstr.Clear();
1883 sstr.Printf(" __return_val = %s", input.GetStringAtIndex(0));
1884 auto_generated_function.AppendString(sstr.GetData());
1885 } else {
1887 "ScriptInterpreterPythonImpl::GenerateFunction(is_callback="
1888 "true) = ERROR: python function is multiline.");
1889 }
1890 } else {
1891 auto_generated_function.AppendString(
1892 " __return_val = None"); // Initialize user callback return value.
1893 auto_generated_function.AppendString(
1894 " def __user_code():"); // Create a nested function that will wrap
1895 // the user input. This is necessary to
1896 // capture the return value of the user input
1897 // and prevent early returns.
1898 for (int i = 0; i < num_lines; ++i) {
1899 sstr.Clear();
1900 sstr.Printf(" %s", input.GetStringAtIndex(i));
1901 auto_generated_function.AppendString(sstr.GetData());
1902 }
1903 auto_generated_function.AppendString(
1904 " __return_val = __user_code()"); // Call user code and capture
1905 // return value
1906 }
1907 auto_generated_function.AppendString(
1908 " for key in new_keys:"); // Iterate over all the keys from session
1909 // dict
1910 auto_generated_function.AppendString(
1911 " if key in old_keys:"); // If key was originally in
1912 // global dict
1913 auto_generated_function.AppendString(
1914 " internal_dict[key] = global_dict[key]"); // Update it
1915 auto_generated_function.AppendString(
1916 " elif key in global_dict:"); // Then if it is still in the
1917 // global dict
1918 auto_generated_function.AppendString(
1919 " del global_dict[key]"); // remove key/value from the
1920 // global dict
1921 auto_generated_function.AppendString(
1922 " return __return_val"); // Return the user callback return value.
1923
1924 // Verify that the results are valid Python.
1926
1927 return error;
1928}
1929
1931 StringList &user_input, std::string &output, const void *name_token) {
1932 static uint32_t num_created_functions = 0;
1933 user_input.RemoveBlankLines();
1934 StreamString sstr;
1935
1936 // Check to see if we have any data; if not, just return.
1937 if (user_input.GetSize() == 0)
1938 return false;
1939
1940 // Take what the user wrote, wrap it all up inside one big auto-generated
1941 // Python function, passing in the ValueObject as parameter to the function.
1942
1943 std::string auto_generated_function_name(
1944 GenerateUniqueName("lldb_autogen_python_type_print_func",
1945 num_created_functions, name_token));
1946 sstr.Printf("def %s (valobj, internal_dict):",
1947 auto_generated_function_name.c_str());
1948
1949 if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
1950 .Success())
1951 return false;
1952
1953 // Store the name of the auto-generated function to be called.
1954 output.assign(auto_generated_function_name);
1955 return true;
1956}
1957
1959 StringList &user_input, std::string &output) {
1960 static uint32_t num_created_functions = 0;
1961 user_input.RemoveBlankLines();
1962 StreamString sstr;
1963
1964 // Check to see if we have any data; if not, just return.
1965 if (user_input.GetSize() == 0)
1966 return false;
1967
1968 std::string auto_generated_function_name(GenerateUniqueName(
1969 "lldb_autogen_python_cmd_alias_func", num_created_functions));
1970
1971 sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",
1972 auto_generated_function_name.c_str());
1973
1974 if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
1975 .Success())
1976 return false;
1977
1978 // Store the name of the auto-generated function to be called.
1979 output.assign(auto_generated_function_name);
1980 return true;
1981}
1982
1984 StringList &user_input, std::string &output, const void *name_token) {
1985 static uint32_t num_created_classes = 0;
1986 user_input.RemoveBlankLines();
1987 int num_lines = user_input.GetSize();
1988 StreamString sstr;
1989
1990 // Check to see if we have any data; if not, just return.
1991 if (user_input.GetSize() == 0)
1992 return false;
1993
1994 // Wrap all user input into a Python class
1995
1996 std::string auto_generated_class_name(GenerateUniqueName(
1997 "lldb_autogen_python_type_synth_class", num_created_classes, name_token));
1998
1999 StringList auto_generated_class;
2000
2001 // Create the function name & definition string.
2002
2003 sstr.Printf("class %s:", auto_generated_class_name.c_str());
2004 auto_generated_class.AppendString(sstr.GetString());
2005
2006 // Wrap everything up inside the class, increasing the indentation. we don't
2007 // need to play any fancy indentation tricks here because there is no
2008 // surrounding code whose indentation we need to honor
2009 for (int i = 0; i < num_lines; ++i) {
2010 sstr.Clear();
2011 sstr.Printf(" %s", user_input.GetStringAtIndex(i));
2012 auto_generated_class.AppendString(sstr.GetString());
2013 }
2014
2015 // Verify that the results are valid Python. (even though the method is
2016 // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
2017 // (TODO: rename that method to ExportDefinitionToInterpreter)
2018 if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
2019 return false;
2020
2021 // Store the name of the auto-generated class
2022
2023 output.assign(auto_generated_class_name);
2024 return true;
2025}
2026
2029 return std::make_unique<ScriptedProcessPythonInterface>(*this);
2030}
2031
2034 return std::make_shared<ScriptedHookPythonInterface>(*this);
2035}
2036
2039 return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
2040}
2041
2044 return std::make_shared<ScriptedStackFrameRecognizerPythonInterface>(*this);
2045}
2046
2049 return std::make_shared<ScriptedCommandPythonInterface>(*this);
2050}
2051
2054 return std::make_shared<ScriptedStringSummaryPythonInterface>(*this);
2055}
2056
2059 return std::make_shared<ScriptedSyntheticChildrenPythonInterface>(*this);
2060}
2061
2064 return std::make_shared<ScriptedThreadPythonInterface>(*this);
2065}
2066
2069 return std::make_shared<ScriptedFramePythonInterface>(*this);
2070}
2071
2074 return std::make_shared<ScriptedFrameProviderPythonInterface>(*this);
2075}
2076
2079 return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
2080}
2081
2084 return std::make_shared<OperatingSystemPythonInterface>(*this);
2085}
2086
2089 ScriptObject obj) {
2090 void *ptr = const_cast<void *>(obj.GetPointer());
2092 PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));
2093 if (!py_obj.IsValid() || py_obj.IsNone())
2094 return {};
2095 return py_obj.CreateStructuredObject();
2096}
2097
2101 if (!FileSystem::Instance().Exists(file_spec)) {
2102 error = Status::FromErrorString("no such file");
2103 return StructuredData::ObjectSP();
2104 }
2105
2106 StructuredData::ObjectSP module_sp;
2107
2108 LoadScriptOptions load_script_options =
2109 LoadScriptOptions().SetInitSession(true).SetSilent(false);
2110 if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
2111 error, &module_sp))
2112 return module_sp;
2113
2114 return StructuredData::ObjectSP();
2115}
2116
2118 StructuredData::ObjectSP plugin_module_sp, Target *target,
2119 const char *setting_name, lldb_private::Status &error) {
2120 if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
2122 StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
2123 if (!generic)
2125
2126 Locker py_lock(this,
2128 TargetSP target_sp(target->shared_from_this());
2129
2130 auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
2131 generic->GetValue(), setting_name, target_sp);
2132
2133 if (!setting)
2135
2136 PythonDictionary py_dict =
2138
2139 if (!py_dict)
2146 const char *oneliner, std::string &output, const void *name_token) {
2148 input.SplitIntoLines(oneliner, strlen(oneliner));
2149 return GenerateTypeScriptFunction(input, output, name_token);
2150}
2151
2153 const char *oneliner, std::string &output, const void *name_token) {
2155 input.SplitIntoLines(oneliner, strlen(oneliner));
2156 return GenerateTypeSynthClass(input, output, name_token);
2157}
2158
2160 StringList &user_input, std::string &output, bool has_extra_args,
2161 bool is_callback) {
2162 static uint32_t num_created_functions = 0;
2163 user_input.RemoveBlankLines();
2164 StreamString sstr;
2165 Status error;
2166 if (user_input.GetSize() == 0) {
2167 error = Status::FromErrorString("No input data.");
2168 return error;
2169 }
2170
2171 std::string auto_generated_function_name(GenerateUniqueName(
2172 "lldb_autogen_python_bp_callback_func_", num_created_functions));
2173 if (has_extra_args)
2174 sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
2175 auto_generated_function_name.c_str());
2176 else
2177 sstr.Printf("def %s (frame, bp_loc, internal_dict):",
2178 auto_generated_function_name.c_str());
2179
2180 error = GenerateFunction(sstr.GetData(), user_input, is_callback);
2181 if (!error.Success())
2182 return error;
2183
2184 // Store the name of the auto-generated function to be called.
2185 output.assign(auto_generated_function_name);
2186 return error;
2187}
2188
2190 StringList &user_input, std::string &output, bool is_callback) {
2191 static uint32_t num_created_functions = 0;
2192 user_input.RemoveBlankLines();
2193 StreamString sstr;
2194
2195 if (user_input.GetSize() == 0)
2196 return false;
2197
2198 std::string auto_generated_function_name(GenerateUniqueName(
2199 "lldb_autogen_python_wp_callback_func_", num_created_functions));
2200 sstr.Printf("def %s (frame, wp, internal_dict):",
2201 auto_generated_function_name.c_str());
2202
2203 if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())
2204 return false;
2205
2206 // Store the name of the auto-generated function to be called.
2207 output.assign(auto_generated_function_name);
2208 return true;
2209}
2210
2212 const char *python_function_name, lldb::ValueObjectSP valobj,
2213 StructuredData::ObjectSP &callee_wrapper_sp,
2214 const TypeSummaryOptions &options, std::string &retval) {
2215
2217
2218 if (!valobj.get()) {
2219 retval.assign("<no object>");
2220 return false;
2221 }
2222
2223 void *old_callee = nullptr;
2224 StructuredData::Generic *generic = nullptr;
2225 if (callee_wrapper_sp) {
2226 generic = callee_wrapper_sp->GetAsGeneric();
2227 if (generic)
2228 old_callee = generic->GetValue();
2229 }
2230 void *new_callee = old_callee;
2231
2232 bool ret_val;
2233 if (python_function_name && *python_function_name) {
2234 {
2237 {
2238 TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
2239
2240 static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");
2241 Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");
2243 python_function_name, GetSessionDictionary().get(), valobj,
2244 &new_callee, options_sp, retval);
2245 }
2246 }
2247 } else {
2248 retval.assign("<no function name>");
2249 return false;
2250 }
2251
2252 if (new_callee && old_callee != new_callee) {
2253 Locker py_lock(this,
2255 callee_wrapper_sp = std::make_shared<StructuredPythonObject>(
2256 PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));
2258
2259 return ret_val;
2260}
2261
2263 const char *python_function_name, TypeImplSP type_impl_sp) {
2264 Locker py_lock(this,
2267 python_function_name, m_dictionary_name.c_str(), type_impl_sp);
2268}
2269
2271 void *baton, StoppointCallbackContext *context, user_id_t break_id,
2272 user_id_t break_loc_id) {
2273 CommandDataPython *bp_option_data = (CommandDataPython *)baton;
2274 const char *python_function_name = bp_option_data->script_source.c_str();
2275
2276 if (!context)
2277 return true;
2278
2279 ExecutionContext exe_ctx(context->exe_ctx_ref);
2280 Target *target = exe_ctx.GetTargetPtr();
2281
2282 if (!target)
2283 return true;
2284
2285 Debugger &debugger = target->GetDebugger();
2286 ScriptInterpreterPythonImpl *python_interpreter =
2287 GetPythonInterpreter(debugger);
2288
2289 if (!python_interpreter)
2290 return true;
2291
2292 if (python_function_name && python_function_name[0]) {
2293 const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
2294 BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
2295 if (breakpoint_sp) {
2296 const BreakpointLocationSP bp_loc_sp(
2297 breakpoint_sp->FindLocationByID(break_loc_id));
2298
2299 if (stop_frame_sp && bp_loc_sp) {
2300 bool ret_val = true;
2301 {
2302 Locker py_lock(python_interpreter, Locker::AcquireLock |
2305 Expected<bool> maybe_ret_val =
2307 python_function_name,
2308 python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
2309 bp_loc_sp, bp_option_data->m_extra_args);
2310
2311 if (!maybe_ret_val) {
2312
2313 llvm::handleAllErrors(
2314 maybe_ret_val.takeError(),
2315 [&](PythonException &E) {
2316 *debugger.GetAsyncErrorStream() << E.ReadBacktrace();
2317 },
2318 [&](const llvm::ErrorInfoBase &E) {
2319 *debugger.GetAsyncErrorStream() << E.message();
2320 });
2321
2322 } else {
2323 ret_val = maybe_ret_val.get();
2324 }
2325 }
2326 return ret_val;
2327 }
2328 }
2329 }
2330 // We currently always true so we stop in case anything goes wrong when
2331 // trying to call the script function
2332 return true;
2333}
2334
2336 void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
2337 WatchpointOptions::CommandData *wp_option_data =
2339 const char *python_function_name = wp_option_data->script_source.c_str();
2340
2341 if (!context)
2342 return true;
2343
2344 ExecutionContext exe_ctx(context->exe_ctx_ref);
2345 Target *target = exe_ctx.GetTargetPtr();
2346
2347 if (!target)
2348 return true;
2349
2350 Debugger &debugger = target->GetDebugger();
2351 ScriptInterpreterPythonImpl *python_interpreter =
2352 GetPythonInterpreter(debugger);
2353
2354 if (!python_interpreter)
2355 return true;
2356
2357 if (python_function_name && python_function_name[0]) {
2358 const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
2359 WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
2360 if (wp_sp) {
2361 if (stop_frame_sp && wp_sp) {
2362 bool ret_val = true;
2363 {
2364 Locker py_lock(python_interpreter, Locker::AcquireLock |
2368 python_function_name,
2369 python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
2370 wp_sp);
2371 }
2372 return ret_val;
2373 }
2374 }
2375 }
2376 // We currently always true so we stop in case anything goes wrong when
2377 // trying to call the script function
2378 return true;
2379}
2380
2382 const char *impl_function, Process *process, std::string &output,
2383 Status &error) {
2384 bool ret_val;
2385 if (!process) {
2386 error = Status::FromErrorString("no process");
2387 return false;
2388 }
2389 if (!impl_function || !impl_function[0]) {
2390 error = Status::FromErrorString("no function to execute");
2391 return false;
2392 }
2393
2394 {
2395 Locker py_lock(this,
2398 impl_function, m_dictionary_name.c_str(), process->shared_from_this(),
2399 output);
2400 if (!ret_val)
2401 error = Status::FromErrorString("python script evaluation failed");
2402 }
2403 return ret_val;
2404}
2405
2407 const char *impl_function, Thread *thread, std::string &output,
2408 Status &error) {
2409 if (!thread) {
2410 error = Status::FromErrorString("no thread");
2411 return false;
2412 }
2413 if (!impl_function || !impl_function[0]) {
2414 error = Status::FromErrorString("no function to execute");
2415 return false;
2416 }
2417
2418 Locker py_lock(this,
2420 if (std::optional<std::string> result =
2422 impl_function, m_dictionary_name.c_str(),
2423 thread->shared_from_this())) {
2424 output = std::move(*result);
2425 return true;
2427 error = Status::FromErrorString("python script evaluation failed");
2428 return false;
2429}
2430
2432 const char *impl_function, Target *target, std::string &output,
2433 Status &error) {
2434 bool ret_val;
2435 if (!target) {
2436 error = Status::FromErrorString("no thread");
2437 return false;
2438 }
2439 if (!impl_function || !impl_function[0]) {
2440 error = Status::FromErrorString("no function to execute");
2441 return false;
2442 }
2443
2444 {
2445 TargetSP target_sp(target->shared_from_this());
2446 Locker py_lock(this,
2449 impl_function, m_dictionary_name.c_str(), target_sp, output);
2450 if (!ret_val)
2451 error = Status::FromErrorString("python script evaluation failed");
2452 }
2453 return ret_val;
2454}
2455
2457 const char *impl_function, StackFrame *frame, std::string &output,
2458 Status &error) {
2459 if (!frame) {
2460 error = Status::FromErrorString("no frame");
2461 return false;
2462 }
2463 if (!impl_function || !impl_function[0]) {
2464 error = Status::FromErrorString("no function to execute");
2465 return false;
2466 }
2467
2468 Locker py_lock(this,
2470 if (std::optional<std::string> result =
2472 impl_function, m_dictionary_name.c_str(),
2473 frame->shared_from_this())) {
2474 output = std::move(*result);
2475 return true;
2477 error = Status::FromErrorString("python script evaluation failed");
2478 return false;
2479}
2480
2482 const char *impl_function, ValueObject *value, std::string &output,
2483 Status &error) {
2484 bool ret_val;
2485 if (!value) {
2486 error = Status::FromErrorString("no value");
2487 return false;
2488 }
2489 if (!impl_function || !impl_function[0]) {
2490 error = Status::FromErrorString("no function to execute");
2491 return false;
2492 }
2493
2494 {
2495 Locker py_lock(this,
2498 impl_function, m_dictionary_name.c_str(), value->GetSP(), output);
2499 if (!ret_val)
2500 error = Status::FromErrorString("python script evaluation failed");
2501 }
2502 return ret_val;
2503}
2504
2505uint64_t replace_all(std::string &str, const std::string &oldStr,
2506 const std::string &newStr) {
2507 size_t pos = 0;
2508 uint64_t matches = 0;
2509 while ((pos = str.find(oldStr, pos)) != std::string::npos) {
2510 matches++;
2511 str.replace(pos, oldStr.length(), newStr);
2512 pos += newStr.length();
2513 }
2514 return matches;
2515}
2516
2518 const char *pathname, const LoadScriptOptions &options,
2520 FileSpec extra_search_dir, lldb::TargetSP target_sp) {
2521 namespace fs = llvm::sys::fs;
2522 namespace path = llvm::sys::path;
2523
2525 .SetEnableIO(!options.GetSilent())
2526 .SetSetLLDBGlobals(false);
2527
2528 if (!pathname || !pathname[0]) {
2529 error = Status::FromErrorString("empty path");
2530 return false;
2531 }
2532
2533 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
2534 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
2535 exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);
2536
2537 if (!io_redirect_or_error) {
2538 error = Status::FromError(io_redirect_or_error.takeError());
2539 return false;
2540 }
2541
2542 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
2543
2544 // Before executing Python code, lock the GIL.
2545 Locker py_lock(this,
2547 (options.GetInitSession() ? Locker::InitSession : 0) |
2550 (options.GetInitSession() ? Locker::TearDownSession : 0),
2551 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
2552 io_redirect.GetErrorFile());
2553
2554 auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
2555 if (directory.empty()) {
2556 return llvm::createStringError("invalid directory name");
2557 }
2558
2559 replace_all(directory, "\\", "\\\\");
2560 replace_all(directory, "'", "\\'");
2561
2562 // Make sure that Python has "directory" in the search path.
2563 StreamString command_stream;
2564 command_stream.Printf("if not (sys.path.__contains__('%s')):\n "
2565 "sys.path.insert(1,'%s');\n\n",
2566 directory.c_str(), directory.c_str());
2567 bool syspath_retval =
2568 ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
2569 if (!syspath_retval)
2570 return llvm::createStringError("Python sys.path handling failed");
2571
2572 return llvm::Error::success();
2573 };
2574
2575 std::string module_name(pathname);
2576 bool possible_package = false;
2577
2578 if (extra_search_dir) {
2579 if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
2580 error = Status::FromError(std::move(e));
2581 return false;
2582 }
2583 } else {
2584 FileSpec module_file(pathname);
2585 FileSystem::Instance().Resolve(module_file);
2586
2587 fs::file_status st;
2588 std::error_code ec = status(module_file.GetPath(), st);
2589
2590 if (ec || st.type() == fs::file_type::status_error ||
2591 st.type() == fs::file_type::type_unknown ||
2592 st.type() == fs::file_type::file_not_found) {
2593 // if not a valid file of any sort, check if it might be a filename still
2594 // dot can't be used but / and \ can, and if either is found, reject
2595 if (strchr(pathname, '\\') || strchr(pathname, '/')) {
2596 error = Status::FromErrorStringWithFormatv("invalid pathname '{0}'",
2597 pathname);
2598 return false;
2599 }
2600 // Not a filename, probably a package of some sort, let it go through.
2601 possible_package = true;
2602 } else if (is_directory(st) || is_regular_file(st)) {
2603 if (module_file.GetDirectory().empty()) {
2605 "invalid directory name '{0}'", pathname);
2606 return false;
2607 }
2608 if (llvm::Error e = ExtendSysPath(module_file.GetDirectory().str())) {
2609 error = Status::FromError(std::move(e));
2610 return false;
2611 }
2612 module_name = module_file.GetFilename().str();
2613 } else {
2615 "no known way to import this module specification");
2616 return false;
2617 }
2618 }
2619
2620 // Strip .py or .pyc extension
2621 llvm::StringRef extension = llvm::sys::path::extension(module_name);
2622 if (!extension.empty()) {
2623 if (extension == ".py")
2624 module_name.resize(module_name.length() - 3);
2625 else if (extension == ".pyc")
2626 module_name.resize(module_name.length() - 4);
2627 }
2628
2629 if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
2631 "Python does not allow dots in module names: %s", module_name.c_str());
2632 return false;
2633 }
2634
2635 if (module_name.find('-') != llvm::StringRef::npos) {
2637 "Python discourages dashes in module names: %s", module_name.c_str());
2638 return false;
2639 }
2640
2641 // Check if the module is already imported.
2642 StreamString command_stream;
2643 command_stream.Clear();
2644 command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
2645 bool does_contain = false;
2646 // This call will succeed if the module was ever imported in any Debugger in
2647 // the lifetime of the process in which this LLDB framework is living.
2648 const bool does_contain_executed = ExecuteOneLineWithReturn(
2649 command_stream.GetData(),
2651 exc_options);
2652
2653 const bool was_imported_globally = does_contain_executed && does_contain;
2654 const bool was_imported_locally =
2656 .GetItemForKey(PythonString(module_name))
2657 .IsAllocated();
2658
2659 // now actually do the import
2660 command_stream.Clear();
2661
2662 if (was_imported_globally || was_imported_locally) {
2663 if (!was_imported_locally)
2664 command_stream.Printf("import %s ; importlib.reload(%s)",
2665 module_name.c_str(), module_name.c_str());
2666 else
2667 command_stream.Printf("importlib.reload(%s)", module_name.c_str());
2668 } else
2669 command_stream.Printf("import %s", module_name.c_str());
2670
2671 error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
2672 if (error.Fail())
2673 return false;
2674
2675 // if we are here, everything worked
2676 // call __lldb_init_module(debugger,dict)
2678 module_name.c_str(), m_dictionary_name.c_str(),
2679 m_debugger.shared_from_this())) {
2680 error = Status::FromErrorString("calling __lldb_init_module failed");
2681 return false;
2682 }
2683
2684 if (module_sp) {
2685 // everything went just great, now set the module object
2686 command_stream.Clear();
2687 command_stream.Printf("%s", module_name.c_str());
2688 void *module_pyobj = nullptr;
2690 command_stream.GetData(),
2692 exc_options) &&
2693 module_pyobj)
2694 *module_sp = std::make_shared<StructuredPythonObject>(PythonObject(
2695 PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));
2696 }
2697
2698 // Finally, if we got a target passed in, then we should tell the new module
2699 // about this target:
2700 if (target_sp)
2702 module_name.c_str(), m_dictionary_name.c_str(), target_sp);
2703
2704 return true;
2705}
2706
2707bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {
2708 if (!word || !word[0])
2709 return false;
2710
2711 llvm::StringRef word_sr(word);
2712
2713 // filter out a few characters that would just confuse us and that are
2714 // clearly not keyword material anyway
2715 if (word_sr.find('"') != llvm::StringRef::npos ||
2716 word_sr.find('\'') != llvm::StringRef::npos)
2717 return false;
2718
2719 StreamString command_stream;
2720 command_stream.Printf("keyword.iskeyword('%s')", word);
2721 bool result;
2722 ExecuteScriptOptions options;
2723 options.SetEnableIO(false);
2724 options.SetMaskoutErrors(true);
2725 options.SetSetLLDBGlobals(false);
2726 if (ExecuteOneLineWithReturn(command_stream.GetData(),
2728 &result, options))
2729 return result;
2730 return false;
2731}
2732
2735 : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),
2736 m_old_asynch(debugger_sp->GetAsyncExecution()) {
2738 m_debugger_sp->SetAsyncExecution(false);
2740 m_debugger_sp->SetAsyncExecution(true);
2741}
2742
2744 if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
2745 m_debugger_sp->SetAsyncExecution(m_old_asynch);
2746}
2747
2749 const char *impl_function, llvm::StringRef args,
2750 ScriptedCommandSynchronicity synchronicity,
2752 const lldb_private::ExecutionContext &exe_ctx) {
2753 if (!impl_function) {
2754 error = Status::FromErrorString("no function to execute");
2755 return false;
2756 }
2757
2758 lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
2759 lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
2760
2761 if (!debugger_sp.get()) {
2762 error = Status::FromErrorString("invalid Debugger pointer");
2763 return false;
2764 }
2765
2766 bool ret_val = false;
2767
2768 {
2769 Locker py_lock(this,
2771 (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
2773
2774 SynchronicityHandler synch_handler(debugger_sp, synchronicity);
2775
2776 std::string args_str = args.str();
2778 impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),
2779 cmd_retobj, exe_ctx_ref_sp);
2780 }
2781
2782 if (!ret_val) {
2783 error = Status::FromErrorString("unable to execute script function");
2784 return false;
2785 }
2786 if (cmd_retobj.GetStatus() == eReturnStatusFailed)
2787 return false;
2788
2789 error.Clear();
2790 return ret_val;
2792
2793/// In Python, a special attribute __doc__ contains the docstring for an object
2794/// (function, method, class, ...) if any is defined Otherwise, the attribute's
2795/// value is None.
2797 std::string &dest) {
2798 dest.clear();
2799
2800 if (!item || !*item)
2801 return false;
2802
2803 std::string command(item);
2804 command += ".__doc__";
2805
2806 // Python is going to point this to valid data if ExecuteOneLineWithReturn
2807 // returns successfully.
2808 char *result_ptr = nullptr;
2809
2812 &result_ptr, ExecuteScriptOptions().SetEnableIO(false))) {
2813 if (result_ptr)
2814 dest.assign(result_ptr);
2815 return true;
2816 }
2817
2818 StreamString str_stream;
2819 str_stream << "Function " << item
2820 << " was not found. Containing module might be missing.";
2821 dest = std::string(str_stream.GetString());
2823 return false;
2824}
2825
2826std::unique_ptr<ScriptInterpreterLocker>
2828 std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
2831 return py_lock;
2832}
2833
2836
2837 // RAII-based initialization which correctly handles multiple-initialization,
2838 // version- specific differences among Python 2 and Python 3, and saving and
2839 // restoring various other pieces of state that can get mucked with during
2840 // initialization.
2841 InitializePythonRAII initialize_guard;
2842 if (llvm::Error error = initialize_guard.DoInitialize())
2843 return error;
2844
2846
2847 // Update the path python uses to search for modules to include the current
2848 // directory.
2849
2850 RunSimpleString("import sys");
2852
2853 // Don't denormalize paths when calling file_spec.GetPath(). On platforms
2854 // that use a backslash as the path separator, this will result in executing
2855 // python code containing paths with unescaped backslashes. But Python also
2856 // accepts forward slashes, so to make life easier we just use that.
2857 if (FileSpec file_spec = GetPythonDir())
2858 AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
2859 if (FileSpec file_spec = HostInfo::GetShlibDir())
2860 AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
2861
2862 RunSimpleString("sys.dont_write_bytecode = 1; import "
2863 "lldb.embedded_interpreter; from "
2864 "lldb.embedded_interpreter import run_python_interpreter; "
2865 "from lldb.embedded_interpreter import run_one_line");
2866
2867#if LLDB_USE_PYTHON_SET_INTERRUPT
2868 // Python will not just overwrite its internal SIGINT handler but also the
2869 // one from the process. Backup the current SIGINT handler to prevent that
2870 // Python deletes it.
2871 RestoreSignalHandlerScope save_sigint(SIGINT);
2872
2873 // Setup a default SIGINT signal handler that works the same way as the
2874 // normal Python REPL signal handler which raises a KeyboardInterrupt.
2875 // Also make sure to not pollute the user's REPL with the signal module nor
2876 // our utility function.
2877 RunSimpleString("def lldb_setup_sigint_handler():\n"
2878 " import signal;\n"
2879 " def signal_handler(sig, frame):\n"
2880 " raise KeyboardInterrupt()\n"
2881 " signal.signal(signal.SIGINT, signal_handler);\n"
2882 "lldb_setup_sigint_handler();\n"
2883 "del lldb_setup_sigint_handler\n");
2884#endif
2885 return llvm::Error::success();
2886}
2887
2889 std::string path) {
2890 std::string statement;
2891 if (location == AddLocation::Beginning) {
2892 statement.assign("sys.path.insert(0,\"");
2893 statement.append(path);
2894 statement.append("\")");
2895 } else {
2896 statement.assign("sys.path.append(\"");
2897 statement.append(path);
2898 statement.append("\")");
2899 }
2900 RunSimpleString(statement.c_str());
2901}
2902
2903// We are intentionally NOT calling Py_Finalize here (this would be the logical
2904// place to call it). Calling Py_Finalize here causes test suite runs to seg
2905// fault: The test suite runs in Python. It registers SBDebugger::Terminate to
2906// be called 'at_exit'. When the test suite Python harness finishes up, it
2907// calls Py_Finalize, which calls all the 'at_exit' registered functions.
2908// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
2909// which calls ScriptInterpreter::Terminate, which calls
2910// ScriptInterpreterPythonImpl::Terminate. So if we call Py_Finalize here, we
2911// end up with Py_Finalize being called from within Py_Finalize, which results
2912// in a seg fault. Since this function only gets called when lldb is shutting
2913// down and going away anyway, the fact that we don't actually call Py_Finalize
2914// should not cause any problems (everything should shut down/go away anyway
2915// when the process exits).
2916//
2917// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:382
ScriptInterpreterPythonImpl::Locker Locker
#define LLDB_PLUGIN_DEFINE(PluginName)
PyObject * PyInit__lldb(void)
static std::string GenerateUniqueName(const char *base_name_wanted, uint32_t &functions_counter, const void *name_token=nullptr)
#define LLDBSwigPyInit
static ScriptInterpreterPythonImpl * GetPythonInterpreter(Debugger &debugger)
static const char python_exe_relative_path[]
uint64_t replace_all(std::string &str, const std::string &oldStr, const std::string &newStr)
static const char GetInterpreterInfoScript[]
#define LLDB_SCOPED_TIMER()
Definition Timer.h:83
A Python sys.stdout/stderr file backed by a pipe whose read end is drained by a reader thread that wr...
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
static std::unique_ptr< SessionIORedirect > Create(lldb::user_id_t debugger_id, bool is_stdout)
"lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a breakpoint or breakpoint lo...
void SetCallback(BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous=false)
Adds a callback to the breakpoint option set.
void AppendError(llvm::StringRef in_string)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendErrorWithFormatv(const char *format, Args &&...args)
A class to manage flag bits.
Definition Debugger.h:100
lldb::FileSP GetErrorFileSP()
Definition Debugger.h:162
lldb::FileSP GetOutputFileSP()
Definition Debugger.h:158
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
bool StatuslineSupported()
Whether the statusline can be drawn: show-statusline is enabled and the output is an escape-code-capa...
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id)
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
ExecuteScriptOptions & SetMaskoutErrors(bool maskout)
ExecuteScriptOptions & SetSetLLDBGlobals(bool set)
ExecuteScriptOptions & SetEnableIO(bool enable)
Execution context objects refer to objects in the execution of the program that is being debugged.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
Target * GetTargetPtr() const
Returns a pointer to the target object.
A file utility class.
Definition FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:454
bool RemoveLastPathComponent()
Removes the last path component by replacing the current path with its parent.
Definition FileSpec.cpp:465
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
void SetDirectory(llvm::StringRef directory)
Directory string set accessor.
Definition FileSpec.cpp:358
llvm::StringRef GetFileNameExtension() const
Extract the extension of the file.
Definition FileSpec.cpp:410
Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
An abstract base class for files.
Definition FileBase.h:34
static int kInvalidDescriptor
Definition FileBase.h:36
virtual int GetDescriptor() const
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition File.cpp:119
bool IsValid() const override
IsValid.
Definition File.cpp:106
virtual Status Flush()
Flush the current stream.
Definition File.cpp:149
lldb::LockableStreamFileSP GetErrorStreamFileSP()
Definition IOHandler.cpp:95
lldb::LockableStreamFileSP GetOutputStreamFileSP()
Definition IOHandler.cpp:93
void SetIsDone(bool b)
Definition IOHandler.h:81
void PutCString(const char *cstr)
Definition Log.cpp:162
Status CreateNew() override
Definition PipePosix.cpp:82
int ReleaseReadFileDescriptor() override
int ReleaseWriteFileDescriptor() override
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
Definition Process.h:367
void Flush()
Flush our output and error file handles.
static llvm::Expected< std::unique_ptr< ScriptInterpreterIORedirect > > Create(bool enable_io, Debugger &debugger, CommandReturnObject *result)
Create an IO redirect.
bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, lldb::FileSP err)
Locker(ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry=AcquireLock|InitSession, uint16_t on_leave=FreeLock|TearDownSession, lldb::FileSP in=nullptr, lldb::FileSP out=nullptr, lldb::FileSP err=nullptr)
SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity)
bool GenerateTypeScriptFunction(StringList &input, std::string &output, const void *name_token=nullptr) override
Status GenerateFunction(const char *signature, const StringList &input, bool is_callback) override
bool GenerateScriptAliasFunction(StringList &input, std::string &output) override
lldb_private::Status ExecuteMultipleLines(const char *in_string, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
bool GenerateWatchpointCommandCallbackData(StringList &input, std::string &output, bool is_callback) override
Status SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) override
Set a script function as the callback for the breakpoint.
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override
std::unique_ptr< SessionIORedirect > m_stderr_redirect
static bool BreakpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Status &error) override
void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result) override
lldb::ScriptedCommandInterfaceSP CreateScriptedCommandInterface() override
bool RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override
lldb::ScriptedFrameProviderInterfaceSP CreateScriptedFrameProviderInterface() override
Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *callback_body, bool is_callback) override
Set the callback body text into the callback for the breakpoint.
lldb::ScriptedStackFrameRecognizerInterfaceSP CreateScriptedStackFrameRecognizerInterface() override
bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, lldb::FileSP err)
void SetWatchpointCommandCallback(WatchpointOptions *wp_options, const char *user_input, bool is_callback) override
Set a one-liner as the callback for the watchpoint.
bool RedirectTerminalHandleThroughLock(const char *py_name, python::PythonObject &save_file, const char *mode, File &file)
If file is the debugger's own terminal, point sys.
std::unique_ptr< ScriptInterpreterLocker > AcquireInterpreterLock() override
void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &bp_options_vec, CommandReturnObject &result) override
static void AddToSysPath(AddLocation location, std::string path)
lldb::ScriptedStringSummaryInterfaceSP CreateScriptedStringSummaryInterface() override
bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={}, lldb::TargetSP loaded_into_target_sp={}) override
Status GenerateBreakpointCommandCallbackData(StringList &input, std::string &output, bool has_extra_args, bool is_callback) override
lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override
bool FormatterCallbackFunction(const char *function_name, lldb::TypeImplSP type_impl_sp) override
Status ExportFunctionDefinitionToInterpreter(StringList &function_def) override
bool ExecuteOneLine(llvm::StringRef command, CommandReturnObject *result, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
bool GetDocumentationForItem(const char *item, std::string &dest) override
In Python, a special attribute doc contains the docstring for an object (function,...
lldb::ScriptedSyntheticChildrenInterfaceSP CreateScriptedSyntheticChildrenInterface() override
lldb::ScriptedHookInterfaceSP CreateScriptedHookInterface() override
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) override
lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override
lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override
bool ExecuteOneLineWithReturn(llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
lldb::ScriptedBreakpointInterfaceSP CreateScriptedBreakpointInterface() override
bool RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error) override
bool SetStdHandle(lldb::FileSP file, const char *py_name, python::PythonObject &save_file, const char *mode, bool serialize_terminal_output)
Point sys.
bool GenerateTypeSynthClass(StringList &input, std::string &output, const void *name_token=nullptr) override
StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) override
StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) override
llvm::Expected< unsigned > GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) override
static bool WatchpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id)
static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger)
lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override
std::unique_ptr< SessionIORedirect > m_stdout_redirect
Abstract interface for the Python script interpreter.
static void ComputePythonDir(llvm::SmallVectorImpl< char > &path)
static void ComputePythonDirForApple(llvm::SmallVectorImpl< char > &path)
llvm::Expected< StructuredData::ObjectSP > GetExtensionSchema(const llvm::SmallVector< llvm::StringRef > &extension_path)
StructuredData::DictionarySP GetInterpreterInfo() override
llvm::Error ParseExtensionSchema(Stream &s, llvm::StringRef output_script_prefix, const llvm::SmallVector< llvm::StringRef > &extension_path, bool generate_non_abstract_methods, std::set< std::string > &typing_imports)
static void SharedLibraryDirectoryHelper(FileSpec &this_file)
llvm::Expected< std::string > ExtensionToImportPath(lldb::ScriptedExtension extension) override
llvm::Expected< FileSpec > GenerateExtensionTemplate(const std::string &name, std::vector< ExtensionTemplateRequest > &extensions, bool generate_non_abstract_methods, std::string output_file) override
virtual bool ExecuteOneLineWithReturn(llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options=ExecuteScriptOptions())
static llvm::StringLiteral ExtensionToString(lldb::ScriptedExtension extension)
static lldb::ScriptedExtension StringToExtension(llvm::StringRef string)
const void * GetPointer() const
This base class provides an interface to stack frames.
Definition StackFrame.h:44
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition Status.h:151
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
bool Success() const
Test for success condition.
Definition Status.cpp:303
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
void Flush() override
Flush the stream.
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition Stream.cpp:204
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition Stream.cpp:201
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
size_t SplitIntoLines(const std::string &lines)
void AppendString(const std::string &s)
const char * GetStringAtIndex(size_t idx) const
bool ForEach(std::function< bool(Object *object)> const &foreach_callback) const
std::optional< Dictionary * > GetItemAtIndexAsDictionary(size_t idx) const
Retrieves the element at index idx from a StructuredData::Array if it is a Dictionary.
bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result) const
bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const
bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
static ObjectSP ParseJSON(llvm::StringRef json_text)
lldb::BreakpointSP GetBreakpointByID(lldb::break_id_t break_id)
Definition Target.cpp:438
Debugger & GetDebugger() const
Definition Target.h:1349
WatchpointList & GetWatchpointList()
Definition Target.h:978
"lldb/Core/ThreadedCommunication.h" Variation of Communication that supports threaded reads.
lldb::ValueObjectSP GetSP()
lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const
Returns a shared pointer to the watchpoint with id watchID, const version.
"lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a watchpoint.
void SetCallback(WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous=false)
Adds a callback to the watchpoint option set.
static llvm::Expected< ArgInfo > GetArgInfoFromInspectSignature(const PythonCallable &callable)
StructuredData::DictionarySP CreateStructuredDictionary() const
PythonObject GetItemForKey(const PythonObject &key) const
void SetItemForKey(const PythonObject &key, const PythonObject &value)
static int TranslateFdToPython(int our_fd)
static llvm::Expected< PythonFile > FromFile(File &file, const char *mode=nullptr)
static llvm::Expected< PythonModule > Import(const llvm::Twine &name)
PythonObject ResolveName(llvm::StringRef name) const
static PythonObject ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
llvm::Expected< PythonObject > GetAttribute(const llvm::Twine &name) const
llvm::Expected< PythonObject > CallMethod(const char *name, const T &... t) const
static bool LLDBSWIGPythonRunScriptKeywordValue(const char *python_function_name, const char *session_dictionary_name, const lldb::ValueObjectSP &value, std::string &output)
static bool LLDBSwigPythonCallTypeScript(const char *python_function_name, const void *session_dictionary, const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval)
static void * LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, const lldb::TargetSP &target_sp)
static std::optional< std::string > LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, const char *session_dictionary_name, lldb::ThreadSP thread)
static bool LLDBSwigPythonCallCommand(const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP debugger, const char *args, lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp)
static bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, const char *session_dictionary_name, const lldb::TargetSP &target, std::string &output)
static std::optional< std::string > LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, const char *session_dictionary_name, lldb::StackFrameSP frame)
static bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, const char *session_dictionary_name, const lldb::ProcessSP &process, std::string &output)
static bool LLDBSwigPythonFormatterCallbackFunction(const char *python_function_name, const char *session_dictionary_name, lldb::TypeImplSP type_impl_sp)
static bool LLDBSwigPythonCallModuleInit(const char *python_module_name, const char *session_dictionary_name, lldb::DebuggerSP debugger)
static bool LLDBSwigPythonWatchpointCallbackFunction(const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp)
static bool LLDBSwigPythonCallModuleNewTarget(const char *python_module_name, const char *session_dictionary_name, lldb::TargetSP target)
static llvm::Expected< bool > LLDBSwigPythonBreakpointCallbackFunction(const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::BreakpointLocationSP &sb_bp_loc, const lldb_private::StructuredDataImpl &args_impl)
llvm::Expected< T > As(llvm::Expected< PythonObject > &&obj)
T unwrapIgnoringErrors(llvm::Expected< T > expected)
llvm::Expected< PythonObject > runStringMultiLine(const llvm::Twine &string, const PythonDictionary &globals, const PythonDictionary &locals)
int RunSimpleString(const char *str)
llvm::Expected< PythonObject > runStringOneLine(const llvm::Twine &string, const PythonDictionary &globals, const PythonDictionary &locals)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
PipePosix Pipe
Definition Pipe.h:20
int file_t
Definition lldb-types.h:59
@ eScriptLanguagePython
ScriptedExtension
Scripting extension types.
@ eScriptedExtensionOperatingSystem
@ eScriptedExtensionScriptedHook
@ eScriptedExtensionParsedCommand
@ eScriptedExtensionScriptedPlatform
@ eScriptedExtensionScriptedCommand
@ eScriptedExtensionScriptedProcess
@ eScriptedExtensionScriptedFrame
@ eScriptedExtensionScriptedBreakpointResolver
@ eScriptedExtensionScriptedThreadPlan
@ eScriptedExtensionScriptedStringSummary
@ eScriptedExtensionScriptedFrameProvider
@ eScriptedExtensionScriptedThread
@ eScriptedExtensionScriptedStackFrameRecognizer
@ eScriptedExtensionScriptedSyntheticChildren
@ eScriptedExtensionInvalid
std::shared_ptr< lldb_private::ScriptedSyntheticChildrenInterface > ScriptedSyntheticChildrenInterfaceSP
std::shared_ptr< lldb_private::ScriptedHookInterface > ScriptedHookInterfaceSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ScriptedStringSummaryInterface > ScriptedStringSummaryInterfaceSP
std::shared_ptr< lldb_private::BreakpointLocation > BreakpointLocationSP
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
std::shared_ptr< lldb_private::ScriptInterpreter > ScriptInterpreterSP
std::shared_ptr< lldb_private::ScriptedThreadPlanInterface > ScriptedThreadPlanInterfaceSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::unique_ptr< lldb_private::File > FileUP
std::shared_ptr< lldb_private::TypeSummaryOptions > TypeSummaryOptionsSP
std::shared_ptr< lldb_private::OperatingSystemInterface > OperatingSystemInterfaceSP
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
std::shared_ptr< lldb_private::ScriptedBreakpointInterface > ScriptedBreakpointInterfaceSP
std::shared_ptr< lldb_private::ScriptedThreadInterface > ScriptedThreadInterfaceSP
std::shared_ptr< lldb_private::Debugger > DebuggerSP
@ eReturnStatusFailed
std::shared_ptr< lldb_private::Watchpoint > WatchpointSP
std::shared_ptr< lldb_private::ScriptedFrameProviderInterface > ScriptedFrameProviderInterfaceSP
std::shared_ptr< lldb_private::ScriptedCommandInterface > ScriptedCommandInterfaceSP
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::LockableStreamFile > LockableStreamFileSP
std::shared_ptr< lldb_private::TypeImpl > TypeImplSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::File > FileSP
std::shared_ptr< lldb_private::ScriptedStackFrameRecognizerInterface > ScriptedStackFrameRecognizerInterfaceSP
std::unique_ptr< lldb_private::ScriptedProcessInterface > ScriptedProcessInterfaceUP
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP
Describes one extension to emit into the generated template file.
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition UserID.h:47