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"
27#include "lldb/Target/Thread.h"
31#include "lldb/Utility/Log.h"
37#include "lldb/lldb-forward.h"
38#include "llvm/Support/ErrorHandling.h"
39
40#include <memory>
41
42using namespace lldb;
43using namespace lldb_private;
44
46
48 lldbassert(m_script_object_sp && "Invalid Script Object.");
49 lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");
50}
51
52llvm::Expected<std::shared_ptr<ScriptedFrame>>
54 ScriptedThreadInterfaceSP scripted_thread_interface_sp,
56 StructuredData::Generic *script_object) {
57 if (!thread_sp || !thread_sp->IsValid())
58 return llvm::createStringError("invalid thread");
59
60 ProcessSP process_sp = thread_sp->GetProcess();
61 if (!process_sp || !process_sp->IsValid())
62 return llvm::createStringError("invalid process");
63
64 ScriptInterpreter *script_interp =
65 process_sp->GetTarget().GetDebugger().GetScriptInterpreter();
66 if (!script_interp)
67 return llvm::createStringError("no script interpreter");
68
69 auto scripted_frame_interface = script_interp->CreateScriptedFrameInterface();
70 if (!scripted_frame_interface)
71 return llvm::createStringError("failed to create scripted frame interface");
72
73 llvm::StringRef frame_class_name;
74 if (!script_object) {
75 // If no script object is provided and we have a scripted thread interface,
76 // try to get the frame class name from it.
77 if (scripted_thread_interface_sp) {
78 std::optional<std::string> class_name =
79 scripted_thread_interface_sp->GetScriptedFramePluginName();
80 if (!class_name || class_name->empty())
81 return llvm::createStringError(
82 "failed to get scripted frame class name");
83 frame_class_name = *class_name;
84 } else {
85 return llvm::createStringError(
86 "no script object provided and no scripted thread interface");
87 }
88 }
89
90 ExecutionContext exe_ctx(thread_sp);
91 auto obj_or_err = scripted_frame_interface->CreatePluginObject(
92 frame_class_name, exe_ctx, args_sp, script_object);
93
94 if (!obj_or_err)
95 return llvm::createStringError(
96 "failed to create script object: %s",
97 llvm::toString(obj_or_err.takeError()).c_str());
98
99 StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
100
101 if (!owned_script_object_sp->IsValid())
102 return llvm::createStringError("created script object is invalid");
103
104 lldb::user_id_t frame_id = scripted_frame_interface->GetID();
105
106 lldb::addr_t pc = scripted_frame_interface->GetPC();
107 SymbolContext sc;
108 Address symbol_addr;
109 if (pc != LLDB_INVALID_ADDRESS) {
110 symbol_addr.SetLoadAddress(pc, &process_sp->GetTarget());
111 symbol_addr.CalculateSymbolContext(&sc);
112 }
113
114 std::optional<SymbolContext> maybe_sym_ctx =
115 scripted_frame_interface->GetSymbolContext();
116 if (maybe_sym_ctx)
117 sc = *maybe_sym_ctx;
118
119 lldb::RegisterContextSP reg_ctx_sp;
120 auto regs_or_err =
121 CreateRegisterContext(*scripted_frame_interface, *thread_sp, frame_id);
122 if (!regs_or_err)
123 LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), regs_or_err.takeError(), "{0}");
124 else
125 reg_ctx_sp = *regs_or_err;
126
127 return std::make_shared<ScriptedFrame>(thread_sp, scripted_frame_interface,
128 frame_id, pc, sc, reg_ctx_sp,
129 owned_script_object_sp);
130}
131
133 ScriptedFrameInterfaceSP interface_sp,
135 SymbolContext &sym_ctx,
136 lldb::RegisterContextSP reg_ctx_sp,
137 StructuredData::GenericSP script_object_sp)
138 : StackFrame(thread_sp, /*frame_idx=*/id,
139 /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp,
140 /*cfa=*/0, /*pc=*/pc,
141 /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),
142 m_scripted_frame_interface_sp(interface_sp),
143 m_script_object_sp(script_object_sp) {
144 // FIXME: This should be part of the base class constructor.
146}
147
149
152 std::optional<std::string> function_name = GetInterface()->GetFunctionName();
153 if (!function_name)
155 return ConstString(function_name->c_str()).AsCString(nullptr);
156}
157
160 std::optional<std::string> function_name =
161 GetInterface()->GetDisplayFunctionName();
162 if (!function_name)
164 return ConstString(function_name->c_str()).AsCString(nullptr);
165}
166
167bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }
168
170 return GetInterface()->IsArtificial();
171}
172
173bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }
174
178
179std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() {
181
182 StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
183
185 if (!reg_info)
187 std::shared_ptr<DynamicRegisterInfo>>(
188 LLVM_PRETTY_FUNCTION, "failed to get scripted frame registers info",
190
191 ThreadSP thread_sp = m_thread_wp.lock();
192 if (!thread_sp || !thread_sp->IsValid())
194 std::shared_ptr<DynamicRegisterInfo>>(
195 LLVM_PRETTY_FUNCTION,
196 "failed to get scripted frame registers info: invalid thread", error,
198
199 ProcessSP process_sp = thread_sp->GetProcess();
200 if (!process_sp || !process_sp->IsValid())
202 std::shared_ptr<DynamicRegisterInfo>>(
203 LLVM_PRETTY_FUNCTION,
204 "failed to get scripted frame registers info: invalid process", error,
206
207 return DynamicRegisterInfo::Create(*reg_info,
208 process_sp->GetTarget().GetArchitecture());
209}
210
211llvm::Expected<lldb::RegisterContextSP>
213 Thread &thread, lldb::user_id_t frame_id) {
214 StructuredData::DictionarySP reg_info = interface.GetRegisterInfo();
215
216 if (!reg_info)
217 return llvm::createStringError(
218 "failed to get scripted frame registers info");
219
220 std::shared_ptr<DynamicRegisterInfo> register_info_sp =
222 *reg_info, thread.GetProcess()->GetTarget().GetArchitecture());
223
224 lldb::RegisterContextSP reg_ctx_sp;
225
226 std::optional<std::string> reg_data = interface.GetRegisterContext();
227 if (!reg_data)
228 return llvm::createStringError(
229 "failed to get scripted frame registers data");
230
231 DataBufferSP data_sp(
232 std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
233
234 if (!data_sp->GetByteSize())
235 return llvm::createStringError("failed to copy raw registers data");
236
237 std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
238 std::make_shared<RegisterContextMemory>(
239 thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS);
240
241 reg_ctx_memory->SetAllRegisterData(data_sp);
242 reg_ctx_sp = reg_ctx_memory;
243
244 return reg_ctx_sp;
245}
246
248 if (!m_reg_context_sp) {
252 LLVM_PRETTY_FUNCTION,
253 "failed to get scripted frame registers context: invalid interface",
255
256 ThreadSP thread_sp = GetThread();
257 if (!thread_sp)
259 LLVM_PRETTY_FUNCTION,
260 "failed to get scripted frame registers context: invalid thread",
262
264 *thread_sp, GetFrameIndex());
265 if (!regs_or_err) {
266 error = Status::FromError(regs_or_err.takeError());
268 LLVM_PRETTY_FUNCTION,
269 "failed to get scripted frame registers context", error,
271 }
272
273 m_reg_context_sp = *regs_or_err;
274 }
275
276 return m_reg_context_sp;
277}
278
280 bool include_synthetic_vars,
281 Status *error_ptr) {
282 PopulateVariableListFromInterface(include_synthetic_vars);
283 return m_variable_list_sp.get();
284}
285
288 bool include_synthetic_vars,
289 bool must_have_valid_location) {
290 PopulateVariableListFromInterface(include_synthetic_vars);
291 return m_variable_list_sp;
292}
293
295 bool include_synthetic_vars) {
296 // Fetch values from the interface.
297 ValueObjectListSP value_list_sp = GetInterface()->GetVariables();
298 if (!value_list_sp)
299 return;
300
301 // Convert what we can into a variable.
302 m_variable_list_sp = std::make_shared<VariableList>();
303 for (uint32_t i = 0, e = value_list_sp->GetSize(); i < e; ++i) {
304 ValueObjectSP v = value_list_sp->GetValueObjectAtIndex(i);
305 if (!v)
306 continue;
307
308 VariableSP var = v->GetVariable();
309 if (!var && include_synthetic_vars) {
310 // Construct the value type as an synthetic verison of what the value type
311 // is. That'll allow the user to tell the scope and the 'synthetic-ness'
312 // of the variable.
313 lldb::ValueType vt = GetSyntheticValueType(v->GetValueType());
314
315 // Just make up a variable - the frame variable dumper just passes it
316 // back in to GetValueObjectForFrameVariable, so we really just need to
317 // make sure the name and type are correct. We create IDs based on
318 // value_list_sp in order to make sure they're unique.
319 var = std::make_shared<lldb_private::Variable>(
320 (lldb::user_id_t)value_list_sp->GetSize() + i,
321 v->GetName().GetCString(), v->GetName().GetCString(), nullptr, vt,
322 /*owner_scope=*/nullptr,
323 /*scope_range=*/Variable::RangeList{},
324 /*decl=*/nullptr, DWARFExpressionList{}, /*external=*/false,
325 /*artificial=*/true, /*location_is_constant_data=*/false);
326 }
327
328 // Only append the variable if we have one (had already, or just created).
329 if (var)
330 m_variable_list_sp->AddVariable(var);
331 }
332}
333
335 const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic) {
336 // Fetch values from the interface.
337 ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
338 if (!values)
339 return {};
340
341 return values->FindValueObjectByValueName(
342 variable_sp->GetName().AsCString(nullptr));
343}
344
346 // Fetch values from the interface.
347 ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
348 if (!values)
349 return {};
350
351 return values->FindValueObjectByValueName(name.AsCString(nullptr));
352}
353
355 llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
356 uint32_t options, lldb::VariableSP &var_sp, Status &error,
357 lldb::DILMode mode) {
358 // Unless the frame implementation knows how to create variables (which it
359 // doesn't), we can't construct anything for the variable. This may seem
360 // somewhat out of place, but it's basically because of how this API is used -
361 // the print command uses this API to fill in var_sp; and this implementation
362 // can't do that!
363 // FIXME: We should make it possible for the frame implementation to create
364 // Variable objects.
365 (void)var_sp;
366 // Otherwise, delegate to the scripted frame interface pointer.
367 return m_scripted_frame_interface_sp->GetValueObjectForVariableExpression(
368 var_expr, options, error);
369}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:394
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:1034
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
Definition Address.cpp:819
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 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()
virtual StructuredData::DictionarySP GetRegisterInfo()
virtual std::optional< std::string > GetRegisterContext()
lldb::VariableListSP m_variable_list_sp
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...
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
static llvm::Expected< lldb::RegisterContextSP > CreateRegisterContext(ScriptedFrameInterface &interface, Thread &thread, lldb::user_id_t frame_id)
ScriptedFrame(lldb::ThreadSP thread_sp, lldb::ScriptedFrameInterfaceSP interface_sp, lldb::user_id_t frame_idx, lldb::addr_t pc, SymbolContext &sym_ctx, lldb::RegisterContextSP reg_ctx_sp, StructuredData::GenericSP script_object_sp=nullptr)
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.
std::shared_ptr< DynamicRegisterInfo > GetDynamicRegisterInfo()
static Ret ErrorWithMessage(llvm::StringRef caller_name, llvm::StringRef error_msg, Status &error, LLDBLog log_category=LLDBLog::Process)
lldb::ThreadSP GetThread() const
Definition StackFrame.h:137
virtual const char * GetFunctionName()
Get the frame's demangled name.
lldb::ThreadWP m_thread_wp
For StackFrame and derived classes only.
Definition StackFrame.h:596
lldb::RegisterContextSP m_reg_context_sp
Definition StackFrame.h:599
@ Synthetic
An synthetic stack frame (e.g.
Definition StackFrame.h:74
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
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< Generic > GenericSP
std::shared_ptr< Dictionary > DictionarySP
Defines a symbol context baton that can be handed other debug core functions.
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.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
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::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:82
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