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"
24#include "lldb/Target/Process.h"
26#include "lldb/Target/Thread.h"
29#include "lldb/Utility/Log.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
36
38 lldbassert(m_script_object_sp && "Invalid Script Object.");
39 lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");
40}
41
42llvm::Expected<std::shared_ptr<ScriptedFrame>>
44 ScriptedThreadInterfaceSP scripted_thread_interface_sp,
46 StructuredData::Generic *script_object) {
47 if (!thread_sp || !thread_sp->IsValid())
48 return llvm::createStringError("invalid thread");
49
50 ProcessSP process_sp = thread_sp->GetProcess();
51 if (!process_sp || !process_sp->IsValid())
52 return llvm::createStringError("invalid process");
53
54 ScriptInterpreter *script_interp =
55 process_sp->GetTarget().GetDebugger().GetScriptInterpreter();
56 if (!script_interp)
57 return llvm::createStringError("no script interpreter");
58
59 auto scripted_frame_interface = script_interp->CreateScriptedFrameInterface();
60 if (!scripted_frame_interface)
61 return llvm::createStringError("failed to create scripted frame interface");
62
63 llvm::StringRef frame_class_name;
64 if (!script_object) {
65 // If no script object is provided and we have a scripted thread interface,
66 // try to get the frame class name from it.
67 if (scripted_thread_interface_sp) {
68 std::optional<std::string> class_name =
69 scripted_thread_interface_sp->GetScriptedFramePluginName();
70 if (!class_name || class_name->empty())
71 return llvm::createStringError(
72 "failed to get scripted frame class name");
73 frame_class_name = *class_name;
74 } else {
75 return llvm::createStringError(
76 "no script object provided and no scripted thread interface");
77 }
78 }
79
80 ExecutionContext exe_ctx(thread_sp);
81 auto obj_or_err = scripted_frame_interface->CreatePluginObject(
82 frame_class_name, exe_ctx, args_sp, script_object);
83
84 if (!obj_or_err)
85 return llvm::createStringError(
86 "failed to create script object: %s",
87 llvm::toString(obj_or_err.takeError()).c_str());
88
89 StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
90
91 if (!owned_script_object_sp->IsValid())
92 return llvm::createStringError("created script object is invalid");
93
94 lldb::user_id_t frame_id = scripted_frame_interface->GetID();
95
96 lldb::addr_t pc = scripted_frame_interface->GetPC();
98 Address symbol_addr;
99 if (pc != LLDB_INVALID_ADDRESS) {
100 symbol_addr.SetLoadAddress(pc, &process_sp->GetTarget());
101 symbol_addr.CalculateSymbolContext(&sc);
102 }
103
104 std::optional<SymbolContext> maybe_sym_ctx =
105 scripted_frame_interface->GetSymbolContext();
106 if (maybe_sym_ctx)
107 sc = *maybe_sym_ctx;
108
109 lldb::RegisterContextSP reg_ctx_sp;
110 auto regs_or_err =
111 CreateRegisterContext(*scripted_frame_interface, *thread_sp, frame_id);
112 if (!regs_or_err)
113 LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), regs_or_err.takeError(), "{0}");
114 else
115 reg_ctx_sp = *regs_or_err;
116
117 return std::make_shared<ScriptedFrame>(thread_sp, scripted_frame_interface,
118 frame_id, pc, sc, reg_ctx_sp,
119 owned_script_object_sp);
120}
121
123 ScriptedFrameInterfaceSP interface_sp,
125 SymbolContext &sym_ctx,
126 lldb::RegisterContextSP reg_ctx_sp,
127 StructuredData::GenericSP script_object_sp)
128 : StackFrame(thread_sp, /*frame_idx=*/id,
129 /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp,
130 /*cfa=*/0, /*pc=*/pc,
131 /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),
132 m_scripted_frame_interface_sp(interface_sp),
133 m_script_object_sp(script_object_sp) {
134 // FIXME: This should be part of the base class constructor.
136}
137
139
142 std::optional<std::string> function_name = GetInterface()->GetFunctionName();
143 if (!function_name)
145 return ConstString(function_name->c_str()).AsCString();
146}
147
150 std::optional<std::string> function_name =
151 GetInterface()->GetDisplayFunctionName();
152 if (!function_name)
154 return ConstString(function_name->c_str()).AsCString();
155}
156
157bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }
158
160 return GetInterface()->IsArtificial();
161}
162
163bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }
164
168
169std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() {
171
172 StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
173
175 if (!reg_info)
177 std::shared_ptr<DynamicRegisterInfo>>(
178 LLVM_PRETTY_FUNCTION, "failed to get scripted frame registers info",
180
181 ThreadSP thread_sp = m_thread_wp.lock();
182 if (!thread_sp || !thread_sp->IsValid())
184 std::shared_ptr<DynamicRegisterInfo>>(
185 LLVM_PRETTY_FUNCTION,
186 "failed to get scripted frame registers info: invalid thread", error,
188
189 ProcessSP process_sp = thread_sp->GetProcess();
190 if (!process_sp || !process_sp->IsValid())
192 std::shared_ptr<DynamicRegisterInfo>>(
193 LLVM_PRETTY_FUNCTION,
194 "failed to get scripted frame registers info: invalid process", error,
196
197 return DynamicRegisterInfo::Create(*reg_info,
198 process_sp->GetTarget().GetArchitecture());
199}
200
201llvm::Expected<lldb::RegisterContextSP>
203 Thread &thread, lldb::user_id_t frame_id) {
204 StructuredData::DictionarySP reg_info = interface.GetRegisterInfo();
205
206 if (!reg_info)
207 return llvm::createStringError(
208 "failed to get scripted frame registers info");
209
210 std::shared_ptr<DynamicRegisterInfo> register_info_sp =
212 *reg_info, thread.GetProcess()->GetTarget().GetArchitecture());
213
214 lldb::RegisterContextSP reg_ctx_sp;
215
216 std::optional<std::string> reg_data = interface.GetRegisterContext();
217 if (!reg_data)
218 return llvm::createStringError(
219 "failed to get scripted frame registers data");
220
221 DataBufferSP data_sp(
222 std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
223
224 if (!data_sp->GetByteSize())
225 return llvm::createStringError("failed to copy raw registers data");
226
227 std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
228 std::make_shared<RegisterContextMemory>(
229 thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS);
230
231 reg_ctx_memory->SetAllRegisterData(data_sp);
232 reg_ctx_sp = reg_ctx_memory;
233
234 return reg_ctx_sp;
235}
236
238 if (!m_reg_context_sp) {
242 LLVM_PRETTY_FUNCTION,
243 "failed to get scripted frame registers context: invalid interface",
245
246 ThreadSP thread_sp = GetThread();
247 if (!thread_sp)
249 LLVM_PRETTY_FUNCTION,
250 "failed to get scripted frame registers context: invalid thread",
252
254 *thread_sp, GetFrameIndex());
255 if (!regs_or_err) {
256 error = Status::FromError(regs_or_err.takeError());
258 LLVM_PRETTY_FUNCTION,
259 "failed to get scripted frame registers context", error,
261 }
262
263 m_reg_context_sp = *regs_or_err;
264 }
265
266 return m_reg_context_sp;
267}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
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:1035
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=nullptr) const
Get the string value as a C string.
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()
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.
bool IsArtificial() const override
Query whether this frame is artificial (e.g a synthesized result of inferring missing tail call frame...
const char * GetFunctionName() override
Get the frame's demangled name.
lldb::ScriptedFrameInterfaceSP GetInterface() const
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.
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.
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: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:573
lldb::RegisterContextSP m_reg_context_sp
Definition StackFrame.h:576
@ 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
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:137
std::shared_ptr< Generic > GenericSP
std::shared_ptr< Dictionary > DictionarySP
Defines a symbol context baton that can be handed other debug core functions.
#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:332
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::ScriptedThreadInterface > ScriptedThreadInterfaceSP
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
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP