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) {
693 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), loader.takeError(), "{0}");
694 return;
695 }
696 if (llvm::Error error = loader->Load()) {
697 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
698 return;
699 }
700
701#if LLDB_ENABLE_MTE
702 // Python's allocator (pymalloc) is not aware of Memory Tagging Extension
703 // (MTE) and crashes.
704 // https://bugs.python.org/issue43593
705 setenv("PYTHONMALLOC", "malloc", /*overwrite=*/true);
706#endif
707
708 // When the plugin is a separate shared library, the SWIG wrapper lives in
709 // the plugin library, so the path helper that redirects lookups back to
710 // liblldb is unnecessary.
711#if !LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS
712 HostInfo::SetSharedLibraryDirectoryHelper(
714#endif
715
716 // Bring the interpreter up before registering, so a Python that refuses to
717 // initialize leaves no plugin claiming eScriptLanguagePython behind.
718 // GetScriptInterpreterForLanguage then hands out ScriptInterpreterNone and
719 // the rest of lldb keeps working without scripting.
721 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
722 return;
723 }
724
730}
731
736
738 ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
739 uint16_t on_leave, FileSP in, FileSP out, FileSP err)
742 m_python_interpreter(py_interpreter) {
744 if ((on_entry & InitSession) == InitSession) {
745 if (!DoInitSession(on_entry, in, out, err)) {
746 // Don't teardown the session if we didn't init it.
747 m_teardown_session = false;
748 }
749 }
750}
751
753 m_GILState = PyGILState_Ensure();
755 "Ensured PyGILState. Previous state = {0}",
756 m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
757
758 // we need to save the thread state when we first start the command because
759 // we might decide to interrupt it while some action is taking place outside
760 // of Python (e.g. printing to screen, waiting for the network, ...) in that
761 // case, _PyThreadState_Current will be NULL - and we would be unable to set
762 // the asynchronous exception - not a desirable situation
763 m_python_interpreter->SetThreadState(PyThreadState_Get());
764 m_python_interpreter->IncrementLockCount();
765 return true;
766}
767
769 FileSP in, FileSP out,
770 FileSP err) {
772 return false;
773 return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
774}
775
778 "Releasing PyGILState. Returning to state = {0}",
779 m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
780 PyGILState_Release(m_GILState);
781 m_python_interpreter->DecrementLockCount();
782 return true;
783}
784
787 return false;
788 m_python_interpreter->LeaveSession();
789 return true;
790}
791
797
804 m_dictionary_name(m_debugger.GetInstanceName()),
807 m_command_thread_state(nullptr) {
808
809 m_dictionary_name.append("_dict");
810 StreamString run_string;
811 run_string.Printf("%s = dict()", m_dictionary_name.c_str());
812
814 RunSimpleString(run_string.GetData());
815
816 run_string.Clear();
817 run_string.Printf("run_one_line (%s, 'import copy, keyword, os, re, sys, "
818 "uuid, lldb, importlib')",
819 m_dictionary_name.c_str());
820 RunSimpleString(run_string.GetData());
821
822 // WARNING: temporary code that loads Cocoa formatters - this should be done
823 // on a per-platform basis rather than loading the whole set and letting the
824 // individual formatter classes exploit APIs to check whether they can/cannot
825 // do their task
826 run_string.Clear();
827 run_string.Printf(
828 "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",
829 m_dictionary_name.c_str());
830 RunSimpleString(run_string.GetData());
831 run_string.Clear();
832
833 run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "
834 "lldb.embedded_interpreter import run_python_interpreter; "
835 "from lldb.embedded_interpreter import run_one_line')",
836 m_dictionary_name.c_str());
837 RunSimpleString(run_string.GetData());
838 run_string.Clear();
839
840 // Configure pydoc (built-in module) to use the "plain" pager. The default one
841 // doesn't play nice with the statusline.
842 run_string.Printf("run_one_line (%s, 'import pydoc; pydoc.pager = "
843 "pydoc.plainpager')",
844 m_dictionary_name.c_str());
845 RunSimpleString(run_string.GetData());
846 run_string.Clear();
847
848 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64
849 "')",
850 m_dictionary_name.c_str(), m_debugger.GetID());
851 RunSimpleString(run_string.GetData());
852}
853
854/// A Python sys.stdout/stderr file backed by a pipe whose read end is drained
855/// by a reader thread that writes to the debugger's terminal under the output
856/// lock (Debugger::PrintAsync). Handing Python the raw terminal descriptor
857/// instead lets a script's print() race the statusline, which redraws on the
858/// event thread under that lock. Its cursor save/restore then rewinds over and
859/// eats the script's output.
861public:
862 static std::unique_ptr<SessionIORedirect> Create(lldb::user_id_t debugger_id,
863 bool is_stdout) {
864 Pipe pipe;
865 if (pipe.CreateNew().Fail())
866 return nullptr;
867
868 std::unique_ptr<SessionIORedirect> redirect(
869 new SessionIORedirect(debugger_id, is_stdout));
870
871#if defined(_WIN32)
872 lldb::file_t read_handle = pipe.GetReadNativeHandle();
874 std::unique_ptr<Connection> conn =
875 std::make_unique<ConnectionGenericFile>(read_handle, true);
876#else
877 std::unique_ptr<Connection> conn =
878 std::make_unique<ConnectionFileDescriptor>(
879 pipe.ReleaseReadFileDescriptor(), /*owns_fd=*/true);
880#endif
881 if (!conn->IsConnected())
882 return nullptr;
883
884 redirect->m_communication.SetConnection(std::move(conn));
885 redirect->m_communication.SetReadThreadBytesReceivedCallback(
886 ReadThreadBytesReceived, redirect.get());
887 if (!redirect->m_communication.StartReadThread())
888 return nullptr;
889 redirect->m_connected = true;
890
891 // The write end is owned here. Python only borrows its descriptor.
892 redirect->m_write_file_sp = std::make_shared<NativeFile>(
895 return redirect;
896 }
897
899 if (!m_connected)
900 return;
901 // Close the write end so the reader sees EOF and exits, then join it.
902 if (m_write_file_sp)
903 m_write_file_sp->Close();
904 m_communication.JoinReadThread();
905 m_communication.Disconnect();
906 }
907
908 int GetWriteDescriptor() const {
909 return m_write_file_sp ? m_write_file_sp->GetDescriptor()
911 }
912
913private:
914 SessionIORedirect(lldb::user_id_t debugger_id, bool is_stdout)
915 : m_debugger_id(debugger_id), m_is_stdout(is_stdout),
916 m_communication("lldb.ScriptInterpreterPython.io-redirect") {}
917
918 static void ReadThreadBytesReceived(void *baton, const void *src,
919 size_t src_len) {
920 if (!src || !src_len)
921 return;
922 auto *self = static_cast<SessionIORedirect *>(baton);
923 if (lldb::DebuggerSP debugger_sp =
924 Debugger::FindDebuggerWithID(self->m_debugger_id))
925 debugger_sp->PrintAsync(static_cast<const char *>(src), src_len,
926 self->m_is_stdout);
927 }
928
933 bool m_connected = false;
934};
935
937 // the session dictionary may hold objects with complex state which means
938 // that they may need to be torn down with some level of smarts and that, in
939 // turn, requires a valid thread state force Python to procure itself such a
940 // thread state, nuke the session dictionary and then release it for others
941 // to use and proceed with the rest of the shutdown
942 auto gil_state = PyGILState_Ensure();
943 m_session_dict.Reset();
944 PyGILState_Release(gil_state);
945}
946
948 bool interactive) {
949 const char *instructions = nullptr;
950
951 switch (m_active_io_handler) {
952 case eIOHandlerNone:
953 break;
955 instructions = R"(Enter your Python command(s). Type 'DONE' to end.
956def function (frame, bp_loc, internal_dict):
957 """frame: the lldb.SBFrame for the location at which you stopped
958 bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
959 internal_dict: an LLDB support object not to be used"""
960)";
961 break;
963 instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
964 break;
965 }
966
967 if (instructions && interactive) {
968 if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {
969 LockedStreamFile locked_stream = stream_sp->Lock();
970 locked_stream.PutCString(instructions);
971 locked_stream.Flush();
972 }
973 }
974}
975
977 std::string &data) {
978 io_handler.SetIsDone(true);
979 bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();
980
981 switch (m_active_io_handler) {
982 case eIOHandlerNone:
983 break;
985 std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
986 (std::vector<std::reference_wrapper<BreakpointOptions>> *)
987 io_handler.GetUserData();
988 for (BreakpointOptions &bp_options : *bp_options_vec) {
989
990 auto data_up = std::make_unique<CommandDataPython>();
991 if (!data_up)
992 break;
993 data_up->user_source.SplitIntoLines(data);
994
995 if (GenerateBreakpointCommandCallbackData(data_up->user_source,
996 data_up->script_source,
997 /*has_extra_args=*/false,
998 /*is_callback=*/false)
999 .Success()) {
1000 auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
1001 std::move(data_up));
1002 bp_options.SetCallback(
1004 } else if (!batch_mode) {
1005 if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
1006 LockedStreamFile locked_stream = error_sp->Lock();
1007 locked_stream.Printf("Warning: No command attached to breakpoint.\n");
1008 }
1009 }
1010 }
1012 } break;
1013 case eIOHandlerWatchpoint: {
1014 WatchpointOptions *wp_options =
1015 (WatchpointOptions *)io_handler.GetUserData();
1016 auto data_up = std::make_unique<WatchpointOptions::CommandData>();
1017 data_up->user_source.SplitIntoLines(data);
1018
1019 if (GenerateWatchpointCommandCallbackData(data_up->user_source,
1020 data_up->script_source,
1021 /*is_callback=*/false)) {
1022 auto baton_sp =
1023 std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
1024 wp_options->SetCallback(
1026 } else if (!batch_mode) {
1027 if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
1028 LockedStreamFile locked_stream = error_sp->Lock();
1029 locked_stream.Printf("Warning: No command attached to breakpoint.\n");
1030 }
1031 }
1033 } break;
1034 }
1035}
1036
1039 return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
1040}
1041
1043 Log *log = GetLog(LLDBLog::Script);
1044 if (log)
1045 log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");
1046
1047 // Unset the LLDB global variables.
1048 RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
1049 "= None; lldb.thread = None; lldb.frame = None");
1050
1051 // checking that we have a valid thread state - since we use our own
1052 // threading and locking in some (rare) cases during cleanup Python may end
1053 // up believing we have no thread state and PyImport_AddModule will crash if
1054 // that is the case - since that seems to only happen when destroying the
1055 // SBDebugger, we can make do without clearing up stdout and stderr
1056 if (PyThreadState_GetDict()) {
1057 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1058 if (sys_module_dict.IsValid()) {
1059 // Flush the pipe-backed wrappers while they are still sys.stdout/stderr.
1060 // Line buffering already flushes on each newline, but a trailing
1061 // unterminated line would otherwise be stranded (and later flushed into
1062 // a closed descriptor) once we close the pipe write end below.
1063 auto flush_redirect = [&](const char *py_name,
1064 std::unique_ptr<SessionIORedirect> &redirect) {
1065 if (!redirect)
1066 return;
1067 PythonObject file =
1068 sys_module_dict.GetItemForKey(PythonString(py_name));
1069 if (!file.IsValid())
1070 return;
1071 if (llvm::Expected<PythonObject> result = file.CallMethod("flush"))
1072 (void)result;
1073 else
1074 llvm::consumeError(result.takeError());
1075 };
1076 flush_redirect("stdout", m_stdout_redirect);
1077 flush_redirect("stderr", m_stderr_redirect);
1078
1079 if (m_saved_stdin.IsValid()) {
1080 sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
1082 }
1083 if (m_saved_stdout.IsValid()) {
1084 sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
1085 m_saved_stdout.Reset();
1086 }
1087 if (m_saved_stderr.IsValid()) {
1088 sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
1089 m_saved_stderr.Reset();
1090 }
1091 }
1092 }
1093
1094 // Tear down the pipe redirects (closes each write end and joins its reader).
1095 // The wrappers were flushed above, so nothing buffered is lost.
1096 m_stdout_redirect.reset();
1098
1099 m_session_is_active = false;
1100}
1101
1103 const char *py_name, PythonObject &save_file, const char *mode,
1104 File &file) {
1105 const bool is_stdout = ::strcmp(py_name, "stdout") == 0;
1106 if (!is_stdout && ::strcmp(py_name, "stderr") != 0)
1107 return false;
1108
1109 // The statusline is the only writer that races Python's terminal output.
1110 // When it isn't drawing there is nothing to serialize against, so keep the
1111 // normal wrapping and skip the reader thread and pipe.
1113 return false;
1114
1115 // Only the debugger's own terminal races the statusline. A redirect to a
1116 // pipe or user file (a different descriptor) is wrapped normally.
1117 lldb::FileSP debugger_file =
1119 int fd = file.GetDescriptor();
1120 if (!debugger_file || fd == File::kInvalidDescriptor ||
1121 fd != debugger_file->GetDescriptor())
1122 return false;
1123
1124 std::unique_ptr<SessionIORedirect> &redirect =
1126 redirect = SessionIORedirect::Create(m_debugger.GetID(), is_stdout);
1127 if (!redirect)
1128 return false;
1129
1130 // Line-buffer the wrapper so each print() reaches the reader (and the
1131 // terminal) promptly: the pipe descriptor is not a tty, so the default
1132 // buffering would hold output back until the buffer filled.
1133 PyObject *pipe_file = PyFile_FromFd(
1134 PythonFile::TranslateFdToPython(redirect->GetWriteDescriptor()), nullptr,
1135 mode, /*buffering=*/1,
1136 /*encoding=*/nullptr, /*errors=*/"ignore",
1137 /*newline=*/nullptr,
1138 /*closefd=*/0);
1139 if (!pipe_file) {
1140 // Fall back to the raw descriptor. That reopens the statusline race, so
1141 // leave a breadcrumb rather than failing silently.
1143 "failed to wrap sys.{0} on a synchronized pipe; falling back to "
1144 "the unsynchronized terminal descriptor",
1145 py_name);
1146 PyErr_Clear();
1147 redirect.reset();
1148 return false;
1149 }
1150
1151 PythonObject new_file(PyRefType::Owned, pipe_file);
1152 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1153 save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
1154 sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
1155 return true;
1156}
1157
1159 const char *py_name,
1160 PythonObject &save_file,
1161 const char *mode,
1162 bool serialize_terminal_output) {
1163 if (!file_sp || !*file_sp) {
1164 save_file.Reset();
1165 return false;
1166 }
1167 File &file = *file_sp;
1168
1169 // When stdout/stderr point at the debugger's own terminal, route Python's
1170 // output through a pipe drained under the output lock so a script's print()
1171 // cannot race the statusline. Any other target keeps the normal wrapping.
1172 if (serialize_terminal_output &&
1173 RedirectTerminalHandleThroughLock(py_name, save_file, mode, file))
1174 return true;
1175
1176 // Flush the file before giving it to python to avoid interleaved output.
1177 file.Flush();
1178
1179 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1180
1181 auto new_file = PythonFile::FromFile(file, mode);
1182 if (!new_file) {
1183 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), new_file.takeError(),
1184 "ScriptInterpreterPythonImpl::SetStdHandle failed to wrap "
1185 "sys.{1}: {0}",
1186 py_name);
1187 return false;
1188 }
1189
1190 save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
1192 sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());
1193 return true;
1194}
1195
1196bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
1197 FileSP in_sp, FileSP out_sp,
1198 FileSP err_sp) {
1199 // If we have already entered the session, without having officially 'left'
1200 // it, then there is no need to 'enter' it again.
1201 Log *log = GetLog(LLDBLog::Script);
1202 if (m_session_is_active) {
1203 LLDB_LOGF(
1204 log,
1205 "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
1206 ") session is already active, returning without doing anything",
1207 on_entry_flags);
1208 return false;
1209 }
1210
1211 LLDB_LOGF(
1212 log,
1213 "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",
1214 on_entry_flags);
1215
1216 m_session_is_active = true;
1217
1218 StreamString run_string;
1219
1220 if (on_entry_flags & Locker::InitGlobals) {
1221 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
1223 run_string.Printf(
1224 "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
1225 m_debugger.GetID());
1226 run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");
1227 run_string.PutCString("; lldb.process = lldb.target.GetProcess()");
1228 run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
1229 run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
1230 run_string.PutCString("')");
1231 } else {
1232 // If we aren't initing the globals, we should still always set the
1233 // debugger (since that is always unique.)
1234 run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
1235 m_dictionary_name.c_str(), m_debugger.GetID());
1236 run_string.Printf(
1237 "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
1238 m_debugger.GetID());
1239 run_string.PutCString("')");
1240 }
1241
1242 RunSimpleString(run_string.GetData());
1243 run_string.Clear();
1244
1245 PythonDictionary &sys_module_dict = GetSysModuleDictionary();
1246 if (sys_module_dict.IsValid()) {
1247 lldb::FileSP top_in_sp;
1248 lldb::LockableStreamFileSP top_out_sp, top_err_sp;
1249 if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
1250 m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
1251 top_err_sp);
1252
1253 if (on_entry_flags & Locker::NoSTDIN) {
1254 m_saved_stdin.Reset();
1255 } else {
1256 if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r",
1257 /*serialize_terminal_output=*/false)) {
1258 if (top_in_sp)
1259 SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r",
1260 /*serialize_terminal_output=*/false);
1261 }
1262 }
1263
1264 // Serialize terminal output for every session except those that opt out
1265 // with NoOutputRedirect (see the flag for why).
1266 const bool serialize_terminal_output =
1267 !(on_entry_flags & Locker::NoOutputRedirect);
1268
1269 if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w",
1270 serialize_terminal_output)) {
1271 if (top_out_sp)
1272 SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,
1273 "w", serialize_terminal_output);
1274 }
1275
1276 if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w",
1277 serialize_terminal_output)) {
1278 if (top_err_sp)
1279 SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,
1280 "w", serialize_terminal_output);
1281 }
1282 }
1283
1284 if (PyErr_Occurred())
1285 PyErr_Clear();
1286
1287 return true;
1288}
1289
1291 if (!m_main_module.IsValid())
1293 return m_main_module;
1294}
1295
1297 if (m_session_dict.IsValid())
1298 return m_session_dict;
1299
1300 PythonObject &main_module = GetMainModule();
1301 if (!main_module.IsValid())
1302 return m_session_dict;
1303
1305 PyModule_GetDict(main_module.get()));
1306 if (!main_dict.IsValid())
1307 return m_session_dict;
1308
1316 return m_sys_module_dict;
1319 return m_sys_module_dict;
1320}
1321
1322llvm::Expected<unsigned>
1324 const llvm::StringRef &callable_name) {
1325 if (callable_name.empty()) {
1326 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1327 "called with empty callable name.");
1328 }
1329 Locker py_lock(this,
1334 callable_name, dict);
1335 if (!pfunc.IsAllocated()) {
1336 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1337 "can't find callable: %s",
1338 callable_name.str().c_str());
1339 }
1340 llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
1341 if (!arg_info) {
1342 // `-f` may point at a builtin, unlike other GetArgInfo() callers.
1343 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), arg_info.takeError(),
1344 "GetArgInfo failed for callable {1}, falling back to "
1345 "inspect.signature: {0}",
1346 callable_name);
1348 }
1349 if (!arg_info)
1350 return arg_info.takeError();
1351 return arg_info.get().max_positional_args;
1352}
1353
1354static std::string GenerateUniqueName(const char *base_name_wanted,
1355 uint32_t &functions_counter,
1356 const void *name_token = nullptr) {
1357 StreamString sstr;
1358
1359 if (!base_name_wanted)
1360 return std::string();
1361
1362 if (!name_token)
1363 sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
1364 else
1365 sstr.Printf("%s_%p", base_name_wanted, name_token);
1366
1367 return std::string(sstr.GetString());
1368}
1369
1372 return true;
1373
1375 PyImport_AddModule("lldb.embedded_interpreter"));
1376 if (!module.IsValid())
1377 return false;
1378
1380 PyModule_GetDict(module.get()));
1381 if (!module_dict.IsValid())
1382 return false;
1383
1385 module_dict.GetItemForKey(PythonString("run_one_line"));
1387 module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
1388 return m_run_one_line_function.IsValid();
1389}
1390
1392 llvm::StringRef command, CommandReturnObject *result,
1393 const ExecuteScriptOptions &options) {
1394 std::string command_str = command.str();
1395
1396 if (!m_valid_session)
1397 return false;
1398
1399 if (!command.empty()) {
1400 // We want to call run_one_line, passing in the dictionary and the command
1401 // string. We cannot do this through RunSimpleString here because the
1402 // command string may contain escaped characters, and putting it inside
1403 // another string to pass to RunSimpleString messes up the escaping. So
1404 // we use the following more complicated method to pass the command string
1405 // directly down to Python.
1406 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1407 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1408 options.GetEnableIO(), m_debugger, result);
1409 if (!io_redirect_or_error) {
1410 if (result)
1411 result->AppendErrorWithFormatv(
1412 "failed to redirect I/O: {0}\n",
1413 llvm::fmt_consume(io_redirect_or_error.takeError()));
1414 else
1415 llvm::consumeError(io_redirect_or_error.takeError());
1416 return false;
1417 }
1418
1419 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1420
1421 bool success = false;
1422 {
1423 // WARNING! It's imperative that this RAII scope be as tight as
1424 // possible. In particular, the scope must end *before* we try to join
1425 // the read thread. The reason for this is that a pre-requisite for
1426 // joining the read thread is that we close the write handle (to break
1427 // the pipe and cause it to wake up and exit). But acquiring the GIL as
1428 // below will redirect Python's stdio to use this same handle. If we
1429 // close the handle while Python is still using it, bad things will
1430 // happen.
1431 Locker locker(
1432 this,
1434 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1435 ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
1437 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1438 io_redirect.GetErrorFile());
1439
1440 // Find the correct script interpreter dictionary in the main module.
1441 PythonDictionary &session_dict = GetSessionDictionary();
1442 if (session_dict.IsValid()) {
1444 if (PyCallable_Check(m_run_one_line_function.get())) {
1445 PythonObject pargs(
1447 Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
1448 if (pargs.IsValid()) {
1449 PythonObject return_value(
1451 PyObject_CallObject(m_run_one_line_function.get(),
1452 pargs.get()));
1453 if (return_value.IsValid())
1454 success = true;
1455 else if (options.GetMaskoutErrors() && PyErr_Occurred()) {
1456 PyErr_Print();
1457 PyErr_Clear();
1458 }
1459 }
1460 }
1461 }
1462 }
1463
1464 io_redirect.Flush();
1465 }
1466
1467 if (success)
1468 return true;
1469
1470 // The one-liner failed. Append the error message.
1471 if (result) {
1472 result->AppendErrorWithFormat("python failed attempting to evaluate '%s'",
1473 command_str.c_str());
1474 }
1475 return false;
1476 }
1477
1478 if (result)
1479 result->AppendError("empty command passed to python\n");
1480 return false;
1481}
1482
1485
1486 Debugger &debugger = m_debugger;
1487
1488 // At the moment, the only time the debugger does not have an input file
1489 // handle is when this is called directly from Python, in which case it is
1490 // both dangerous and unnecessary (not to mention confusing) to try to embed
1491 // a running interpreter loop inside the already running Python interpreter
1492 // loop, so we won't do it.
1493
1494 if (!debugger.GetInputFile().IsValid())
1495 return;
1496
1497 IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
1498 if (io_handler_sp) {
1499 debugger.RunIOHandlerAsync(io_handler_sp);
1500 }
1501}
1502
1504#if LLDB_USE_PYTHON_SET_INTERRUPT
1505 // If the interpreter isn't evaluating any Python at the moment then return
1506 // false to signal that this function didn't handle the interrupt and the
1507 // next component should try handling it.
1508 if (!IsExecutingPython())
1509 return false;
1510
1511 // Tell Python that it should pretend to have received a SIGINT.
1512 PyErr_SetInterrupt();
1513 // PyErr_SetInterrupt has no way to return an error so we can only pretend the
1514 // signal got successfully handled and return true.
1515 // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but
1516 // the error handling is limited to checking the arguments which would be
1517 // just our (hardcoded) input signal code SIGINT, so that's not useful at all.
1518 return true;
1519#else
1520 Log *log = GetLog(LLDBLog::Script);
1521
1522 if (IsExecutingPython()) {
1523 PyThreadState *state = PyThreadState_Get();
1524 if (!state)
1525 state = GetThreadState();
1526 if (state) {
1527 long tid = PyThread_get_thread_ident();
1528 PyThreadState_Swap(state);
1529 int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
1530 LLDB_LOGF(log,
1531 "ScriptInterpreterPythonImpl::Interrupt() sending "
1532 "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
1533 tid, num_threads);
1534 return true;
1535 }
1536 }
1537 LLDB_LOGF(log,
1538 "ScriptInterpreterPythonImpl::Interrupt() python code not running, "
1539 "can't interrupt");
1540 return false;
1541#endif
1542}
1543
1545 llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
1546 void *ret_value, const ExecuteScriptOptions &options) {
1547
1548 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1549 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1550 options.GetEnableIO(), m_debugger, /*result=*/nullptr);
1551
1552 if (!io_redirect_or_error) {
1553 llvm::consumeError(io_redirect_or_error.takeError());
1554 return false;
1555 }
1556
1557 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1558
1559 Locker locker(this,
1561 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1564 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1565 io_redirect.GetErrorFile());
1566
1567 PythonModule &main_module = GetMainModule();
1568 PythonDictionary globals = main_module.GetDictionary();
1569
1571 if (!locals.IsValid())
1572 locals = unwrapIgnoringErrors(
1574 if (!locals.IsValid())
1575 locals = globals;
1576
1577 Expected<PythonObject> maybe_py_return =
1578 runStringOneLine(in_string, globals, locals);
1579
1580 if (!maybe_py_return) {
1581 llvm::handleAllErrors(
1582 maybe_py_return.takeError(),
1583 [&](PythonException &E) {
1584 E.Restore();
1585 if (options.GetMaskoutErrors()) {
1586 if (E.Matches(PyExc_SyntaxError)) {
1587 PyErr_Print();
1588 }
1589 PyErr_Clear();
1590 }
1591 },
1592 [](const llvm::ErrorInfoBase &E) {});
1593 return false;
1594 }
1595
1596 PythonObject py_return = std::move(maybe_py_return.get());
1597 assert(py_return.IsValid());
1598
1599 switch (return_type) {
1600 case eScriptReturnTypeCharPtr: // "char *"
1601 {
1602 const char format[3] = "s#";
1603 return PyArg_Parse(py_return.get(), format, (char **)ret_value);
1604 }
1605 case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
1606 // Py_None
1607 {
1608 const char format[3] = "z";
1609 return PyArg_Parse(py_return.get(), format, (char **)ret_value);
1610 }
1611 case eScriptReturnTypeBool: {
1612 const char format[2] = "b";
1613 return PyArg_Parse(py_return.get(), format, (bool *)ret_value);
1614 }
1615 case eScriptReturnTypeShortInt: {
1616 const char format[2] = "h";
1617 return PyArg_Parse(py_return.get(), format, (short *)ret_value);
1618 }
1619 case eScriptReturnTypeShortIntUnsigned: {
1620 const char format[2] = "H";
1621 return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
1622 }
1623 case eScriptReturnTypeInt: {
1624 const char format[2] = "i";
1625 return PyArg_Parse(py_return.get(), format, (int *)ret_value);
1626 }
1627 case eScriptReturnTypeIntUnsigned: {
1628 const char format[2] = "I";
1629 return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
1630 }
1631 case eScriptReturnTypeLongInt: {
1632 const char format[2] = "l";
1633 return PyArg_Parse(py_return.get(), format, (long *)ret_value);
1634 }
1635 case eScriptReturnTypeLongIntUnsigned: {
1636 const char format[2] = "k";
1637 return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
1638 }
1639 case eScriptReturnTypeLongLong: {
1640 const char format[2] = "L";
1641 return PyArg_Parse(py_return.get(), format, (long long *)ret_value);
1642 }
1643 case eScriptReturnTypeLongLongUnsigned: {
1644 const char format[2] = "K";
1645 return PyArg_Parse(py_return.get(), format,
1646 (unsigned long long *)ret_value);
1647 }
1648 case eScriptReturnTypeFloat: {
1649 const char format[2] = "f";
1650 return PyArg_Parse(py_return.get(), format, (float *)ret_value);
1651 }
1652 case eScriptReturnTypeDouble: {
1653 const char format[2] = "d";
1654 return PyArg_Parse(py_return.get(), format, (double *)ret_value);
1655 }
1656 case eScriptReturnTypeChar: {
1657 const char format[2] = "c";
1658 return PyArg_Parse(py_return.get(), format, (char *)ret_value);
1659 }
1660 case eScriptReturnTypeOpaqueObject: {
1661 *((PyObject **)ret_value) = py_return.release();
1662 return true;
1664 }
1665 llvm_unreachable("Fully covered switch!");
1666}
1667
1669 const char *in_string, const ExecuteScriptOptions &options) {
1670
1671 if (in_string == nullptr)
1672 return Status();
1673
1674 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
1675 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
1676 options.GetEnableIO(), m_debugger, /*result=*/nullptr);
1677
1678 if (!io_redirect_or_error)
1679 return Status::FromError(io_redirect_or_error.takeError());
1680
1681 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
1682
1683 Locker locker(this,
1685 (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
1688 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
1689 io_redirect.GetErrorFile());
1690
1691 PythonModule &main_module = GetMainModule();
1692 PythonDictionary globals = main_module.GetDictionary();
1693
1694 PythonDictionary locals = GetSessionDictionary();
1695 if (!locals.IsValid())
1696 locals = unwrapIgnoringErrors(
1698 if (!locals.IsValid())
1699 locals = globals;
1700
1701 Expected<PythonObject> return_value =
1702 runStringMultiLine(in_string, globals, locals);
1703
1704 if (!return_value) {
1705 llvm::Error error =
1706 llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {
1707 llvm::Error error = llvm::createStringError(
1708 llvm::inconvertibleErrorCode(), E.ReadBacktrace());
1709 if (!options.GetMaskoutErrors())
1710 E.Restore();
1711 return error;
1712 });
1713 return Status::FromError(std::move(error));
1715
1716 return Status();
1717}
1718
1720 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
1721 CommandReturnObject &result) {
1723 m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
1724 " ", *this, &bp_options_vec);
1725}
1726
1728 WatchpointOptions *wp_options, CommandReturnObject &result) {
1730 m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
1731 " ", *this, wp_options);
1732}
1733
1735 BreakpointOptions &bp_options, const char *function_name,
1736 StructuredData::ObjectSP extra_args_sp) {
1737 Status error;
1738 // For now just cons up a oneliner that calls the provided function.
1739 std::string function_signature = function_name;
1740
1741 llvm::Expected<unsigned> maybe_args =
1743 if (!maybe_args) {
1745 "could not get num args: %s",
1746 llvm::toString(maybe_args.takeError()).c_str());
1747 return error;
1748 }
1749 size_t max_args = *maybe_args;
1750
1751 bool uses_extra_args = false;
1752 if (max_args >= 4) {
1753 uses_extra_args = true;
1754 function_signature += "(frame, bp_loc, extra_args, internal_dict)";
1755 } else if (max_args >= 3) {
1756 if (extra_args_sp) {
1758 "cannot pass extra_args to a three argument callback");
1759 return error;
1760 }
1761 uses_extra_args = false;
1762 function_signature += "(frame, bp_loc, internal_dict)";
1763 } else {
1764 error = Status::FromErrorStringWithFormat("expected 3 or 4 argument "
1765 "function, %s can only take %zu",
1766 function_name, max_args);
1767 return error;
1768 }
1769
1770 SetBreakpointCommandCallback(bp_options, function_signature.c_str(),
1771 extra_args_sp, uses_extra_args,
1772 /*is_callback=*/true);
1773 return error;
1774}
1775
1777 BreakpointOptions &bp_options,
1778 std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
1779 Status error;
1780 error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
1781 cmd_data_up->script_source,
1782 /*has_extra_args=*/false,
1783 /*is_callback=*/false);
1784 if (error.Fail()) {
1785 return error;
1786 }
1787 auto baton_sp =
1788 std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
1795 BreakpointOptions &bp_options, const char *command_body_text,
1796 bool is_callback) {
1797 return SetBreakpointCommandCallback(bp_options, command_body_text, {},
1798 /*uses_extra_args=*/false, is_callback);
1799}
1800
1801// Set a Python one-liner as the callback for the breakpoint.
1803 BreakpointOptions &bp_options, const char *command_body_text,
1804 StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,
1805 bool is_callback) {
1806 auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
1807 // Split the command_body_text into lines, and pass that to
1808 // GenerateBreakpointCommandCallbackData. That will wrap the body in an
1809 // auto-generated function, and return the function name in script_source.
1810 // That is what the callback will actually invoke.
1811
1812 data_up->user_source.SplitIntoLines(command_body_text);
1814 data_up->user_source, data_up->script_source, uses_extra_args,
1815 is_callback);
1816 if (error.Success()) {
1817 auto baton_sp =
1818 std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
1819 bp_options.SetCallback(
1821 return error;
1823 return error;
1824}
1825
1826// Set a Python one-liner as the callback for the watchpoint.
1828 WatchpointOptions *wp_options, const char *user_input, bool is_callback) {
1829 auto data_up = std::make_unique<WatchpointOptions::CommandData>();
1830
1831 // It's necessary to set both user_source and script_source to the oneliner.
1832 // The former is used to generate callback description (as in watchpoint
1833 // command list) while the latter is used for Python to interpret during the
1834 // actual callback.
1835
1836 data_up->user_source.AppendString(user_input);
1837 data_up->script_source.assign(user_input);
1838
1840 data_up->user_source, data_up->script_source, is_callback)) {
1841 auto baton_sp =
1842 std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
1843 wp_options->SetCallback(
1845 }
1846}
1847
1849 StringList &function_def) {
1850 // Convert StringList to one long, newline delimited, const char *.
1851 std::string function_def_string(function_def.CopyList());
1852 LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n{0}\n",
1853 function_def_string.c_str());
1854
1856 function_def_string.c_str(), ExecuteScriptOptions().SetEnableIO(false));
1857 return error;
1858}
1859
1861 const StringList &input,
1862 bool is_callback) {
1863 Status error;
1864 int num_lines = input.GetSize();
1865 if (num_lines == 0) {
1866 error = Status::FromErrorString("No input data.");
1867 return error;
1868 }
1869
1870 if (!signature || *signature == 0) {
1871 error = Status::FromErrorString("No output function name.");
1872 return error;
1873 }
1874
1875 StreamString sstr;
1876 StringList auto_generated_function;
1877 auto_generated_function.AppendString(signature);
1878 auto_generated_function.AppendString(
1879 " global_dict = globals()"); // Grab the global dictionary
1880 auto_generated_function.AppendString(
1881 " new_keys = internal_dict.keys()"); // Make a list of keys in the
1882 // session dict
1883 auto_generated_function.AppendString(
1884 " old_keys = global_dict.keys()"); // Save list of keys in global dict
1885 auto_generated_function.AppendString(
1886 " global_dict.update(internal_dict)"); // Add the session dictionary
1887 // to the global dictionary.
1888
1889 if (is_callback) {
1890 // If the user input is a callback to a python function, make sure the input
1891 // is only 1 line, otherwise appending the user input would break the
1892 // generated wrapped function
1893 if (num_lines == 1) {
1894 sstr.Clear();
1895 sstr.Printf(" __return_val = %s", input.GetStringAtIndex(0));
1896 auto_generated_function.AppendString(sstr.GetData());
1897 } else {
1899 "ScriptInterpreterPythonImpl::GenerateFunction(is_callback="
1900 "true) = ERROR: python function is multiline.");
1901 }
1902 } else {
1903 auto_generated_function.AppendString(
1904 " __return_val = None"); // Initialize user callback return value.
1905 auto_generated_function.AppendString(
1906 " def __user_code():"); // Create a nested function that will wrap
1907 // the user input. This is necessary to
1908 // capture the return value of the user input
1909 // and prevent early returns.
1910 for (int i = 0; i < num_lines; ++i) {
1911 sstr.Clear();
1912 sstr.Printf(" %s", input.GetStringAtIndex(i));
1913 auto_generated_function.AppendString(sstr.GetData());
1914 }
1915 auto_generated_function.AppendString(
1916 " __return_val = __user_code()"); // Call user code and capture
1917 // return value
1918 }
1919 auto_generated_function.AppendString(
1920 " for key in new_keys:"); // Iterate over all the keys from session
1921 // dict
1922 auto_generated_function.AppendString(
1923 " if key in old_keys:"); // If key was originally in
1924 // global dict
1925 auto_generated_function.AppendString(
1926 " internal_dict[key] = global_dict[key]"); // Update it
1927 auto_generated_function.AppendString(
1928 " elif key in global_dict:"); // Then if it is still in the
1929 // global dict
1930 auto_generated_function.AppendString(
1931 " del global_dict[key]"); // remove key/value from the
1932 // global dict
1933 auto_generated_function.AppendString(
1934 " return __return_val"); // Return the user callback return value.
1935
1936 // Verify that the results are valid Python.
1938
1939 return error;
1940}
1941
1943 StringList &user_input, std::string &output, const void *name_token) {
1944 static uint32_t num_created_functions = 0;
1945 user_input.RemoveBlankLines();
1946 StreamString sstr;
1947
1948 // Check to see if we have any data; if not, just return.
1949 if (user_input.GetSize() == 0)
1950 return false;
1951
1952 // Take what the user wrote, wrap it all up inside one big auto-generated
1953 // Python function, passing in the ValueObject as parameter to the function.
1954
1955 std::string auto_generated_function_name(
1956 GenerateUniqueName("lldb_autogen_python_type_print_func",
1957 num_created_functions, name_token));
1958 sstr.Printf("def %s (valobj, internal_dict):",
1959 auto_generated_function_name.c_str());
1960
1961 if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
1962 .Success())
1963 return false;
1964
1965 // Store the name of the auto-generated function to be called.
1966 output.assign(auto_generated_function_name);
1967 return true;
1968}
1969
1971 StringList &user_input, std::string &output) {
1972 static uint32_t num_created_functions = 0;
1973 user_input.RemoveBlankLines();
1974 StreamString sstr;
1975
1976 // Check to see if we have any data; if not, just return.
1977 if (user_input.GetSize() == 0)
1978 return false;
1979
1980 std::string auto_generated_function_name(GenerateUniqueName(
1981 "lldb_autogen_python_cmd_alias_func", num_created_functions));
1982
1983 sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",
1984 auto_generated_function_name.c_str());
1985
1986 if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
1987 .Success())
1988 return false;
1989
1990 // Store the name of the auto-generated function to be called.
1991 output.assign(auto_generated_function_name);
1992 return true;
1993}
1994
1996 StringList &user_input, std::string &output, const void *name_token) {
1997 static uint32_t num_created_classes = 0;
1998 user_input.RemoveBlankLines();
1999 int num_lines = user_input.GetSize();
2000 StreamString sstr;
2001
2002 // Check to see if we have any data; if not, just return.
2003 if (user_input.GetSize() == 0)
2004 return false;
2005
2006 // Wrap all user input into a Python class
2007
2008 std::string auto_generated_class_name(GenerateUniqueName(
2009 "lldb_autogen_python_type_synth_class", num_created_classes, name_token));
2010
2011 StringList auto_generated_class;
2012
2013 // Create the function name & definition string.
2014
2015 sstr.Printf("class %s:", auto_generated_class_name.c_str());
2016 auto_generated_class.AppendString(sstr.GetString());
2017
2018 // Wrap everything up inside the class, increasing the indentation. we don't
2019 // need to play any fancy indentation tricks here because there is no
2020 // surrounding code whose indentation we need to honor
2021 for (int i = 0; i < num_lines; ++i) {
2022 sstr.Clear();
2023 sstr.Printf(" %s", user_input.GetStringAtIndex(i));
2024 auto_generated_class.AppendString(sstr.GetString());
2025 }
2026
2027 // Verify that the results are valid Python. (even though the method is
2028 // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
2029 // (TODO: rename that method to ExportDefinitionToInterpreter)
2030 if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
2031 return false;
2032
2033 // Store the name of the auto-generated class
2034
2035 output.assign(auto_generated_class_name);
2036 return true;
2037}
2038
2041 return std::make_unique<ScriptedProcessPythonInterface>(*this);
2042}
2043
2046 return std::make_shared<ScriptedHookPythonInterface>(*this);
2047}
2048
2051 return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
2052}
2053
2056 return std::make_shared<ScriptedStackFrameRecognizerPythonInterface>(*this);
2057}
2058
2061 return std::make_shared<ScriptedCommandPythonInterface>(*this);
2062}
2063
2066 return std::make_shared<ScriptedStringSummaryPythonInterface>(*this);
2067}
2068
2071 return std::make_shared<ScriptedSyntheticChildrenPythonInterface>(*this);
2072}
2073
2076 return std::make_shared<ScriptedThreadPythonInterface>(*this);
2077}
2078
2081 return std::make_shared<ScriptedFramePythonInterface>(*this);
2082}
2083
2086 return std::make_shared<ScriptedFrameProviderPythonInterface>(*this);
2087}
2088
2091 return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
2092}
2093
2096 return std::make_shared<OperatingSystemPythonInterface>(*this);
2097}
2098
2101 ScriptObject obj) {
2102 void *ptr = const_cast<void *>(obj.GetPointer());
2104 PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));
2105 if (!py_obj.IsValid() || py_obj.IsNone())
2106 return {};
2107 return py_obj.CreateStructuredObject();
2108}
2109
2113 if (!FileSystem::Instance().Exists(file_spec)) {
2114 error = Status::FromErrorString("no such file");
2115 return StructuredData::ObjectSP();
2116 }
2117
2118 StructuredData::ObjectSP module_sp;
2119
2120 LoadScriptOptions load_script_options =
2121 LoadScriptOptions().SetInitSession(true).SetSilent(false);
2122 if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
2123 error, &module_sp))
2124 return module_sp;
2125
2126 return StructuredData::ObjectSP();
2127}
2128
2130 StructuredData::ObjectSP plugin_module_sp, Target *target,
2131 const char *setting_name, lldb_private::Status &error) {
2132 if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
2134 StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
2135 if (!generic)
2137
2138 Locker py_lock(this,
2140 TargetSP target_sp(target->shared_from_this());
2141
2142 auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
2143 generic->GetValue(), setting_name, target_sp);
2144
2145 if (!setting)
2147
2148 PythonDictionary py_dict =
2150
2151 if (!py_dict)
2158 const char *oneliner, std::string &output, const void *name_token) {
2160 input.SplitIntoLines(oneliner, strlen(oneliner));
2161 return GenerateTypeScriptFunction(input, output, name_token);
2162}
2163
2165 const char *oneliner, std::string &output, const void *name_token) {
2167 input.SplitIntoLines(oneliner, strlen(oneliner));
2168 return GenerateTypeSynthClass(input, output, name_token);
2169}
2170
2172 StringList &user_input, std::string &output, bool has_extra_args,
2173 bool is_callback) {
2174 static uint32_t num_created_functions = 0;
2175 user_input.RemoveBlankLines();
2176 StreamString sstr;
2177 Status error;
2178 if (user_input.GetSize() == 0) {
2179 error = Status::FromErrorString("No input data.");
2180 return error;
2181 }
2182
2183 std::string auto_generated_function_name(GenerateUniqueName(
2184 "lldb_autogen_python_bp_callback_func_", num_created_functions));
2185 if (has_extra_args)
2186 sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
2187 auto_generated_function_name.c_str());
2188 else
2189 sstr.Printf("def %s (frame, bp_loc, internal_dict):",
2190 auto_generated_function_name.c_str());
2191
2192 error = GenerateFunction(sstr.GetData(), user_input, is_callback);
2193 if (!error.Success())
2194 return error;
2195
2196 // Store the name of the auto-generated function to be called.
2197 output.assign(auto_generated_function_name);
2198 return error;
2199}
2200
2202 StringList &user_input, std::string &output, bool is_callback) {
2203 static uint32_t num_created_functions = 0;
2204 user_input.RemoveBlankLines();
2205 StreamString sstr;
2206
2207 if (user_input.GetSize() == 0)
2208 return false;
2209
2210 std::string auto_generated_function_name(GenerateUniqueName(
2211 "lldb_autogen_python_wp_callback_func_", num_created_functions));
2212 sstr.Printf("def %s (frame, wp, internal_dict):",
2213 auto_generated_function_name.c_str());
2214
2215 if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())
2216 return false;
2217
2218 // Store the name of the auto-generated function to be called.
2219 output.assign(auto_generated_function_name);
2220 return true;
2221}
2222
2224 const char *python_function_name, lldb::ValueObjectSP valobj,
2225 StructuredData::ObjectSP &callee_wrapper_sp,
2226 const TypeSummaryOptions &options, std::string &retval) {
2227
2229
2230 if (!valobj.get()) {
2231 retval.assign("<no object>");
2232 return false;
2233 }
2234
2235 void *old_callee = nullptr;
2236 StructuredData::Generic *generic = nullptr;
2237 if (callee_wrapper_sp) {
2238 generic = callee_wrapper_sp->GetAsGeneric();
2239 if (generic)
2240 old_callee = generic->GetValue();
2241 }
2242 void *new_callee = old_callee;
2243
2244 bool ret_val;
2245 if (python_function_name && *python_function_name) {
2246 {
2249 {
2250 TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
2251
2252 static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");
2253 Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");
2255 python_function_name, GetSessionDictionary().get(), valobj,
2256 &new_callee, options_sp, retval);
2257 }
2258 }
2259 } else {
2260 retval.assign("<no function name>");
2261 return false;
2262 }
2263
2264 if (new_callee && old_callee != new_callee) {
2265 Locker py_lock(this,
2267 callee_wrapper_sp = std::make_shared<StructuredPythonObject>(
2268 PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));
2270
2271 return ret_val;
2272}
2273
2275 const char *python_function_name, TypeImplSP type_impl_sp) {
2276 Locker py_lock(this,
2279 python_function_name, m_dictionary_name.c_str(), type_impl_sp);
2280}
2281
2283 void *baton, StoppointCallbackContext *context, user_id_t break_id,
2284 user_id_t break_loc_id) {
2285 CommandDataPython *bp_option_data = (CommandDataPython *)baton;
2286 const char *python_function_name = bp_option_data->script_source.c_str();
2287
2288 if (!context)
2289 return true;
2290
2291 ExecutionContext exe_ctx(context->exe_ctx_ref);
2292 Target *target = exe_ctx.GetTargetPtr();
2293
2294 if (!target)
2295 return true;
2296
2297 Debugger &debugger = target->GetDebugger();
2298 ScriptInterpreterPythonImpl *python_interpreter =
2299 GetPythonInterpreter(debugger);
2300
2301 if (!python_interpreter)
2302 return true;
2303
2304 if (python_function_name && python_function_name[0]) {
2305 const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
2306 BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
2307 if (breakpoint_sp) {
2308 const BreakpointLocationSP bp_loc_sp(
2309 breakpoint_sp->FindLocationByID(break_loc_id));
2310
2311 if (stop_frame_sp && bp_loc_sp) {
2312 bool ret_val = true;
2313 {
2314 Locker py_lock(python_interpreter, Locker::AcquireLock |
2317 Expected<bool> maybe_ret_val =
2319 python_function_name,
2320 python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
2321 bp_loc_sp, bp_option_data->m_extra_args);
2322
2323 if (!maybe_ret_val) {
2324
2325 llvm::handleAllErrors(
2326 maybe_ret_val.takeError(),
2327 [&](PythonException &E) {
2328 *debugger.GetAsyncErrorStream() << E.ReadBacktrace();
2329 },
2330 [&](const llvm::ErrorInfoBase &E) {
2331 *debugger.GetAsyncErrorStream() << E.message();
2332 });
2333
2334 } else {
2335 ret_val = maybe_ret_val.get();
2336 }
2337 }
2338 return ret_val;
2339 }
2340 }
2341 }
2342 // We currently always true so we stop in case anything goes wrong when
2343 // trying to call the script function
2344 return true;
2345}
2346
2348 void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
2349 WatchpointOptions::CommandData *wp_option_data =
2351 const char *python_function_name = wp_option_data->script_source.c_str();
2352
2353 if (!context)
2354 return true;
2355
2356 ExecutionContext exe_ctx(context->exe_ctx_ref);
2357 Target *target = exe_ctx.GetTargetPtr();
2358
2359 if (!target)
2360 return true;
2361
2362 Debugger &debugger = target->GetDebugger();
2363 ScriptInterpreterPythonImpl *python_interpreter =
2364 GetPythonInterpreter(debugger);
2365
2366 if (!python_interpreter)
2367 return true;
2368
2369 if (python_function_name && python_function_name[0]) {
2370 const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
2371 WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
2372 if (wp_sp) {
2373 if (stop_frame_sp && wp_sp) {
2374 bool ret_val = true;
2375 {
2376 Locker py_lock(python_interpreter, Locker::AcquireLock |
2380 python_function_name,
2381 python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
2382 wp_sp);
2383 }
2384 return ret_val;
2385 }
2386 }
2387 }
2388 // We currently always true so we stop in case anything goes wrong when
2389 // trying to call the script function
2390 return true;
2391}
2392
2394 const char *impl_function, Process *process, std::string &output,
2395 Status &error) {
2396 bool ret_val;
2397 if (!process) {
2398 error = Status::FromErrorString("no process");
2399 return false;
2400 }
2401 if (!impl_function || !impl_function[0]) {
2402 error = Status::FromErrorString("no function to execute");
2403 return false;
2404 }
2405
2406 {
2407 Locker py_lock(this,
2410 impl_function, m_dictionary_name.c_str(), process->shared_from_this(),
2411 output);
2412 if (!ret_val)
2413 error = Status::FromErrorString("python script evaluation failed");
2414 }
2415 return ret_val;
2416}
2417
2419 const char *impl_function, Thread *thread, std::string &output,
2420 Status &error) {
2421 if (!thread) {
2422 error = Status::FromErrorString("no thread");
2423 return false;
2424 }
2425 if (!impl_function || !impl_function[0]) {
2426 error = Status::FromErrorString("no function to execute");
2427 return false;
2428 }
2429
2430 Locker py_lock(this,
2432 if (std::optional<std::string> result =
2434 impl_function, m_dictionary_name.c_str(),
2435 thread->shared_from_this())) {
2436 output = std::move(*result);
2437 return true;
2439 error = Status::FromErrorString("python script evaluation failed");
2440 return false;
2441}
2442
2444 const char *impl_function, Target *target, std::string &output,
2445 Status &error) {
2446 bool ret_val;
2447 if (!target) {
2448 error = Status::FromErrorString("no thread");
2449 return false;
2450 }
2451 if (!impl_function || !impl_function[0]) {
2452 error = Status::FromErrorString("no function to execute");
2453 return false;
2454 }
2455
2456 {
2457 TargetSP target_sp(target->shared_from_this());
2458 Locker py_lock(this,
2461 impl_function, m_dictionary_name.c_str(), target_sp, output);
2462 if (!ret_val)
2463 error = Status::FromErrorString("python script evaluation failed");
2464 }
2465 return ret_val;
2466}
2467
2469 const char *impl_function, StackFrame *frame, std::string &output,
2470 Status &error) {
2471 if (!frame) {
2472 error = Status::FromErrorString("no frame");
2473 return false;
2474 }
2475 if (!impl_function || !impl_function[0]) {
2476 error = Status::FromErrorString("no function to execute");
2477 return false;
2478 }
2479
2480 Locker py_lock(this,
2482 if (std::optional<std::string> result =
2484 impl_function, m_dictionary_name.c_str(),
2485 frame->shared_from_this())) {
2486 output = std::move(*result);
2487 return true;
2489 error = Status::FromErrorString("python script evaluation failed");
2490 return false;
2491}
2492
2494 const char *impl_function, ValueObject *value, std::string &output,
2495 Status &error) {
2496 bool ret_val;
2497 if (!value) {
2498 error = Status::FromErrorString("no value");
2499 return false;
2500 }
2501 if (!impl_function || !impl_function[0]) {
2502 error = Status::FromErrorString("no function to execute");
2503 return false;
2504 }
2505
2506 {
2507 Locker py_lock(this,
2510 impl_function, m_dictionary_name.c_str(), value->GetSP(), output);
2511 if (!ret_val)
2512 error = Status::FromErrorString("python script evaluation failed");
2513 }
2514 return ret_val;
2515}
2516
2517uint64_t replace_all(std::string &str, const std::string &oldStr,
2518 const std::string &newStr) {
2519 size_t pos = 0;
2520 uint64_t matches = 0;
2521 while ((pos = str.find(oldStr, pos)) != std::string::npos) {
2522 matches++;
2523 str.replace(pos, oldStr.length(), newStr);
2524 pos += newStr.length();
2525 }
2526 return matches;
2527}
2528
2530 const char *pathname, const LoadScriptOptions &options,
2532 FileSpec extra_search_dir, lldb::TargetSP target_sp) {
2533 namespace fs = llvm::sys::fs;
2534 namespace path = llvm::sys::path;
2535
2537 .SetEnableIO(!options.GetSilent())
2538 .SetSetLLDBGlobals(false);
2539
2540 if (!pathname || !pathname[0]) {
2541 error = Status::FromErrorString("empty path");
2542 return false;
2543 }
2544
2545 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
2546 io_redirect_or_error = ScriptInterpreterIORedirect::Create(
2547 exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);
2548
2549 if (!io_redirect_or_error) {
2550 error = Status::FromError(io_redirect_or_error.takeError());
2551 return false;
2552 }
2553
2554 ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
2555
2556 // Before executing Python code, lock the GIL.
2557 Locker py_lock(this,
2559 (options.GetInitSession() ? Locker::InitSession : 0) |
2562 (options.GetInitSession() ? Locker::TearDownSession : 0),
2563 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
2564 io_redirect.GetErrorFile());
2565
2566 auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
2567 if (directory.empty()) {
2568 return llvm::createStringError("invalid directory name");
2569 }
2570
2571 replace_all(directory, "\\", "\\\\");
2572 replace_all(directory, "'", "\\'");
2573
2574 // Make sure that Python has "directory" in the search path.
2575 StreamString command_stream;
2576 command_stream.Printf("if not (sys.path.__contains__('%s')):\n "
2577 "sys.path.insert(1,'%s');\n\n",
2578 directory.c_str(), directory.c_str());
2579 bool syspath_retval =
2580 ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
2581 if (!syspath_retval)
2582 return llvm::createStringError("Python sys.path handling failed");
2583
2584 return llvm::Error::success();
2585 };
2586
2587 std::string module_name(pathname);
2588 bool possible_package = false;
2589
2590 if (extra_search_dir) {
2591 if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
2592 error = Status::FromError(std::move(e));
2593 return false;
2594 }
2595 } else {
2596 FileSpec module_file(pathname);
2597 FileSystem::Instance().Resolve(module_file);
2598
2599 fs::file_status st;
2600 std::error_code ec = status(module_file.GetPath(), st);
2601
2602 if (ec || st.type() == fs::file_type::status_error ||
2603 st.type() == fs::file_type::type_unknown ||
2604 st.type() == fs::file_type::file_not_found) {
2605 // if not a valid file of any sort, check if it might be a filename still
2606 // dot can't be used but / and \ can, and if either is found, reject
2607 if (strchr(pathname, '\\') || strchr(pathname, '/')) {
2608 error = Status::FromErrorStringWithFormatv("invalid pathname '{0}'",
2609 pathname);
2610 return false;
2611 }
2612 // Not a filename, probably a package of some sort, let it go through.
2613 possible_package = true;
2614 } else if (is_directory(st) || is_regular_file(st)) {
2615 if (module_file.GetDirectory().empty()) {
2617 "invalid directory name '{0}'", pathname);
2618 return false;
2619 }
2620 if (llvm::Error e = ExtendSysPath(module_file.GetDirectory().str())) {
2621 error = Status::FromError(std::move(e));
2622 return false;
2623 }
2624 module_name = module_file.GetFilename().str();
2625 } else {
2627 "no known way to import this module specification");
2628 return false;
2629 }
2630 }
2631
2632 // Strip .py or .pyc extension
2633 llvm::StringRef extension = llvm::sys::path::extension(module_name);
2634 if (!extension.empty()) {
2635 if (extension == ".py")
2636 module_name.resize(module_name.length() - 3);
2637 else if (extension == ".pyc")
2638 module_name.resize(module_name.length() - 4);
2639 }
2640
2641 if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
2643 "Python does not allow dots in module names: %s", module_name.c_str());
2644 return false;
2645 }
2646
2647 if (module_name.find('-') != llvm::StringRef::npos) {
2649 "Python discourages dashes in module names: %s", module_name.c_str());
2650 return false;
2651 }
2652
2653 // Check if the module is already imported.
2654 StreamString command_stream;
2655 command_stream.Clear();
2656 command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
2657 bool does_contain = false;
2658 // This call will succeed if the module was ever imported in any Debugger in
2659 // the lifetime of the process in which this LLDB framework is living.
2660 const bool does_contain_executed = ExecuteOneLineWithReturn(
2661 command_stream.GetData(),
2663 exc_options);
2664
2665 const bool was_imported_globally = does_contain_executed && does_contain;
2666 const bool was_imported_locally =
2668 .GetItemForKey(PythonString(module_name))
2669 .IsAllocated();
2670
2671 // now actually do the import
2672 command_stream.Clear();
2673
2674 if (was_imported_globally || was_imported_locally) {
2675 if (!was_imported_locally)
2676 command_stream.Printf("import %s ; importlib.reload(%s)",
2677 module_name.c_str(), module_name.c_str());
2678 else
2679 command_stream.Printf("importlib.reload(%s)", module_name.c_str());
2680 } else
2681 command_stream.Printf("import %s", module_name.c_str());
2682
2683 error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
2684 if (error.Fail())
2685 return false;
2686
2687 // if we are here, everything worked
2688 // call __lldb_init_module(debugger,dict)
2690 module_name.c_str(), m_dictionary_name.c_str(),
2691 m_debugger.shared_from_this())) {
2692 error = Status::FromErrorString("calling __lldb_init_module failed");
2693 return false;
2694 }
2695
2696 if (module_sp) {
2697 // everything went just great, now set the module object
2698 command_stream.Clear();
2699 command_stream.Printf("%s", module_name.c_str());
2700 void *module_pyobj = nullptr;
2702 command_stream.GetData(),
2704 exc_options) &&
2705 module_pyobj)
2706 *module_sp = std::make_shared<StructuredPythonObject>(PythonObject(
2707 PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));
2708 }
2709
2710 // Finally, if we got a target passed in, then we should tell the new module
2711 // about this target:
2712 if (target_sp)
2714 module_name.c_str(), m_dictionary_name.c_str(), target_sp);
2715
2716 return true;
2717}
2718
2719bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {
2720 if (!word || !word[0])
2721 return false;
2722
2723 llvm::StringRef word_sr(word);
2724
2725 // filter out a few characters that would just confuse us and that are
2726 // clearly not keyword material anyway
2727 if (word_sr.find('"') != llvm::StringRef::npos ||
2728 word_sr.find('\'') != llvm::StringRef::npos)
2729 return false;
2730
2731 StreamString command_stream;
2732 command_stream.Printf("keyword.iskeyword('%s')", word);
2733 bool result;
2734 ExecuteScriptOptions options;
2735 options.SetEnableIO(false);
2736 options.SetMaskoutErrors(true);
2737 options.SetSetLLDBGlobals(false);
2738 if (ExecuteOneLineWithReturn(command_stream.GetData(),
2740 &result, options))
2741 return result;
2742 return false;
2743}
2744
2747 : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),
2748 m_old_asynch(debugger_sp->GetAsyncExecution()) {
2750 m_debugger_sp->SetAsyncExecution(false);
2752 m_debugger_sp->SetAsyncExecution(true);
2753}
2754
2756 if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
2757 m_debugger_sp->SetAsyncExecution(m_old_asynch);
2758}
2759
2761 const char *impl_function, llvm::StringRef args,
2762 ScriptedCommandSynchronicity synchronicity,
2764 const lldb_private::ExecutionContext &exe_ctx) {
2765 if (!impl_function) {
2766 error = Status::FromErrorString("no function to execute");
2767 return false;
2768 }
2769
2770 lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
2771 lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
2772
2773 if (!debugger_sp.get()) {
2774 error = Status::FromErrorString("invalid Debugger pointer");
2775 return false;
2776 }
2777
2778 bool ret_val = false;
2779
2780 {
2781 Locker py_lock(this,
2783 (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
2785
2786 SynchronicityHandler synch_handler(debugger_sp, synchronicity);
2787
2788 std::string args_str = args.str();
2790 impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),
2791 cmd_retobj, exe_ctx_ref_sp);
2792 }
2793
2794 if (!ret_val) {
2795 error = Status::FromErrorString("unable to execute script function");
2796 return false;
2797 }
2798 if (cmd_retobj.GetStatus() == eReturnStatusFailed)
2799 return false;
2800
2801 error.Clear();
2802 return ret_val;
2804
2805/// In Python, a special attribute __doc__ contains the docstring for an object
2806/// (function, method, class, ...) if any is defined Otherwise, the attribute's
2807/// value is None.
2809 std::string &dest) {
2810 dest.clear();
2811
2812 if (!item || !*item)
2813 return false;
2814
2815 std::string command(item);
2816 command += ".__doc__";
2817
2818 // Python is going to point this to valid data if ExecuteOneLineWithReturn
2819 // returns successfully.
2820 char *result_ptr = nullptr;
2821
2824 &result_ptr, ExecuteScriptOptions().SetEnableIO(false))) {
2825 if (result_ptr)
2826 dest.assign(result_ptr);
2827 return true;
2828 }
2829
2830 StreamString str_stream;
2831 str_stream << "Function " << item
2832 << " was not found. Containing module might be missing.";
2833 dest = std::string(str_stream.GetString());
2835 return false;
2836}
2837
2838std::unique_ptr<ScriptInterpreterLocker>
2840 std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
2843 return py_lock;
2844}
2845
2848
2849 // RAII-based initialization which correctly handles multiple-initialization,
2850 // version- specific differences among Python 2 and Python 3, and saving and
2851 // restoring various other pieces of state that can get mucked with during
2852 // initialization.
2853 InitializePythonRAII initialize_guard;
2854 if (llvm::Error error = initialize_guard.DoInitialize())
2855 return error;
2856
2858
2859 // Update the path python uses to search for modules to include the current
2860 // directory.
2861
2862 RunSimpleString("import sys");
2864
2865 // Don't denormalize paths when calling file_spec.GetPath(). On platforms
2866 // that use a backslash as the path separator, this will result in executing
2867 // python code containing paths with unescaped backslashes. But Python also
2868 // accepts forward slashes, so to make life easier we just use that.
2869 if (FileSpec file_spec = GetPythonDir())
2870 AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
2871 if (FileSpec file_spec = HostInfo::GetShlibDir())
2872 AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
2873
2874 RunSimpleString("sys.dont_write_bytecode = 1; import "
2875 "lldb.embedded_interpreter; from "
2876 "lldb.embedded_interpreter import run_python_interpreter; "
2877 "from lldb.embedded_interpreter import run_one_line");
2878
2879#if LLDB_USE_PYTHON_SET_INTERRUPT
2880 // Python will not just overwrite its internal SIGINT handler but also the
2881 // one from the process. Backup the current SIGINT handler to prevent that
2882 // Python deletes it.
2883 RestoreSignalHandlerScope save_sigint(SIGINT);
2884
2885 // Setup a default SIGINT signal handler that works the same way as the
2886 // normal Python REPL signal handler which raises a KeyboardInterrupt.
2887 // Also make sure to not pollute the user's REPL with the signal module nor
2888 // our utility function.
2889 RunSimpleString("def lldb_setup_sigint_handler():\n"
2890 " import signal;\n"
2891 " def signal_handler(sig, frame):\n"
2892 " raise KeyboardInterrupt()\n"
2893 " signal.signal(signal.SIGINT, signal_handler);\n"
2894 "lldb_setup_sigint_handler();\n"
2895 "del lldb_setup_sigint_handler\n");
2896#endif
2897 return llvm::Error::success();
2898}
2899
2901 std::string path) {
2902 std::string statement;
2903 if (location == AddLocation::Beginning) {
2904 statement.assign("sys.path.insert(0,\"");
2905 statement.append(path);
2906 statement.append("\")");
2907 } else {
2908 statement.assign("sys.path.append(\"");
2909 statement.append(path);
2910 statement.append("\")");
2911 }
2912 RunSimpleString(statement.c_str());
2913}
2914
2915// We are intentionally NOT calling Py_Finalize here (this would be the logical
2916// place to call it). Calling Py_Finalize here causes test suite runs to seg
2917// fault: The test suite runs in Python. It registers SBDebugger::Terminate to
2918// be called 'at_exit'. When the test suite Python harness finishes up, it
2919// calls Py_Finalize, which calls all the 'at_exit' registered functions.
2920// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
2921// which calls ScriptInterpreter::Terminate, which calls
2922// ScriptInterpreterPythonImpl::Terminate. So if we call Py_Finalize here, we
2923// end up with Py_Finalize being called from within Py_Finalize, which results
2924// in a seg fault. Since this function only gets called when lldb is shutting
2925// down and going away anyway, the fact that we don't actually call Py_Finalize
2926// should not cause any problems (everything should shut down/go away anyway
2927// when the process exits).
2928//
2929// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:382
ScriptInterpreterPythonImpl::Locker Locker
#define LLDB_PLUGIN_DEFINE(PluginName)
PyObject * PyInit__lldb(void)
static std::string GenerateUniqueName(const char *base_name_wanted, uint32_t &functions_counter, const void *name_token=nullptr)
#define LLDBSwigPyInit
static ScriptInterpreterPythonImpl * GetPythonInterpreter(Debugger &debugger)
static const char python_exe_relative_path[]
uint64_t replace_all(std::string &str, const std::string &oldStr, const std::string &newStr)
static const char GetInterpreterInfoScript[]
#define LLDB_SCOPED_TIMER()
Definition Timer.h:83
A Python sys.stdout/stderr file backed by a pipe whose read end is drained by a reader thread that wr...
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
static std::unique_ptr< SessionIORedirect > Create(lldb::user_id_t debugger_id, bool is_stdout)
"lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a breakpoint or breakpoint lo...
void SetCallback(BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous=false)
Adds a callback to the breakpoint option set.
void AppendError(llvm::StringRef in_string)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendErrorWithFormatv(const char *format, Args &&...args)
A class to manage flag bits.
Definition Debugger.h:101
lldb::FileSP GetErrorFileSP()
Definition Debugger.h:163
lldb::FileSP GetOutputFileSP()
Definition Debugger.h:159
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
bool StatuslineSupported()
Whether the statusline can be drawn: show-statusline is enabled and the output is an escape-code-capa...
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id)
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
ExecuteScriptOptions & SetMaskoutErrors(bool maskout)
ExecuteScriptOptions & SetSetLLDBGlobals(bool set)
ExecuteScriptOptions & SetEnableIO(bool enable)
Execution context objects refer to objects in the execution of the program that is being debugged.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
Target * GetTargetPtr() const
Returns a pointer to the target object.
A file utility class.
Definition FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:454
bool RemoveLastPathComponent()
Removes the last path component by replacing the current path with its parent.
Definition FileSpec.cpp:465
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
void SetDirectory(llvm::StringRef directory)
Directory string set accessor.
Definition FileSpec.cpp:358
llvm::StringRef GetFileNameExtension() const
Extract the extension of the file.
Definition FileSpec.cpp:410
Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
An abstract base class for files.
Definition FileBase.h:34
static int kInvalidDescriptor
Definition FileBase.h:36
virtual int GetDescriptor() const
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition File.cpp:119
bool IsValid() const override
IsValid.
Definition File.cpp:106
virtual Status Flush()
Flush the current stream.
Definition File.cpp:149
lldb::LockableStreamFileSP GetErrorStreamFileSP()
Definition IOHandler.cpp:95
lldb::LockableStreamFileSP GetOutputStreamFileSP()
Definition IOHandler.cpp:93
void SetIsDone(bool b)
Definition IOHandler.h:81
void PutCString(const char *cstr)
Definition Log.cpp:162
Status CreateNew() override
Definition PipePosix.cpp:82
int ReleaseReadFileDescriptor() override
int ReleaseWriteFileDescriptor() override
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
Definition Process.h: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
bool GenerateWatchpointCommandCallbackData(StringList &input, std::string &output, bool is_callback) override
Status SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) override
Set a script function as the callback for the breakpoint.
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override
std::unique_ptr< SessionIORedirect > m_stderr_redirect
static bool BreakpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Status &error) override
void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result) override
lldb::ScriptedCommandInterfaceSP CreateScriptedCommandInterface() override
bool RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override
lldb::ScriptedFrameProviderInterfaceSP CreateScriptedFrameProviderInterface() override
Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *callback_body, bool is_callback) override
Set the callback body text into the callback for the breakpoint.
lldb::ScriptedStackFrameRecognizerInterfaceSP CreateScriptedStackFrameRecognizerInterface() override
bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, lldb::FileSP err)
void SetWatchpointCommandCallback(WatchpointOptions *wp_options, const char *user_input, bool is_callback) override
Set a one-liner as the callback for the watchpoint.
bool RedirectTerminalHandleThroughLock(const char *py_name, python::PythonObject &save_file, const char *mode, File &file)
If file is the debugger's own terminal, point sys.
std::unique_ptr< ScriptInterpreterLocker > AcquireInterpreterLock() override
void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &bp_options_vec, CommandReturnObject &result) override
static void AddToSysPath(AddLocation location, std::string path)
lldb::ScriptedStringSummaryInterfaceSP CreateScriptedStringSummaryInterface() override
bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={}, lldb::TargetSP loaded_into_target_sp={}) override
Status GenerateBreakpointCommandCallbackData(StringList &input, std::string &output, bool has_extra_args, bool is_callback) override
lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override
bool FormatterCallbackFunction(const char *function_name, lldb::TypeImplSP type_impl_sp) override
Status ExportFunctionDefinitionToInterpreter(StringList &function_def) override
bool ExecuteOneLine(llvm::StringRef command, CommandReturnObject *result, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
bool GetDocumentationForItem(const char *item, std::string &dest) override
In Python, a special attribute doc contains the docstring for an object (function,...
lldb::ScriptedSyntheticChildrenInterfaceSP CreateScriptedSyntheticChildrenInterface() override
lldb::ScriptedHookInterfaceSP CreateScriptedHookInterface() override
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) override
lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override
lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override
bool ExecuteOneLineWithReturn(llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
lldb::ScriptedBreakpointInterfaceSP CreateScriptedBreakpointInterface() override
bool RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error) override
bool SetStdHandle(lldb::FileSP file, const char *py_name, python::PythonObject &save_file, const char *mode, bool serialize_terminal_output)
Point sys.
bool GenerateTypeSynthClass(StringList &input, std::string &output, const void *name_token=nullptr) override
StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) override
StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) override
llvm::Expected< unsigned > GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) override
static bool WatchpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id)
static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger)
lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override
std::unique_ptr< SessionIORedirect > m_stdout_redirect
Abstract interface for the Python script interpreter.
static void ComputePythonDir(llvm::SmallVectorImpl< char > &path)
static void ComputePythonDirForApple(llvm::SmallVectorImpl< char > &path)
llvm::Expected< StructuredData::ObjectSP > GetExtensionSchema(const llvm::SmallVector< llvm::StringRef > &extension_path)
StructuredData::DictionarySP GetInterpreterInfo() override
llvm::Error ParseExtensionSchema(Stream &s, llvm::StringRef output_script_prefix, const llvm::SmallVector< llvm::StringRef > &extension_path, bool generate_non_abstract_methods, std::set< std::string > &typing_imports)
static void SharedLibraryDirectoryHelper(FileSpec &this_file)
llvm::Expected< std::string > ExtensionToImportPath(lldb::ScriptedExtension extension) override
llvm::Expected< FileSpec > GenerateExtensionTemplate(const std::string &name, std::vector< ExtensionTemplateRequest > &extensions, bool generate_non_abstract_methods, std::string output_file) override
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:439
Debugger & GetDebugger() const
Definition Target.h:1362
WatchpointList & GetWatchpointList()
Definition Target.h:985
"lldb/Core/ThreadedCommunication.h" Variation of Communication that supports threaded reads.
lldb::ValueObjectSP GetSP()
lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const
Returns a shared pointer to the watchpoint with id watchID, const version.
"lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a watchpoint.
void SetCallback(WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous=false)
Adds a callback to the watchpoint option set.
static llvm::Expected< ArgInfo > GetArgInfoFromInspectSignature(const PythonCallable &callable)
StructuredData::DictionarySP CreateStructuredDictionary() const
PythonObject GetItemForKey(const PythonObject &key) const
void SetItemForKey(const PythonObject &key, const PythonObject &value)
static int TranslateFdToPython(int our_fd)
static llvm::Expected< PythonFile > FromFile(File &file, const char *mode=nullptr)
static llvm::Expected< PythonModule > Import(const llvm::Twine &name)
PythonObject ResolveName(llvm::StringRef name) const
static PythonObject ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
llvm::Expected< PythonObject > GetAttribute(const llvm::Twine &name) const
llvm::Expected< PythonObject > CallMethod(const char *name, const T &... t) const
static bool LLDBSWIGPythonRunScriptKeywordValue(const char *python_function_name, const char *session_dictionary_name, const lldb::ValueObjectSP &value, std::string &output)
static bool LLDBSwigPythonCallTypeScript(const char *python_function_name, const void *session_dictionary, const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval)
static void * LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, const lldb::TargetSP &target_sp)
static std::optional< std::string > LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, const char *session_dictionary_name, lldb::ThreadSP thread)
static bool LLDBSwigPythonCallCommand(const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP debugger, const char *args, lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp)
static bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, const char *session_dictionary_name, const lldb::TargetSP &target, std::string &output)
static std::optional< std::string > LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, const char *session_dictionary_name, lldb::StackFrameSP frame)
static bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, const char *session_dictionary_name, const lldb::ProcessSP &process, std::string &output)
static bool LLDBSwigPythonFormatterCallbackFunction(const char *python_function_name, const char *session_dictionary_name, lldb::TypeImplSP type_impl_sp)
static bool LLDBSwigPythonCallModuleInit(const char *python_module_name, const char *session_dictionary_name, lldb::DebuggerSP debugger)
static bool LLDBSwigPythonWatchpointCallbackFunction(const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp)
static bool LLDBSwigPythonCallModuleNewTarget(const char *python_module_name, const char *session_dictionary_name, lldb::TargetSP target)
static llvm::Expected< bool > LLDBSwigPythonBreakpointCallbackFunction(const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::BreakpointLocationSP &sb_bp_loc, const lldb_private::StructuredDataImpl &args_impl)
llvm::Expected< T > As(llvm::Expected< PythonObject > &&obj)
T unwrapIgnoringErrors(llvm::Expected< T > expected)
llvm::Expected< PythonObject > runStringMultiLine(const llvm::Twine &string, const PythonDictionary &globals, const PythonDictionary &locals)
int RunSimpleString(const char *str)
llvm::Expected< PythonObject > runStringOneLine(const llvm::Twine &string, const PythonDictionary &globals, const PythonDictionary &locals)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
PipePosix Pipe
Definition Pipe.h:20
int file_t
Definition lldb-types.h:59
@ eScriptLanguagePython
ScriptedExtension
Scripting extension types.
@ eScriptedExtensionOperatingSystem
@ eScriptedExtensionScriptedHook
@ eScriptedExtensionParsedCommand
@ eScriptedExtensionScriptedPlatform
@ eScriptedExtensionScriptedCommand
@ eScriptedExtensionScriptedProcess
@ eScriptedExtensionScriptedFrame
@ eScriptedExtensionScriptedBreakpointResolver
@ eScriptedExtensionScriptedThreadPlan
@ eScriptedExtensionScriptedStringSummary
@ eScriptedExtensionScriptedFrameProvider
@ eScriptedExtensionScriptedThread
@ eScriptedExtensionScriptedStackFrameRecognizer
@ eScriptedExtensionScriptedSyntheticChildren
@ eScriptedExtensionInvalid
std::shared_ptr< lldb_private::ScriptedSyntheticChildrenInterface > ScriptedSyntheticChildrenInterfaceSP
std::shared_ptr< lldb_private::ScriptedHookInterface > ScriptedHookInterfaceSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ScriptedStringSummaryInterface > ScriptedStringSummaryInterfaceSP
std::shared_ptr< lldb_private::BreakpointLocation > BreakpointLocationSP
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
std::shared_ptr< lldb_private::ScriptInterpreter > ScriptInterpreterSP
std::shared_ptr< lldb_private::ScriptedThreadPlanInterface > ScriptedThreadPlanInterfaceSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::unique_ptr< lldb_private::File > FileUP
std::shared_ptr< lldb_private::TypeSummaryOptions > TypeSummaryOptionsSP
std::shared_ptr< lldb_private::OperatingSystemInterface > OperatingSystemInterfaceSP
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
std::shared_ptr< lldb_private::ScriptedBreakpointInterface > ScriptedBreakpointInterfaceSP
std::shared_ptr< lldb_private::ScriptedThreadInterface > ScriptedThreadInterfaceSP
std::shared_ptr< lldb_private::Debugger > DebuggerSP
@ eReturnStatusFailed
std::shared_ptr< lldb_private::Watchpoint > WatchpointSP
std::shared_ptr< lldb_private::ScriptedFrameProviderInterface > ScriptedFrameProviderInterfaceSP
std::shared_ptr< lldb_private::ScriptedCommandInterface > ScriptedCommandInterfaceSP
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::LockableStreamFile > LockableStreamFileSP
std::shared_ptr< lldb_private::TypeImpl > TypeImplSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::File > FileSP
std::shared_ptr< lldb_private::ScriptedStackFrameRecognizerInterface > ScriptedStackFrameRecognizerInterfaceSP
std::unique_ptr< lldb_private::ScriptedProcessInterface > ScriptedProcessInterfaceUP
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP
Describes one extension to emit into the generated template file.
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition UserID.h:47