================ @@ -0,0 +1,192 @@ +//===-- ScriptedFrame.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ScriptedFrame.h" + +#include "lldb/Utility/DataBufferHeap.h" + +using namespace lldb; +using namespace lldb_private; + +void ScriptedFrame::CheckInterpreterAndScriptObject() const { + lldbassert(m_script_object_sp && "Invalid Script Object."); + lldbassert(GetInterface() && "Invalid Scripted Frame Interface."); +} + +llvm::Expected<std::shared_ptr<ScriptedFrame>> +ScriptedFrame::Create(ScriptedThread &thread, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_object) { + if (!thread.IsValid()) + return llvm::createStringError("Invalid scripted thread."); + + thread.CheckInterpreterAndScriptObject(); + + auto scripted_frame_interface = + thread.GetInterface()->CreateScriptedFrameInterface(); + if (!scripted_frame_interface) + return llvm::createStringError( + "Failed to create scripted frame interface."); + + llvm::StringRef frame_class_name; + if (!script_object) { + std::optional<std::string> class_name = + thread.GetInterface()->GetScriptedFramePluginName(); + if (!class_name || class_name->empty()) + return llvm::createStringError( + "Failed to get scripted thread class name."); + frame_class_name = *class_name; + } + + ExecutionContext exe_ctx(thread); + auto obj_or_err = scripted_frame_interface->CreatePluginObject( + frame_class_name, exe_ctx, args_sp, script_object); + + if (!obj_or_err) { + llvm::consumeError(obj_or_err.takeError()); + return llvm::createStringError("Failed to create script object."); + } + + StructuredData::GenericSP owned_script_object_sp = *obj_or_err; + + if (!owned_script_object_sp->IsValid()) + return llvm::createStringError("Created script object is invalid."); + + lldb::user_id_t frame_id = scripted_frame_interface->GetID(); + + lldb::addr_t pc = scripted_frame_interface->GetPC(); + SymbolContext sc; + Address symbol_addr; + if (pc != LLDB_INVALID_ADDRESS) { + symbol_addr.SetLoadAddress(pc, &thread.GetProcess()->GetTarget()); + symbol_addr.CalculateSymbolContext(&sc); + } + + std::optional<SymbolContext> maybe_sym_ctx = + scripted_frame_interface->GetSymbolContext(); + if (maybe_sym_ctx) { + sc = *maybe_sym_ctx; + } + + StructuredData::DictionarySP reg_info = + scripted_frame_interface->GetRegisterInfo(); + + if (!reg_info) + return llvm::createStringError( + "Failed to get scripted thread registers info."); + + std::shared_ptr<DynamicRegisterInfo> register_info_sp = + DynamicRegisterInfo::Create( + *reg_info, thread.GetProcess()->GetTarget().GetArchitecture()); + + lldb::RegisterContextSP reg_ctx_sp; + + std::optional<std::string> reg_data = + scripted_frame_interface->GetRegisterContext(); + if (reg_data) { + DataBufferSP data_sp( + std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size())); + + if (!data_sp->GetByteSize()) + return llvm::createStringError("Failed to copy raw registers data"); + + std::shared_ptr<RegisterContextMemory> reg_ctx_memory = + std::make_shared<RegisterContextMemory>( + thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS); + if (!reg_ctx_memory) + return llvm::createStringError("Failed to create a register context."); + + reg_ctx_memory->SetAllRegisterData(data_sp); + reg_ctx_sp = reg_ctx_memory; + } + + return std::make_shared<ScriptedFrame>( + thread, scripted_frame_interface, frame_id, pc, sc, reg_ctx_sp, + register_info_sp, owned_script_object_sp); +} + +ScriptedFrame::ScriptedFrame(ScriptedThread &thread, + ScriptedFrameInterfaceSP interface_sp, + lldb::user_id_t id, lldb::addr_t pc, + SymbolContext &sym_ctx, + lldb::RegisterContextSP reg_ctx_sp, + std::shared_ptr<DynamicRegisterInfo> reg_info_sp, + StructuredData::GenericSP script_object_sp) + : StackFrame(thread.shared_from_this(), /*frame_idx=*/id, + /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp, + /*cfa=*/0, /*pc=*/pc, + /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx), + m_scripted_thread(thread), m_scripted_frame_interface_sp(interface_sp), + m_script_object_sp(script_object_sp), m_register_info_sp(reg_info_sp) {} + +ScriptedFrame::~ScriptedFrame() {} + +const char *ScriptedFrame::GetFunctionName() { + CheckInterpreterAndScriptObject(); + std::optional<std::string> function_name = GetInterface()->GetFunctionName(); + if (!function_name) + return nullptr; + return ConstString(function_name->c_str()).AsCString(); +} + +const char *ScriptedFrame::GetDisplayFunctionName() { + CheckInterpreterAndScriptObject(); + std::optional<std::string> function_name = + GetInterface()->GetDisplayFunctionName(); + if (!function_name) + return nullptr; + return ConstString(function_name->c_str()).AsCString(); +} + +bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); } + +bool ScriptedFrame::IsArtificial() const { + return GetInterface()->IsArtificial(); +} + +bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); } + +lldb::ScriptedFrameInterfaceSP ScriptedFrame::GetInterface() const { + return m_scripted_frame_interface_sp; +} + +std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() { + CheckInterpreterAndScriptObject(); + + if (!m_register_info_sp) { + StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo(); + + Status error; + if (!reg_info) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr<DynamicRegisterInfo>>( + LLVM_PRETTY_FUNCTION, "Failed to get scripted frame registers info.", + error, LLDBLog::Thread); + + ThreadSP thread_sp = m_thread_wp.lock(); + if (!thread_sp || !thread_sp->IsValid()) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr<DynamicRegisterInfo>>( + LLVM_PRETTY_FUNCTION, + "Failed to get scripted frame registers info: invalid thread.", error, + LLDBLog::Thread); + + ProcessSP process_sp = thread_sp->GetProcess(); + if (!process_sp || !process_sp->IsValid()) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr<DynamicRegisterInfo>>( + LLVM_PRETTY_FUNCTION, + "Failed to get scripted frame registers info: invalid process.", + error, LLDBLog::Thread); ---------------- medismailben wrote:
`ScriptedInterface::ErrorWithMessage` will both log the message in the logging channel passed to it, append it to the Status object parameter and return the templated defaultly constructed object. That way we're sure to have enough error reporting no matter how the callers does it. https://github.com/llvm/llvm-project/pull/149622 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits