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