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"
14#include "lldb/Utility/Log.h"
17
18#include "../SWIGPythonBridge.h"
21#include <optional>
22
23using namespace lldb;
24using namespace lldb_private;
25using namespace lldb_private::python;
27
31
32llvm::Expected<StructuredData::GenericSP>
34 const llvm::StringRef class_name, ExecutionContext &exe_ctx,
36 ExecutionContextRefSP exe_ctx_ref_sp =
37 std::make_shared<ExecutionContextRef>(exe_ctx);
38 ScriptedMetadata scripted_metadata(class_name, args_sp);
40 scripted_metadata, script_obj, exe_ctx_ref_sp, args_sp);
41}
42
46
47 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
48 error))
50
51 return obj->GetUnsignedIntegerValue(LLDB_INVALID_FRAME_ID);
52}
53
57
58 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
59 error))
61
62 return obj->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
63}
64
67 StructuredData::ObjectSP obj = Dispatch("get_cfa", error);
68
69 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
70 error))
72
73 return obj->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
74}
75
76std::optional<SymbolContext> ScriptedFramePythonInterface::GetSymbolContext() {
78 auto sym_ctx = Dispatch<SymbolContext>("get_symbol_context", error);
79
80 if (error.Fail()) {
81 return ErrorWithMessage<SymbolContext>(LLVM_PRETTY_FUNCTION,
82 error.AsCString(), error);
83 }
84
85 return sym_ctx;
86}
87
90 StructuredData::ObjectSP obj = Dispatch("get_function_name", error);
91
92 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
93 error))
94 return {};
95
96 return obj->GetStringValue().str();
97}
98
99std::optional<std::string>
102 StructuredData::ObjectSP obj = Dispatch("get_display_function_name", error);
103
104 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
105 error))
106 return {};
107
108 return obj->GetStringValue().str();
109}
110
113 StructuredData::ObjectSP obj = Dispatch("is_inlined", error);
114
115 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
116 error))
117 return false;
118
119 return obj->GetBooleanValue();
120}
121
124 StructuredData::ObjectSP obj = Dispatch("is_artificial", error);
125
126 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
127 error))
128 return false;
129
130 return obj->GetBooleanValue();
131}
132
135 StructuredData::ObjectSP obj = Dispatch("is_hidden", error);
136
137 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
138 error))
139 return false;
140
141 return obj->GetBooleanValue();
142}
143
147 Dispatch<StructuredData::DictionarySP>("get_register_info", error);
148
149 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
150 error))
151 return {};
152
153 return dict;
154}
155
158 StructuredData::ObjectSP obj = Dispatch("get_register_context", error);
159
160 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
161 error))
162 return {};
163
164 return obj->GetAsString()->GetValue().str();
165}
166
169 auto vals = Dispatch<lldb::ValueObjectListSP>("get_variables", error);
170
171 if (error.Fail()) {
172 return ErrorWithMessage<lldb::ValueObjectListSP>(LLVM_PRETTY_FUNCTION,
173 error.AsCString(), error);
174 }
175
176 return vals;
177}
178
179std::optional<lldb::ValueType>
181 lldb::ValueObjectSP value) {
184 "get_value_type_for_variable", error, std::move(value));
185
186 if (error.Fail()) {
188 LLVM_PRETTY_FUNCTION, error.AsCString(), error);
189 }
190
191 return val;
192}
193
196 llvm::StringRef expr, uint32_t options, Status &status) {
197 Status dispatch_error;
198 auto val = Dispatch<lldb::ValueObjectSP>("get_value_for_variable_expression",
199 dispatch_error, expr.data(), options,
200 status);
201
202 if (dispatch_error.Fail()) {
204 LLVM_PRETTY_FUNCTION, dispatch_error.AsCString(), dispatch_error);
205 }
206
207 return val;
208}
209
210llvm::Expected<ScriptedMetadata>
212 lldb::StepType step_type) {
214
217 "get_plan_spec_for_step_type", error, step_type);
218 if (error.Fail()) {
219 // There are two cases here. The `get_plan_spec_for_step_type` didn't
220 // exist, in which case we should return no_plan_return
221 // FIXME - Dispatch should distinguish between these two cases in a way
222 // that's more definitive than this.
223 llvm::StringRef err_str(error.AsCString());
224 if (err_str.contains(
225 "object has no attribute 'get_plan_spec_for_step_type'"))
226 return no_plan_return;
227 else
228 return llvm::createStringError(
229 "error dispatching get_plan_spec_for_step_type: %s",
230 error.AsCString());
231 }
232
233 // The return value is an StructuredData::Dictionary with the class name and
234 // the extra args for the call:
235 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION,
236 dict_sp, error))
237 return llvm::createStringError(
238 "return from get_plan_spec_for_step_type not a valid object: %s",
239 error.AsCString());
240
241 StructuredData::ObjectSP obj = dict_sp->GetValueForKey("class_name");
242 if (!obj)
243 return llvm::createStringError("Required 'class_name' field not provided.");
244
245 std::string class_string = obj->GetStringValue().str();
246 // Passing out an empty class name is they way to say the frame provider
247 // doesn't know how to step from here, and the regular method should be tried
248 // instead. So we only need to make sure the class exists if we were given a
249 // string:
250 if (!class_string.empty()) {
251 const char *class_str = class_string.c_str();
252 if (!m_interpreter.CheckObjectExists(class_str))
253 return llvm::createStringError(
254 "class_name specified a class: '%s' that does not exist.", class_str);
255 }
256
257 // Look for extra args, this is optional:
258 StructuredData::Dictionary *extra_args_ptr = nullptr;
259 StructuredData::DictionarySP extra_args_sp;
260 if (dict_sp->GetValueForKeyAsDictionary("extra_args", extra_args_ptr))
261 extra_args_sp = std::static_pointer_cast<StructuredData::Dictionary>(
262 extra_args_ptr->shared_from_this());
263
264 // Now make a new thread plan for stepping using the provided class name and
265 // extra args.
266 ScriptedMetadata plan_metadata(class_string, extra_args_sp);
267 return plan_metadata;
268}
269
273 "Provide frame state for scripted threads and frame providers.",
275 {});
276}
277
static llvm::raw_ostream & error(Stream &strm)
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 Ret ErrorWithMessage(llvm::StringRef caller_name, llvm::StringRef user_msg, Status &error, LLDBLog log_category=LLDBLog::Process)
static bool CheckStructuredDataObject(llvm::StringRef caller, T obj, Status &error)
static bool CreateInstance(lldb::ScriptLanguage language, ScriptedInterfaceUsages usages)
ScriptInterpreterPythonImpl & m_interpreter
ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter)
T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args)
llvm::Expected< StructuredData::GenericSP > CreatePluginObject(const ScriptedMetadata &scripted_metadata, StructuredData::Generic *script_obj, Args... args)
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:293
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition Status.cpp:194
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.
@ 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