LLDB mainline
ScriptedFrame.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 "ScriptedFrame.h"
11
12#include "lldb/Core/Address.h"
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/Module.h"
28#include "lldb/Target/Thread.h"
33#include "lldb/Utility/Log.h"
40#include "lldb/lldb-forward.h"
41#include "llvm/Support/ErrorHandling.h"
42
43#include <memory>
44
45using namespace lldb;
46using namespace lldb_private;
47
49
51 lldbassert(m_script_object_sp && "Invalid Script Object.");
52 lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");
53}
54
55llvm::Expected<std::shared_ptr<ScriptedFrame>>
57 ScriptedThreadInterfaceSP scripted_thread_interface_sp,
59 StructuredData::Generic *script_object) {
60 if (!thread_sp || !thread_sp->IsValid())
61 return llvm::createStringError("invalid thread");
62
63 ProcessSP process_sp = thread_sp->GetProcess();
64 if (!process_sp || !process_sp->IsValid())
65 return llvm::createStringError("invalid process");
66
67 ScriptInterpreter *script_interp =
68 process_sp->GetTarget().GetDebugger().GetScriptInterpreter();
69 if (!script_interp)
70 return llvm::createStringError("no script interpreter");
71
72 auto scripted_frame_interface = script_interp->CreateScriptedFrameInterface();
73 if (!scripted_frame_interface)
74 return llvm::createStringError("failed to create scripted frame interface");
75
76 llvm::StringRef frame_class_name;
77 if (!script_object) {
78 // If no script object is provided and we have a scripted thread interface,
79 // try to get the frame class name from it.
80 if (scripted_thread_interface_sp) {
81 std::optional<std::string> class_name =
82 scripted_thread_interface_sp->GetScriptedFramePluginName();
83 if (!class_name || class_name->empty())
84 return llvm::createStringError(
85 "failed to get scripted frame class name");
86 frame_class_name = *class_name;
87 } else {
88 return llvm::createStringError(
89 "no script object provided and no scripted thread interface");
90 }
91 }
92
93 ExecutionContext exe_ctx(thread_sp);
94 auto obj_or_err = scripted_frame_interface->CreatePluginObject(
95 frame_class_name, exe_ctx, args_sp, script_object);
96
97 if (!obj_or_err)
98 return llvm::createStringError(
99 "failed to create script object: %s",
100 llvm::toString(obj_or_err.takeError()).c_str());
101
102 StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
103
104 if (!owned_script_object_sp->IsValid())
105 return llvm::createStringError("created script object is invalid");
106
107 lldb::user_id_t frame_id = scripted_frame_interface->GetID();
108
109 lldb::addr_t pc = scripted_frame_interface->GetPC();
110 lldb::addr_t cfa = scripted_frame_interface->GetCFA();
111
112 SymbolContext sc;
113 Address symbol_addr;
114 if (pc != LLDB_INVALID_ADDRESS) {
115 pc = process_sp->FixCodeAddress(pc);
116 symbol_addr.SetLoadAddress(pc, &process_sp->GetTarget());
117 symbol_addr.CalculateSymbolContext(&sc);
118 }
119
120 std::optional<SymbolContext> maybe_sym_ctx =
121 scripted_frame_interface->GetSymbolContext();
122 if (maybe_sym_ctx)
123 sc = *maybe_sym_ctx;
124
125 return std::make_shared<ScriptedFrame>(thread_sp, scripted_frame_interface,
126 frame_id, pc, cfa, sc,
127 owned_script_object_sp);
128}
129
131 ScriptedFrameInterfaceSP interface_sp,
133 lldb::addr_t cfa, SymbolContext &sym_ctx,
134 StructuredData::GenericSP script_object_sp)
135 : StackFrame(thread_sp, /*frame_idx=*/id,
136 /*concrete_frame_idx=*/id, /*reg_context_sp=*/nullptr,
137 /*cfa=*/cfa, /*pc=*/pc,
138 /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),
139 m_scripted_frame_interface_sp(interface_sp),
140 m_script_object_sp(script_object_sp) {
141 // FIXME: This should be part of the base class constructor.
143
144 llvm::Expected<lldb::RegisterContextSP> reg_ctx_or_err =
146 if (!reg_ctx_or_err) {
147 std::optional<lldb::user_id_t> debugger_id;
148 if (ProcessSP process_sp = thread_sp->GetProcess())
149 debugger_id = process_sp->GetTarget().GetDebugger().GetID();
150 Debugger::ReportError("failed to create scripted frame register context: " +
151 llvm::toString(reg_ctx_or_err.takeError()),
152 debugger_id);
153 return;
154 }
155
156 m_reg_context_sp = *reg_ctx_or_err;
157}
158
160
163 std::optional<std::string> function_name = GetInterface()->GetFunctionName();
164 if (!function_name)
166 return ConstString(*function_name).AsCString(nullptr);
167}
168
171 std::optional<std::string> function_name =
172 GetInterface()->GetDisplayFunctionName();
173 if (!function_name)
175 return ConstString(*function_name).AsCString(nullptr);
176}
177
178bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }
179
181 return GetInterface()->IsArtificial();
182}
183
184bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }
185
189
190llvm::Expected<DynamicRegisterInfoSP> ScriptedFrame::GetDynamicRegisterInfo() {
192
193 StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
194 if (!reg_info)
195 return llvm::createStringError(
196 "failed to get scripted frame registers info");
197
198 ThreadSP thread_sp = m_thread_wp.lock();
199 if (!thread_sp || !thread_sp->IsValid())
200 return llvm::createStringError("invalid thread");
201
202 ProcessSP process_sp = thread_sp->GetProcess();
203 if (!process_sp || !process_sp->IsValid())
204 return llvm::createStringError("invalid process");
205
207 *reg_info, process_sp->GetTarget().GetArchitecture());
208 if (!register_info_sp)
209 return llvm::createStringError(
210 "failed to create scripted frame registers info");
211
212 return register_info_sp;
213}
214
215llvm::Expected<lldb::RegisterContextSP> ScriptedFrame::CreateRegisterContext() {
217 return llvm::createStringError("invalid scripted frame interface");
218
219 ThreadSP thread_sp = GetThread();
220 if (!thread_sp)
221 return llvm::createStringError("invalid thread");
222
223 // A frame that reports no register data has no register context. That is a
224 // valid state, not a failure: only frames that expose registers implement it.
225 std::optional<std::string> reg_data =
226 m_scripted_frame_interface_sp->GetRegisterContext();
227 if (!reg_data)
229
230 DataBufferSP data_sp(
231 std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
232
233 if (!data_sp->GetByteSize())
234 return llvm::createStringError("failed to copy raw registers data");
235
236 llvm::Expected<DynamicRegisterInfoSP> register_info_or_err =
238 if (!register_info_or_err)
239 return register_info_or_err.takeError();
240
241 std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
242 std::make_shared<RegisterContextMemory>(*thread_sp, GetFrameIndex(),
243 std::move(*register_info_or_err),
245
246 reg_ctx_memory->SetAllRegisterData(data_sp);
247
248 return reg_ctx_memory;
249}
250
254
256 bool include_synthetic_vars,
257 Status *error_ptr) {
258 PopulateVariableListFromInterface(include_synthetic_vars);
259 return m_variable_list_sp.get();
260}
261
264 bool include_synthetic_vars,
265 bool must_have_valid_location) {
266 PopulateVariableListFromInterface(include_synthetic_vars);
267 return m_variable_list_sp;
268}
269
271 bool include_synthetic_vars) {
272 // Fetch values from the interface.
273 ValueObjectListSP value_list_sp = GetInterface()->GetVariables();
274 if (!value_list_sp)
275 return;
276
277 // Convert what we can into a variable.
278 m_variable_list_sp = std::make_shared<VariableList>();
279
280 for (uint32_t i = 0, e = value_list_sp->GetSize(); i < e; ++i) {
281 ValueObjectSP v = value_list_sp->GetValueObjectAtIndex(i);
282 if (!v)
283 continue;
284
285 // Ask the interface about the value type of this variable. If it doesn't
286 // specify any, use the original value type.
287 lldb::ValueType vt = GetInterface()->GetValueTypeForVariable(v).value_or(
288 GetSyntheticValueType(v->GetValueType()));
289
290 if (IsSyntheticValueType(vt) && !include_synthetic_vars)
291 continue;
292
293 // Just make up a variable - the frame variable dumper just passes it
294 // back in to GetValueObjectForFrameVariable, so we really just need to
295 // make sure the name and type are correct. We create IDs based on
296 // value_list_sp in order to make sure they're unique.
297 m_variable_list_sp->AddVariable(std::make_shared<lldb_private::Variable>(
298 (lldb::user_id_t)value_list_sp->GetSize() + i,
299 v->GetName().GetCString(), v->GetName().GetCString(), nullptr, vt,
300 /*owner_scope=*/nullptr,
301 /*scope_range=*/Variable::RangeList{},
302 /*decl=*/nullptr, DWARFExpressionList{}, /*external=*/false,
303 /*artificial=*/true, /*location_is_constant_data=*/false));
304 }
305}
306
308 const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic) {
309 // Fetch values from the interface.
310 ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
311 if (!values)
312 return {};
313
314 lldb::ValueObjectSP valobj_sp = values->FindValueObjectByValueName(
315 variable_sp->GetName().AsCString(nullptr));
316 if (!valobj_sp)
317 return {};
318
319 return ValueObjectSynthesizedValue::Create(*valobj_sp,
320 variable_sp->GetScope());
321}
322
324 // Fetch values from the interface.
325 ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
326 if (!values)
327 return {};
328
329 lldb::ValueObjectSP valobj_sp =
330 values->FindValueObjectByValueName(name.AsCString(nullptr));
331 if (!valobj_sp)
332 return {};
333
334 // Present the ValueObject under the same ValueType the frame's variable list
335 // would, so reaching a variable by name and by enumeration agree.
336 if (m_variable_list_sp) {
337 if (VariableSP variable_sp = m_variable_list_sp->FindVariable(name))
338 return ValueObjectSynthesizedValue::Create(*valobj_sp,
339 variable_sp->GetScope());
340 }
341
342 return valobj_sp;
343}
344
346 llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
347 uint32_t options, lldb::VariableSP &var_sp, Status &error,
348 lldb::DILMode mode) {
349 // Unless the frame implementation knows how to create variables (which it
350 // doesn't), we can't construct anything for the variable. This may seem
351 // somewhat out of place, but it's basically because of how this API is used -
352 // the print command uses this API to fill in var_sp; and this implementation
353 // can't do that!
354 // FIXME: We should make it possible for the frame implementation to create
355 // Variable objects.
356 (void)var_sp;
357 // Otherwise, delegate to the scripted frame interface pointer.
358 return m_scripted_frame_interface_sp->GetValueObjectForVariableExpression(
359 var_expr, options, error);
360}
361
362llvm::Expected<lldb::ThreadPlanSP>
364 llvm::Expected<ScriptedMetadata> metadata =
365 m_scripted_frame_interface_sp->GetThreadPlanMetadataForStepType(
366 step_type);
367 if (!metadata)
368 return metadata.takeError();
369
370 // Returning a ScriptedMetadata with an empty class name means that the
371 // scripted frame doesn't know how to step. That's not an error, but don't
372 // try to make a thread plan in this case. The bool operator of
373 // ScriptedMetadata checks the class name...
374
375 ThreadSP thread_sp = GetThread();
376 if (thread_sp && !metadata->GetClassName().empty()) {
377 lldb::ThreadPlanSP new_plan_sp(
378 new ScriptedThreadPlan(*thread_sp.get(), *metadata));
379 return new_plan_sp;
380 }
381
382 return lldb::ThreadPlanSP();
383}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
A section + offset based address class.
Definition Address.h:62
bool SetLoadAddress(lldb::addr_t load_addr, Target *target, bool allow_section_end=false)
Set the address to represent load_addr.
Definition Address.cpp:1029
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
Definition Address.cpp:820
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty) const
Get the string value as a C string.
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
static void ReportError(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report error events.
static std::unique_ptr< DynamicRegisterInfo > Create(const StructuredData::Dictionary &dict, const ArchSpec &arch)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
virtual lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface()
lldb::VariableListSP m_variable_list_sp
llvm::Expected< lldb::DynamicRegisterInfoSP > GetDynamicRegisterInfo()
static llvm::Expected< std::shared_ptr< ScriptedFrame > > Create(lldb::ThreadSP thread_sp, lldb::ScriptedThreadInterfaceSP scripted_thread_interface_sp, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_object=nullptr)
Create a ScriptedFrame from a object instanciated in the script interpreter.
lldb::ValueObjectSP FindVariable(ConstString name) override
Attempt to reconstruct the ValueObject for a variable with a given name from within the current Stack...
ScriptedFrame(lldb::ThreadSP thread_sp, lldb::ScriptedFrameInterfaceSP interface_sp, lldb::user_id_t frame_idx, lldb::addr_t pc, lldb::addr_t cfa, SymbolContext &sym_ctx, StructuredData::GenericSP script_object_sp=nullptr)
bool IsArtificial() const override
Query whether this frame is artificial (e.g a synthesized result of inferring missing tail call frame...
lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error, lldb::DILMode mode=lldb::eDILModeFull) override
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
const char * GetFunctionName() override
Get the frame's demangled name.
lldb::ScriptedFrameInterfaceSP GetInterface() const
void PopulateVariableListFromInterface(bool include_synthetic_vars=true)
void CheckInterpreterAndScriptObject() const
lldb::ScriptedFrameInterfaceSP m_scripted_frame_interface_sp
llvm::Expected< lldb::ThreadPlanSP > GetThreadPlanForStepType(lldb::StepType step_type) override
lldb_private::StructuredData::GenericSP m_script_object_sp
lldb::RegisterContextSP GetRegisterContext() override
Get the RegisterContext for this frame, if possible.
bool IsHidden() override
Query whether this frame should be hidden from backtraces.
lldb::VariableListSP GetInScopeVariableList(bool get_file_globals, bool include_synthetic_vars, bool must_have_valid_location=false) override
Retrieve the list of variables that are in scope at this StackFrame's pc.
VariableList * GetVariableList(bool get_file_globals, bool include_synthetic_vars, lldb_private::Status *error_ptr) override
Retrieve the list of variables whose scope either:
bool IsInlined() override
Query whether this frame is a concrete frame on the call stack, or if it is an inlined frame derived ...
const char * GetDisplayFunctionName() override
Get the frame's demangled display name.
lldb::ValueObjectSP GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic) override
Create a ValueObject for a given Variable in this StackFrame.
llvm::Expected< lldb::RegisterContextSP > CreateRegisterContext()
lldb::ThreadSP GetThread() const
Definition StackFrame.h:135
virtual const char * GetFunctionName()
Get the frame's demangled name.
lldb::ThreadWP m_thread_wp
For StackFrame and derived classes only.
Definition StackFrame.h:608
lldb::RegisterContextSP m_reg_context_sp
Definition StackFrame.h:611
@ Synthetic
An synthetic stack frame (e.g.
Definition StackFrame.h:72
virtual const char * GetDisplayFunctionName()
Get the frame's demangled display name.
virtual uint32_t GetFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList.
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa, bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind, bool artificial, bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr)
Construct a StackFrame object without supplying a RegisterContextSP.
An error handling class.
Definition Status.h:118
std::shared_ptr< Generic > GenericSP
std::shared_ptr< Dictionary > DictionarySP
Defines a symbol context baton that can be handed other debug core functions.
static lldb::ValueObjectSP Create(ValueObject &valobj, lldb::ValueType type)
RangeVector< lldb::addr_t, lldb::addr_t > RangeList
Definition Variable.h:27
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
constexpr bool IsSyntheticValueType(lldb::ValueType vt)
Return true if vt represents a synthetic value, false if not.
Definition ValueType.h:27
constexpr lldb::ValueType GetSyntheticValueType(lldb::ValueType base)
Given a base value type, return a version that carries the synthetic bit.
Definition ValueType.h:22
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
std::shared_ptr< lldb_private::DynamicRegisterInfo > DynamicRegisterInfoSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::ScriptedThreadInterface > ScriptedThreadInterfaceSP
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
DILMode
Data Inspection Language (DIL) evaluation modes.
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP