LLDB mainline
ScriptedPythonInterface.h
Go to the documentation of this file.
1//===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===//
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#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
10#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
11
12#if LLDB_ENABLE_PYTHON
13
14#include <optional>
15#include <sstream>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19
20#include "lldb/Host/Config.h"
23
25#include "../SWIGPythonBridge.h"
27
28namespace lldb_private {
29class ScriptInterpreterPythonImpl;
30class ScriptedPythonInterface : virtual public ScriptedInterface {
31public:
32 ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter);
33 ~ScriptedPythonInterface() override = default;
34
35 enum class AbstractMethodCheckerCases {
36 eNotImplemented,
37 eNotAllocated,
38 eNotCallable,
39 eUnknownArgumentCount,
40 eInvalidArgumentCount,
41 eValid
42 };
43
44 struct AbstrackMethodCheckerPayload {
45
46 struct InvalidArgumentCountPayload {
47 InvalidArgumentCountPayload(size_t required, size_t actual)
48 : required_argument_count(required), actual_argument_count(actual) {}
49
50 size_t required_argument_count;
51 size_t actual_argument_count;
52 };
53
54 AbstractMethodCheckerCases checker_case;
55 std::variant<std::monostate, InvalidArgumentCountPayload> payload;
56 };
57
58 llvm::Expected<std::map<llvm::StringLiteral, AbstrackMethodCheckerPayload>>
59 CheckAbstractMethodImplementation(
60 const python::PythonDictionary &class_dict) const {
61
62 using namespace python;
63
64 std::map<llvm::StringLiteral, AbstrackMethodCheckerPayload> checker;
65#define SET_CASE_AND_CONTINUE(method_name, case) \
66 { \
67 checker[method_name] = {case, {}}; \
68 continue; \
69 }
70
71 for (const AbstractMethodRequirement &requirement :
72 GetAbstractMethodRequirements()) {
73 llvm::StringLiteral method_name = requirement.name;
74 if (!class_dict.HasKey(method_name))
75 SET_CASE_AND_CONTINUE(method_name,
76 AbstractMethodCheckerCases::eNotImplemented)
77 auto callable_or_err = class_dict.GetItem(method_name);
78 if (!callable_or_err) {
79 llvm::consumeError(callable_or_err.takeError());
80 SET_CASE_AND_CONTINUE(method_name,
81 AbstractMethodCheckerCases::eNotAllocated)
82 }
83
84 PythonCallable callable = callable_or_err->AsType<PythonCallable>();
85 if (!callable)
86 SET_CASE_AND_CONTINUE(method_name,
87 AbstractMethodCheckerCases::eNotCallable)
88
89 if (!requirement.min_arg_count)
90 SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid)
91
92 auto arg_info_or_err = callable.GetArgInfo();
93 if (!arg_info_or_err) {
94 llvm::consumeError(arg_info_or_err.takeError());
95 SET_CASE_AND_CONTINUE(method_name,
96 AbstractMethodCheckerCases::eUnknownArgumentCount)
97 }
98
99 PythonCallable::ArgInfo arg_info = *arg_info_or_err;
100 if (requirement.min_arg_count <= arg_info.max_positional_args) {
101 SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid)
102 } else {
103 checker[method_name] = {
104 AbstractMethodCheckerCases::eInvalidArgumentCount,
105 AbstrackMethodCheckerPayload::InvalidArgumentCountPayload(
106 requirement.min_arg_count, arg_info.max_positional_args)};
107 }
108 }
109
110#undef SET_CASE_AND_CONTINUE
111
112 return checker;
113 }
114
115 template <typename... Args>
116 llvm::Expected<StructuredData::GenericSP>
117 CreatePluginObject(llvm::StringRef class_name,
118 StructuredData::Generic *script_obj, Args... args) {
119 using namespace python;
120 using Locker = ScriptInterpreterPythonImpl::Locker;
121
122 Log *log = GetLog(LLDBLog::Script);
123 auto create_error = [](llvm::StringLiteral format, auto &&...ts) {
124 return llvm::createStringError(
125 llvm::formatv(format.data(), std::forward<decltype(ts)>(ts)...)
126 .str());
127 };
128
129 bool has_class_name = !class_name.empty();
130 bool has_interpreter_dict =
131 !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty());
132 if (!has_class_name && !has_interpreter_dict && !script_obj) {
133 if (!has_class_name)
134 return create_error("Missing script class name.");
135 else if (!has_interpreter_dict)
136 return create_error("Invalid script interpreter dictionary.");
137 else
138 return create_error("Missing scripting object.");
139 }
140
141 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
142 Locker::FreeLock);
143
144 PythonObject result = {};
145
146 if (script_obj) {
147 result = PythonObject(PyRefType::Borrowed,
148 static_cast<PyObject *>(script_obj->GetValue()));
149 } else {
150 auto dict =
151 PythonModule::MainModule().ResolveName<python::PythonDictionary>(
152 m_interpreter.GetDictionaryName());
153 if (!dict.IsAllocated())
154 return create_error("Could not find interpreter dictionary: {0}",
155 m_interpreter.GetDictionaryName());
156
157 auto init =
158 PythonObject::ResolveNameWithDictionary<python::PythonCallable>(
159 class_name, dict);
160 if (!init.IsAllocated())
161 return create_error("Could not find script class: {0}",
162 class_name.data());
163
164 std::tuple<Args...> original_args = std::forward_as_tuple(args...);
165 auto transformed_args = TransformArgs(original_args);
166
167 std::string error_string;
168 llvm::Expected<PythonCallable::ArgInfo> arg_info = init.GetArgInfo();
169 if (!arg_info) {
170 llvm::handleAllErrors(
171 arg_info.takeError(),
172 [&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
173 [&](const llvm::ErrorInfoBase &E) {
174 error_string.append(E.message());
175 });
176 return llvm::createStringError(llvm::inconvertibleErrorCode(),
177 error_string);
178 }
179
180 llvm::Expected<PythonObject> expected_return_object =
181 create_error("Resulting object is not initialized.");
182
183 // This relax the requirement on the number of argument for
184 // initializing scripting extension if the size of the interface
185 // parameter pack contains 1 less element than the extension maximum
186 // number of positional arguments for this initializer.
187 //
188 // This addresses the cases where the embedded interpreter session
189 // dictionary is passed to the extension initializer which is not used
190 // most of the time.
191 // Note, though none of our API's suggest defining the interfaces with
192 // varargs, we have some extant clients that were doing that. To keep
193 // from breaking them, we just say putting a varargs in these signatures
194 // turns off argument checking.
195 size_t num_args = sizeof...(Args);
196 if (arg_info->max_positional_args != PythonCallable::ArgInfo::UNBOUNDED &&
197 num_args != arg_info->max_positional_args) {
198 if (num_args != arg_info->max_positional_args - 1)
199 return create_error("Passed arguments ({0}) doesn't match the number "
200 "of expected arguments ({1}).",
201 num_args, arg_info->max_positional_args);
202
203 std::apply(
204 [&init, &expected_return_object](auto &&...args) {
205 llvm::consumeError(expected_return_object.takeError());
206 expected_return_object = init(args...);
207 },
208 std::tuple_cat(transformed_args, std::make_tuple(dict)));
209 } else {
210 std::apply(
211 [&init, &expected_return_object](auto &&...args) {
212 llvm::consumeError(expected_return_object.takeError());
213 expected_return_object = init(args...);
214 },
215 transformed_args);
216 }
217
218 if (!expected_return_object)
219 return expected_return_object.takeError();
220 result = expected_return_object.get();
221 }
222
223 if (!result.IsValid())
224 return create_error("Resulting object is not a valid Python Object.");
225 if (!result.HasAttribute("__class__"))
226 return create_error("Resulting object doesn't have '__class__' member.");
227
228 PythonObject obj_class = result.GetAttributeValue("__class__");
229 if (!obj_class.IsValid())
230 return create_error("Resulting class object is not a valid.");
231 if (!obj_class.HasAttribute("__name__"))
232 return create_error(
233 "Resulting object class doesn't have '__name__' member.");
234 PythonString obj_class_name =
235 obj_class.GetAttributeValue("__name__").AsType<PythonString>();
236
237 PythonObject object_class_mapping_proxy =
238 obj_class.GetAttributeValue("__dict__");
239 if (!obj_class.HasAttribute("__dict__"))
240 return create_error(
241 "Resulting object class doesn't have '__dict__' member.");
242
243 PythonCallable dict_converter = PythonModule::BuiltinsModule()
244 .ResolveName("dict")
245 .AsType<PythonCallable>();
246 if (!dict_converter.IsAllocated())
247 return create_error(
248 "Python 'builtins' module doesn't have 'dict' class.");
249
250 PythonDictionary object_class_dict =
251 dict_converter(object_class_mapping_proxy).AsType<PythonDictionary>();
252 if (!object_class_dict.IsAllocated())
253 return create_error("Coudn't create dictionary from resulting object "
254 "class mapping proxy object.");
255
256 auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict);
257 if (!checker_or_err)
258 return checker_or_err.takeError();
259
260 llvm::Error abstract_method_errors = llvm::Error::success();
261 for (const auto &method_checker : *checker_or_err)
262 switch (method_checker.second.checker_case) {
263 case AbstractMethodCheckerCases::eNotImplemented:
264 abstract_method_errors = llvm::joinErrors(
265 std::move(abstract_method_errors),
266 std::move(create_error("Abstract method {0}.{1} not implemented.",
267 obj_class_name.GetString(),
268 method_checker.first)));
269 break;
270 case AbstractMethodCheckerCases::eNotAllocated:
271 abstract_method_errors = llvm::joinErrors(
272 std::move(abstract_method_errors),
273 std::move(create_error("Abstract method {0}.{1} not allocated.",
274 obj_class_name.GetString(),
275 method_checker.first)));
276 break;
277 case AbstractMethodCheckerCases::eNotCallable:
278 abstract_method_errors = llvm::joinErrors(
279 std::move(abstract_method_errors),
280 std::move(create_error("Abstract method {0}.{1} not callable.",
281 obj_class_name.GetString(),
282 method_checker.first)));
283 break;
284 case AbstractMethodCheckerCases::eUnknownArgumentCount:
285 abstract_method_errors = llvm::joinErrors(
286 std::move(abstract_method_errors),
287 std::move(create_error(
288 "Abstract method {0}.{1} has unknown argument count.",
289 obj_class_name.GetString(), method_checker.first)));
290 break;
291 case AbstractMethodCheckerCases::eInvalidArgumentCount: {
292 auto &payload_variant = method_checker.second.payload;
293 if (!std::holds_alternative<
294 AbstrackMethodCheckerPayload::InvalidArgumentCountPayload>(
295 payload_variant)) {
296 abstract_method_errors = llvm::joinErrors(
297 std::move(abstract_method_errors),
298 std::move(create_error(
299 "Abstract method {0}.{1} has unexpected argument count.",
300 obj_class_name.GetString(), method_checker.first)));
301 } else {
302 auto payload = std::get<
303 AbstrackMethodCheckerPayload::InvalidArgumentCountPayload>(
304 payload_variant);
305 abstract_method_errors = llvm::joinErrors(
306 std::move(abstract_method_errors),
307 std::move(
308 create_error("Abstract method {0}.{1} has unexpected "
309 "argument count (expected {2} but has {3}).",
310 obj_class_name.GetString(), method_checker.first,
311 payload.required_argument_count,
312 payload.actual_argument_count)));
313 }
314 } break;
315 case AbstractMethodCheckerCases::eValid:
316 LLDB_LOG(log, "Abstract method {0}.{1} implemented & valid.",
317 obj_class_name.GetString(), method_checker.first);
318 break;
319 }
320
321 if (abstract_method_errors) {
322 Status error = Status::FromError(std::move(abstract_method_errors));
323 LLDB_LOG(log, "Abstract method error in {0}:\n{1}", class_name,
324 error.AsCString());
325 return error.ToError();
326 }
327
328 m_object_instance_sp = StructuredData::GenericSP(
329 new StructuredPythonObject(std::move(result)));
330 return m_object_instance_sp;
331 }
332
333 /// Call a static method on a Python class without creating an instance.
334 ///
335 /// This method resolves a Python class by name and calls a static method
336 /// on it, returning the result. This is useful for calling class-level
337 /// methods that don't require an instance.
338 ///
339 /// \param class_name The fully-qualified name of the Python class.
340 /// \param method_name The name of the static method to call.
341 /// \param error Output parameter to receive error information if the call
342 /// fails.
343 /// \param args Arguments to pass to the static method.
344 ///
345 /// \return The return value of the static method call, or an error value.
346 template <typename T = StructuredData::ObjectSP, typename... Args>
347 T CallStaticMethod(llvm::StringRef class_name, llvm::StringRef method_name,
348 Status &error, Args &&...args) {
349 using namespace python;
350 using Locker = ScriptInterpreterPythonImpl::Locker;
351
352 std::string caller_signature =
353 llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
354 llvm::Twine(class_name) + llvm::Twine(".") +
355 llvm::Twine(method_name) + llvm::Twine(")"))
356 .str();
357
358 if (class_name.empty())
359 return ErrorWithMessage<T>(caller_signature, "missing script class name",
360 error);
361
362 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
363 Locker::FreeLock);
364
365 // Get the interpreter dictionary.
366 auto dict =
367 PythonModule::MainModule().ResolveName<python::PythonDictionary>(
368 m_interpreter.GetDictionaryName());
369 if (!dict.IsAllocated())
370 return ErrorWithMessage<T>(
371 caller_signature,
372 llvm::formatv("could not find interpreter dictionary: {0}",
373 m_interpreter.GetDictionaryName())
374 .str(),
375 error);
376
377 // Resolve the class.
378 auto class_obj =
379 PythonObject::ResolveNameWithDictionary<python::PythonCallable>(
380 class_name, dict);
381 if (!class_obj.IsAllocated())
382 return ErrorWithMessage<T>(
383 caller_signature,
384 llvm::formatv("could not find script class: {0}", class_name).str(),
385 error);
386
387 // Get the static method from the class.
388 if (!class_obj.HasAttribute(method_name))
389 return ErrorWithMessage<T>(
390 caller_signature,
391 llvm::formatv("class {0} does not have method {1}", class_name,
392 method_name)
393 .str(),
394 error);
395
396 PythonCallable method =
397 class_obj.GetAttributeValue(method_name).AsType<PythonCallable>();
398 if (!method.IsAllocated())
399 return ErrorWithMessage<T>(caller_signature,
400 llvm::formatv("method {0}.{1} is not callable",
401 class_name, method_name)
402 .str(),
403 error);
404
405 // Transform the arguments.
406 std::tuple<Args...> original_args = std::forward_as_tuple(args...);
407 auto transformed_args = TransformArgs(original_args);
408
409 // Call the static method.
410 llvm::Expected<PythonObject> expected_return_object =
411 llvm::make_error<llvm::StringError>("Not initialized.",
412 llvm::inconvertibleErrorCode());
413 std::apply(
414 [&method, &expected_return_object](auto &&...args) {
415 llvm::consumeError(expected_return_object.takeError());
416 expected_return_object = method(args...);
417 },
418 transformed_args);
419
420 if (llvm::Error e = expected_return_object.takeError()) {
421 error = Status::FromError(std::move(e));
422 return ErrorWithMessage<T>(
423 caller_signature, "python static method could not be called", error);
424 }
425
426 PythonObject py_return = std::move(expected_return_object.get());
427
428 // Re-assign reference and pointer arguments if needed.
429 if (sizeof...(Args) > 0)
430 if (!ReassignPtrsOrRefsArgs(original_args, transformed_args))
431 return ErrorWithMessage<T>(
432 caller_signature,
433 "couldn't re-assign reference and pointer arguments", error);
434
435 // Extract value from Python object (handles unallocated case).
436 return ExtractValueFromPythonObject<T>(py_return, error);
437 }
438
439protected:
440 template <typename T = StructuredData::ObjectSP>
441 T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) {
442 return p.CreateStructuredObject();
443 }
444
445 template <typename T = StructuredData::ObjectSP, typename... Args>
446 T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) {
447 using namespace python;
448 using Locker = ScriptInterpreterPythonImpl::Locker;
449
450 std::string caller_signature =
451 llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
452 llvm::Twine(method_name) + llvm::Twine(")"))
453 .str();
454 if (!m_object_instance_sp)
455 return ErrorWithMessage<T>(caller_signature, "python object ill-formed",
456 error);
457
458 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
459 Locker::FreeLock);
460
461 PythonObject implementor(PyRefType::Borrowed,
462 (PyObject *)m_object_instance_sp->GetValue());
463
464 if (!implementor.IsAllocated())
465 return llvm::is_contained(GetAbstractMethods(), method_name)
466 ? ErrorWithMessage<T>(caller_signature,
467 "python implementor not allocated",
468 error)
469 : T{};
470
471 std::tuple<Args...> original_args = std::forward_as_tuple(args...);
472 auto transformed_args = TransformArgs(original_args);
473
474 llvm::Expected<PythonObject> expected_return_object =
475 llvm::make_error<llvm::StringError>("Not initialized.",
476 llvm::inconvertibleErrorCode());
477 std::apply(
478 [&implementor, &method_name, &expected_return_object](auto &&...args) {
479 llvm::consumeError(expected_return_object.takeError());
480 expected_return_object =
481 implementor.CallMethod(method_name.data(), args...);
482 },
483 transformed_args);
484
485 if (llvm::Error e = expected_return_object.takeError()) {
486 error = Status::FromError(std::move(e));
487 return ErrorWithMessage<T>(caller_signature,
488 "python method could not be called", error);
489 }
490
491 PythonObject py_return = std::move(expected_return_object.get());
492
493 // Now that we called the python method with the transformed arguments,
494 // we need to iterate again over both the original and transformed
495 // parameter pack, and transform back the parameter that were passed in
496 // the original parameter pack as references or pointers.
497 if (sizeof...(Args) > 0)
498 if (!ReassignPtrsOrRefsArgs(original_args, transformed_args))
499 return ErrorWithMessage<T>(
500 caller_signature,
501 "couldn't re-assign reference and pointer arguments", error);
502
503 if (!py_return.IsAllocated())
504 return {};
505 return ExtractValueFromPythonObject<T>(py_return, error);
506 }
507
508 template <typename... Args>
509 Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) {
511 Dispatch<Status>(method_name, error, std::forward<Args>(args)...);
512
513 return error;
514 }
515
516 template <typename T> T Transform(T object) {
517 // No Transformation for generic usage
518 return {object};
519 }
520
521 python::PythonObject Transform(bool arg) {
522 // Boolean arguments need to be turned into python objects.
523 return python::PythonBoolean(arg);
524 }
525
526 python::PythonObject Transform(const Status &arg) {
527 return python::SWIGBridge::ToSWIGWrapper(arg.Clone());
528 }
529
530 python::PythonObject Transform(Status &&arg) {
531 return python::SWIGBridge::ToSWIGWrapper(std::move(arg));
532 }
533
534 python::PythonObject Transform(const StructuredDataImpl &arg) {
535 return python::SWIGBridge::ToSWIGWrapper(arg);
536 }
537
538 python::PythonObject Transform(lldb::ExecutionContextRefSP arg) {
539 return python::SWIGBridge::ToSWIGWrapper(arg);
540 }
541
542 python::PythonObject Transform(lldb::TargetSP arg) {
543 return python::SWIGBridge::ToSWIGWrapper(arg);
544 }
545
546 python::PythonObject Transform(lldb::BreakpointSP arg) {
547 return python::SWIGBridge::ToSWIGWrapper(arg);
548 }
549
550 python::PythonObject Transform(lldb::BreakpointLocationSP arg) {
551 return python::SWIGBridge::ToSWIGWrapper(arg);
552 }
553
554 python::PythonObject Transform(lldb::ProcessSP arg) {
555 return python::SWIGBridge::ToSWIGWrapper(arg);
556 }
557
558 python::PythonObject Transform(lldb::ThreadSP arg) {
559 return python::SWIGBridge::ToSWIGWrapper(arg);
560 }
561
562 python::PythonObject Transform(lldb::StackFrameListSP arg) {
563 return python::SWIGBridge::ToSWIGWrapper(arg);
564 }
565
566 python::PythonObject Transform(lldb::ThreadPlanSP arg) {
567 return python::SWIGBridge::ToSWIGWrapper(arg);
568 }
569
570 python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) {
571 return python::SWIGBridge::ToSWIGWrapper(arg);
572 }
573
574 python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) {
575 return python::SWIGBridge::ToSWIGWrapper(arg);
576 }
577
578 python::PythonObject Transform(Event *arg) {
579 return python::SWIGBridge::ToSWIGWrapper(arg);
580 }
581
582 python::PythonObject Transform(const SymbolContext &arg) {
583 return python::SWIGBridge::ToSWIGWrapper(arg);
584 }
585
586 python::PythonObject Transform(lldb::StreamSP arg) {
587 return python::SWIGBridge::ToSWIGWrapper(arg.get());
588 }
589
590 python::PythonObject Transform(lldb::StackFrameSP arg) {
591 return python::SWIGBridge::ToSWIGWrapper(arg);
592 }
593
594 python::PythonObject Transform(lldb::DataExtractorSP arg) {
595 return python::SWIGBridge::ToSWIGWrapper(arg);
596 }
597
598 python::PythonObject Transform(lldb::DescriptionLevel arg) {
599 return python::SWIGBridge::ToSWIGWrapper(arg);
600 }
601
602 template <typename T, typename U>
603 void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
604 // If U is not a PythonObject, don't touch it!
605 }
606
607 template <typename T>
608 void ReverseTransform(T &original_arg, python::PythonObject transformed_arg,
609 Status &error) {
610 original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error);
611 }
612
613 void ReverseTransform(bool &original_arg,
614 python::PythonObject transformed_arg, Status &error) {
615 python::PythonBoolean boolean_arg = python::PythonBoolean(
616 python::PyRefType::Borrowed, transformed_arg.get());
617 if (boolean_arg.IsValid())
618 original_arg = boolean_arg.GetValue();
619 else
620 error = Status::FromErrorStringWithFormatv(
621 "{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION);
622 }
623
624 template <std::size_t... I, typename... Args>
625 auto TransformTuple(const std::tuple<Args...> &args,
626 std::index_sequence<I...>) {
627 return std::make_tuple(Transform(std::get<I>(args))...);
628 }
629
630 // This will iterate over the Dispatch parameter pack and replace in-place
631 // every `lldb_private` argument that has a SB counterpart.
632 template <typename... Args>
633 auto TransformArgs(const std::tuple<Args...> &args) {
634 return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>());
635 }
636
637 template <typename T, typename U>
638 void TransformBack(T &original_arg, U transformed_arg, Status &error) {
639 ReverseTransform(original_arg, transformed_arg, error);
640 }
641
642 template <std::size_t... I, typename... Ts, typename... Us>
643 bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
644 std::tuple<Us...> &transformed_args,
645 std::index_sequence<I...>) {
647 (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args),
648 error),
649 ...);
650 return error.Success();
651 }
652
653 template <typename... Ts, typename... Us>
654 bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
655 std::tuple<Us...> &transformed_args) {
656 if (sizeof...(Ts) != sizeof...(Us))
657 return false;
658
659 return ReassignPtrsOrRefsArgs(original_args, transformed_args,
660 std::make_index_sequence<sizeof...(Ts)>());
661 }
662
663 template <typename T, typename... Args>
664 void FormatArgs(std::string &fmt, T arg, Args... args) const {
665 FormatArgs(fmt, arg);
666 FormatArgs(fmt, args...);
667 }
668
669 template <typename T> void FormatArgs(std::string &fmt, T arg) const {
670 fmt += python::PythonFormat<T>::format;
671 }
672
673 void FormatArgs(std::string &fmt) const {}
674
675 // The lifetime is managed by the ScriptInterpreter
676 ScriptInterpreterPythonImpl &m_interpreter;
677};
678
679template <>
681ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
682 python::PythonObject &p, Status &error);
683
684template <>
686ScriptedPythonInterface::ExtractValueFromPythonObject<
687 StructuredData::DictionarySP>(python::PythonObject &p, Status &error);
688
689template <>
690Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
691 python::PythonObject &p, Status &error);
692
693template <>
694Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
695 python::PythonObject &p, Status &error);
696
697template <>
699ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
700 python::PythonObject &p, Status &error);
701
702template <>
704ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
705 python::PythonObject &p, Status &error);
706
707template <>
709ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ThreadSP>(
710 python::PythonObject &p, Status &error);
711
712template <>
714ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameSP>(
715 python::PythonObject &p, Status &error);
716
717template <>
719ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>(
720 python::PythonObject &p, Status &error);
721
722template <>
724ScriptedPythonInterface::ExtractValueFromPythonObject<
725 lldb::BreakpointLocationSP>(python::PythonObject &p, Status &error);
726
727template <>
728lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
729 lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error);
730
731template <>
732lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
733 lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error);
734
735template <>
737ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
738 python::PythonObject &p, Status &error);
739
740template <>
741std::optional<MemoryRegionInfo>
742ScriptedPythonInterface::ExtractValueFromPythonObject<
743 std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
744
745template <>
747ScriptedPythonInterface::ExtractValueFromPythonObject<
748 lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error);
749
750template <>
752ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DescriptionLevel>(
753 python::PythonObject &p, Status &error);
754
755template <>
757ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameListSP>(
758 python::PythonObject &p, Status &error);
759
760} // namespace lldb_private
761
762#endif // LLDB_ENABLE_PYTHON
763#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:369
An error handling class.
Definition Status.h:118
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Array > ArraySP
Defines a symbol context baton that can be handed other debug core functions.
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:332
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::BreakpointLocation > BreakpointLocationSP
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ProcessAttachInfo > ProcessAttachInfoSP
std::shared_ptr< lldb_private::Stream > StreamSP
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
std::shared_ptr< lldb_private::ProcessLaunchInfo > ProcessLaunchInfoSP
std::shared_ptr< lldb_private::StackFrameList > StackFrameListSP
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP