LLDB mainline
ScriptedFramePythonInterface.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 "lldb/Host/Config.h"
15#include "lldb/Utility/Log.h"
18
19#include "../SWIGPythonBridge.h"
22#include <optional>
23
24using namespace lldb;
25using namespace lldb_private;
26using namespace lldb_private::python;
28
32
33llvm::Expected<StructuredData::GenericSP>
35 const llvm::StringRef class_name, ExecutionContext &exe_ctx,
37 ExecutionContextRefSP exe_ctx_ref_sp =
38 std::make_shared<ExecutionContextRef>(exe_ctx);
39 ScriptedMetadata scripted_metadata(class_name, args_sp);
41 scripted_metadata, script_obj, exe_ctx_ref_sp, args_sp);
42}
43
46 LogAndDefault(Dispatch("get_id"), LLVM_PRETTY_FUNCTION);
47 if (!obj)
49
50 return obj->GetUnsignedIntegerValue(LLDB_INVALID_FRAME_ID);
51}
52
55 LogAndDefault(Dispatch("get_pc"), LLVM_PRETTY_FUNCTION);
56 if (!obj)
58
59 return obj->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
60}
61
64 LogAndDefault(Dispatch("get_cfa"), LLVM_PRETTY_FUNCTION);
65 if (!obj)
67
68 return obj->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
69}
70
71std::optional<SymbolContext> ScriptedFramePythonInterface::GetSymbolContext() {
72 llvm::Expected<SymbolContext> sym_ctx_or_err =
73 Dispatch<SymbolContext>("get_symbol_context");
74 if (!sym_ctx_or_err) {
75 LLDB_LOG_ERROR(GetLog(LLDBLog::Script), sym_ctx_or_err.takeError(),
76 "get_symbol_context failed: {0}");
77 return {};
78 }
79
80 return *sym_ctx_or_err;
81}
82
85 LogAndDefault(Dispatch("get_function_name"), LLVM_PRETTY_FUNCTION);
86 if (!obj)
87 return {};
88
89 return obj->GetStringValue().str();
90}
91
92std::optional<std::string>
95 Dispatch("get_display_function_name"), LLVM_PRETTY_FUNCTION);
96 if (!obj)
97 return {};
98
99 return obj->GetStringValue().str();
100}
101
104 LogAndDefault(Dispatch("is_inlined"), LLVM_PRETTY_FUNCTION);
105 if (!obj)
106 return false;
107
108 return obj->GetBooleanValue();
109}
110
113 LogAndDefault(Dispatch("is_artificial"), LLVM_PRETTY_FUNCTION);
114 if (!obj)
115 return false;
116
117 return obj->GetBooleanValue();
118}
119
122 LogAndDefault(Dispatch("is_hidden"), LLVM_PRETTY_FUNCTION);
123 if (!obj)
124 return false;
125
126 return obj->GetBooleanValue();
127}
128
132 LLVM_PRETTY_FUNCTION);
133 if (!dict)
134 return {};
135
136 return dict;
137}
138
141 LogAndDefault(Dispatch("get_register_context"), LLVM_PRETTY_FUNCTION);
142 if (!obj)
143 return {};
144
145 return obj->GetStringValue().str();
146}
147
152
153std::optional<lldb::ValueType>
155 lldb::ValueObjectSP value) {
156 return LogAndDefault(Dispatch<std::optional<lldb::ValueType>>(
157 "get_value_type_for_variable", std::move(value)),
158 LLVM_PRETTY_FUNCTION);
159}
160
163 llvm::StringRef expr, uint32_t options, Status &status) {
164 llvm::Expected<lldb::ValueObjectSP> val_or_err =
165 Dispatch<lldb::ValueObjectSP>("get_value_for_variable_expression",
166 expr.data(), options, status);
167 if (!val_or_err) {
168 status = Status::FromError(val_or_err.takeError());
169 return {};
170 }
171
172 return *val_or_err;
173}
174
175llvm::Expected<ScriptedMetadata>
177 lldb::StepType step_type) {
179
180 // A frame that doesn't implement `get_plan_spec_for_step_type` simply has no
181 // plan to offer, which Dispatch reports as an UnimplementedError. Any other
182 // failure - notably an exception raised inside the method - propagates.
183 llvm::Expected<std::optional<StructuredData::DictionarySP>> dict_or_err =
185 "get_plan_spec_for_step_type", step_type);
186 if (!dict_or_err)
187 return llvm::joinErrors(
188 llvm::createStringError(
189 "error dispatching get_plan_spec_for_step_type"),
190 dict_or_err.takeError());
191
192 // The return value is an StructuredData::Dictionary with the class name and
193 // the extra args for the call:
194 StructuredData::DictionarySP dict_sp = dict_or_err->value_or(nullptr);
195 if (!dict_sp || !dict_sp->IsValid())
196 return no_plan_return;
197
198 StructuredData::ObjectSP obj = dict_sp->GetValueForKey("class_name");
199 if (!obj)
200 return llvm::createStringError("Required 'class_name' field not provided.");
201
202 std::string class_string = obj->GetStringValue().str();
203 // Passing out an empty class name is they way to say the frame provider
204 // doesn't know how to step from here, and the regular method should be tried
205 // instead. So we only need to make sure the class exists if we were given a
206 // string:
207 if (!class_string.empty()) {
208 const char *class_str = class_string.c_str();
209 if (!m_interpreter.CheckObjectExists(class_str))
210 return llvm::createStringError(
211 "class_name specified a class: '%s' that does not exist.", class_str);
212 }
213
214 // Look for extra args, this is optional:
215 StructuredData::Dictionary *extra_args_ptr = nullptr;
216 StructuredData::DictionarySP extra_args_sp;
217 if (dict_sp->GetValueForKeyAsDictionary("extra_args", extra_args_ptr))
218 extra_args_sp = std::static_pointer_cast<StructuredData::Dictionary>(
219 extra_args_ptr->shared_from_this());
220
221 // Now make a new thread plan for stepping using the provided class name and
222 // extra args.
223 ScriptedMetadata plan_metadata(class_string, extra_args_sp);
224 return plan_metadata;
225}
226
230 "Provide frame state for scripted threads and frame providers.",
232 {});
233}
234
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
ScriptInterpreterPythonImpl::Locker Locker
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
std::optional< std::string > GetRegisterContext() override
std::optional< lldb::ValueType > GetValueTypeForVariable(lldb::ValueObjectSP value) override
Report which kind of variable valobj is presented as, for instance eValueTypeVariableLocal to have it...
llvm::Expected< ScriptedMetadata > GetThreadPlanMetadataForStepType(lldb::StepType step_type) override
std::optional< std::string > GetDisplayFunctionName() override
std::optional< SymbolContext > GetSymbolContext() override
StructuredData::DictionarySP GetRegisterInfo() override
lldb::ValueObjectSP GetValueObjectForVariableExpression(llvm::StringRef expr, uint32_t options, Status &status) override
std::optional< std::string > GetFunctionName() override
llvm::Expected< StructuredData::GenericSP > CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj=nullptr) override
ScriptedFramePythonInterface(ScriptInterpreterPythonImpl &interpreter)
static bool CreateInstance(lldb::ScriptLanguage language, ScriptedInterfaceUsages usages)
ScriptInterpreterPythonImpl & m_interpreter
static T LogAndDefault(llvm::Expected< T > value_or_err, llvm::StringRef caller)
Log the failure in value_or_err and fall back to a default-constructed T.
ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter)
llvm::Expected< T > Dispatch(llvm::StringRef method_name, Args &&...args)
Call method_name on the scripted object.
llvm::Expected< std::optional< T > > DispatchToOptional(llvm::StringRef method_name, Args &&...args)
Call an optional method_name, reporting "the script doesn't implementit" as std::nullopt rather than ...
llvm::Expected< StructuredData::GenericSP > CreatePluginObject(const ScriptedMetadata &scripted_metadata, StructuredData::Generic *script_obj, Args... args)
An error handling class.
Definition Status.h:118
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_FRAME_ID
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
@ eScriptLanguagePython
@ eScriptedExtensionScriptedFrame
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
uint64_t user_id_t
Definition lldb-types.h:83
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP