192 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ScriptedFrame.h"10 11#include "lldb/Utility/DataBufferHeap.h"12 13using namespace lldb;14using namespace lldb_private;15 16void ScriptedFrame::CheckInterpreterAndScriptObject() const {17 lldbassert(m_script_object_sp && "Invalid Script Object.");18 lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");19}20 21llvm::Expected<std::shared_ptr<ScriptedFrame>>22ScriptedFrame::Create(ScriptedThread &thread,23 StructuredData::DictionarySP args_sp,24 StructuredData::Generic *script_object) {25 if (!thread.IsValid())26 return llvm::createStringError("Invalid scripted thread.");27 28 thread.CheckInterpreterAndScriptObject();29 30 auto scripted_frame_interface =31 thread.GetInterface()->CreateScriptedFrameInterface();32 if (!scripted_frame_interface)33 return llvm::createStringError("failed to create scripted frame interface");34 35 llvm::StringRef frame_class_name;36 if (!script_object) {37 std::optional<std::string> class_name =38 thread.GetInterface()->GetScriptedFramePluginName();39 if (!class_name || class_name->empty())40 return llvm::createStringError(41 "failed to get scripted thread class name");42 frame_class_name = *class_name;43 }44 45 ExecutionContext exe_ctx(thread);46 auto obj_or_err = scripted_frame_interface->CreatePluginObject(47 frame_class_name, exe_ctx, args_sp, script_object);48 49 if (!obj_or_err)50 return llvm::createStringError(51 "failed to create script object: %s",52 llvm::toString(obj_or_err.takeError()).c_str());53 54 StructuredData::GenericSP owned_script_object_sp = *obj_or_err;55 56 if (!owned_script_object_sp->IsValid())57 return llvm::createStringError("created script object is invalid");58 59 lldb::user_id_t frame_id = scripted_frame_interface->GetID();60 61 lldb::addr_t pc = scripted_frame_interface->GetPC();62 SymbolContext sc;63 Address symbol_addr;64 if (pc != LLDB_INVALID_ADDRESS) {65 symbol_addr.SetLoadAddress(pc, &thread.GetProcess()->GetTarget());66 symbol_addr.CalculateSymbolContext(&sc);67 }68 69 std::optional<SymbolContext> maybe_sym_ctx =70 scripted_frame_interface->GetSymbolContext();71 if (maybe_sym_ctx) {72 sc = *maybe_sym_ctx;73 }74 75 StructuredData::DictionarySP reg_info =76 scripted_frame_interface->GetRegisterInfo();77 78 if (!reg_info)79 return llvm::createStringError(80 "failed to get scripted thread registers info");81 82 std::shared_ptr<DynamicRegisterInfo> register_info_sp =83 DynamicRegisterInfo::Create(84 *reg_info, thread.GetProcess()->GetTarget().GetArchitecture());85 86 lldb::RegisterContextSP reg_ctx_sp;87 88 std::optional<std::string> reg_data =89 scripted_frame_interface->GetRegisterContext();90 if (reg_data) {91 DataBufferSP data_sp(92 std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));93 94 if (!data_sp->GetByteSize())95 return llvm::createStringError("failed to copy raw registers data");96 97 std::shared_ptr<RegisterContextMemory> reg_ctx_memory =98 std::make_shared<RegisterContextMemory>(99 thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS);100 if (!reg_ctx_memory)101 return llvm::createStringError("failed to create a register context.");102 103 reg_ctx_memory->SetAllRegisterData(data_sp);104 reg_ctx_sp = reg_ctx_memory;105 }106 107 return std::make_shared<ScriptedFrame>(108 thread, scripted_frame_interface, frame_id, pc, sc, reg_ctx_sp,109 register_info_sp, owned_script_object_sp);110}111 112ScriptedFrame::ScriptedFrame(ScriptedThread &thread,113 ScriptedFrameInterfaceSP interface_sp,114 lldb::user_id_t id, lldb::addr_t pc,115 SymbolContext &sym_ctx,116 lldb::RegisterContextSP reg_ctx_sp,117 std::shared_ptr<DynamicRegisterInfo> reg_info_sp,118 StructuredData::GenericSP script_object_sp)119 : StackFrame(thread.shared_from_this(), /*frame_idx=*/id,120 /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp,121 /*cfa=*/0, /*pc=*/pc,122 /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),123 m_scripted_frame_interface_sp(interface_sp),124 m_script_object_sp(script_object_sp), m_register_info_sp(reg_info_sp) {}125 126ScriptedFrame::~ScriptedFrame() {}127 128const char *ScriptedFrame::GetFunctionName() {129 CheckInterpreterAndScriptObject();130 std::optional<std::string> function_name = GetInterface()->GetFunctionName();131 if (!function_name)132 return nullptr;133 return ConstString(function_name->c_str()).AsCString();134}135 136const char *ScriptedFrame::GetDisplayFunctionName() {137 CheckInterpreterAndScriptObject();138 std::optional<std::string> function_name =139 GetInterface()->GetDisplayFunctionName();140 if (!function_name)141 return nullptr;142 return ConstString(function_name->c_str()).AsCString();143}144 145bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }146 147bool ScriptedFrame::IsArtificial() const {148 return GetInterface()->IsArtificial();149}150 151bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }152 153lldb::ScriptedFrameInterfaceSP ScriptedFrame::GetInterface() const {154 return m_scripted_frame_interface_sp;155}156 157std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() {158 CheckInterpreterAndScriptObject();159 160 if (!m_register_info_sp) {161 StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();162 163 Status error;164 if (!reg_info)165 return ScriptedInterface::ErrorWithMessage<166 std::shared_ptr<DynamicRegisterInfo>>(167 LLVM_PRETTY_FUNCTION, "Failed to get scripted frame registers info.",168 error, LLDBLog::Thread);169 170 ThreadSP thread_sp = m_thread_wp.lock();171 if (!thread_sp || !thread_sp->IsValid())172 return ScriptedInterface::ErrorWithMessage<173 std::shared_ptr<DynamicRegisterInfo>>(174 LLVM_PRETTY_FUNCTION,175 "Failed to get scripted frame registers info: invalid thread.", error,176 LLDBLog::Thread);177 178 ProcessSP process_sp = thread_sp->GetProcess();179 if (!process_sp || !process_sp->IsValid())180 return ScriptedInterface::ErrorWithMessage<181 std::shared_ptr<DynamicRegisterInfo>>(182 LLVM_PRETTY_FUNCTION,183 "Failed to get scripted frame registers info: invalid process.",184 error, LLDBLog::Thread);185 186 m_register_info_sp = DynamicRegisterInfo::Create(187 *reg_info, process_sp->GetTarget().GetArchitecture());188 }189 190 return m_register_info_sp;191}192