diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:05 +0000 |
commit | 349cc55c9796c4596a5b9904cd3281af295f878f (patch) | |
tree | 410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp | |
parent | cb2ae6163174b90e999326ecec3699ee093a5d43 (diff) | |
parent | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp new file mode 100644 index 000000000000..1adbd4e7799d --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -0,0 +1,211 @@ +//===-- ScriptedThread.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 "ScriptedThread.h" + +#include "Plugins/Process/Utility/RegisterContextThreadMemory.h" +#include "lldb/Target/OperatingSystem.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" + +#include <memory> + +using namespace lldb; +using namespace lldb_private; + +void ScriptedThread::CheckInterpreterAndScriptObject() const { + lldbassert(m_script_object_sp && "Invalid Script Object."); + lldbassert(GetInterface() && "Invalid Scripted Thread Interface."); +} + +ScriptedThread::ScriptedThread(ScriptedProcess &process, Status &error) + : Thread(process, LLDB_INVALID_THREAD_ID), m_scripted_process(process) { + if (!process.IsValid()) { + error.SetErrorString("Invalid scripted process"); + return; + } + + process.CheckInterpreterAndScriptObject(); + + auto scripted_thread_interface = GetInterface(); + if (!scripted_thread_interface) { + error.SetErrorString("Failed to get scripted thread interface."); + return; + } + + llvm::Optional<std::string> class_name = + process.GetInterface().GetScriptedThreadPluginName(); + if (!class_name || class_name->empty()) { + error.SetErrorString("Failed to get scripted thread class name."); + return; + } + + ExecutionContext exe_ctx(process); + + StructuredData::GenericSP object_sp = + scripted_thread_interface->CreatePluginObject( + class_name->c_str(), exe_ctx, + process.m_scripted_process_info.GetArgsSP()); + if (!object_sp || !object_sp->IsValid()) { + error.SetErrorString("Failed to create valid script object"); + return; + } + + m_script_object_sp = object_sp; + + SetID(scripted_thread_interface->GetThreadID()); +} + +ScriptedThread::~ScriptedThread() { DestroyThread(); } + +const char *ScriptedThread::GetName() { + CheckInterpreterAndScriptObject(); + llvm::Optional<std::string> thread_name = GetInterface()->GetName(); + if (!thread_name) + return nullptr; + return ConstString(thread_name->c_str()).AsCString(); +} + +const char *ScriptedThread::GetQueueName() { + CheckInterpreterAndScriptObject(); + llvm::Optional<std::string> queue_name = GetInterface()->GetQueue(); + if (!queue_name) + return nullptr; + return ConstString(queue_name->c_str()).AsCString(); +} + +void ScriptedThread::WillResume(StateType resume_state) {} + +void ScriptedThread::ClearStackFrames() { Thread::ClearStackFrames(); } + +RegisterContextSP ScriptedThread::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrame(nullptr); + return m_reg_context_sp; +} + +RegisterContextSP +ScriptedThread::CreateRegisterContextForFrame(StackFrame *frame) { + const uint32_t concrete_frame_idx = + frame ? frame->GetConcreteFrameIndex() : 0; + + if (concrete_frame_idx) + return GetUnwinder().CreateRegisterContextForFrame(frame); + + lldb::RegisterContextSP reg_ctx_sp; + Status error; + + llvm::Optional<std::string> reg_data = GetInterface()->GetRegisterContext(); + if (!reg_data) + return GetInterface()->ErrorWithMessage<lldb::RegisterContextSP>( + LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers data.", + error, LIBLLDB_LOG_THREAD); + + DataBufferSP data_sp( + std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size())); + + if (!data_sp->GetByteSize()) + return GetInterface()->ErrorWithMessage<lldb::RegisterContextSP>( + LLVM_PRETTY_FUNCTION, "Failed to copy raw registers data.", error, + LIBLLDB_LOG_THREAD); + + std::shared_ptr<RegisterContextMemory> reg_ctx_memory = + std::make_shared<RegisterContextMemory>( + *this, 0, *GetDynamicRegisterInfo(), LLDB_INVALID_ADDRESS); + if (!reg_ctx_memory) + return GetInterface()->ErrorWithMessage<lldb::RegisterContextSP>( + LLVM_PRETTY_FUNCTION, "Failed to create a register context.", error, + LIBLLDB_LOG_THREAD); + + reg_ctx_memory->SetAllRegisterData(data_sp); + m_reg_context_sp = reg_ctx_memory; + + return m_reg_context_sp; +} + +bool ScriptedThread::CalculateStopInfo() { + StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason(); + + Status error; + lldb::StopInfoSP stop_info_sp; + lldb::StopReason stop_reason_type; + + if (!dict_sp->GetValueForKeyAsInteger("type", stop_reason_type)) + return GetInterface()->ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, + "Couldn't find value for key 'type' in stop reason dictionary.", error, + LIBLLDB_LOG_THREAD); + + StructuredData::Dictionary *data_dict; + if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict)) + return GetInterface()->ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, + "Couldn't find value for key 'type' in stop reason dictionary.", error, + LIBLLDB_LOG_THREAD); + + switch (stop_reason_type) { + case lldb::eStopReasonNone: + break; + case lldb::eStopReasonBreakpoint: { + lldb::break_id_t break_id; + data_dict->GetValueForKeyAsInteger("break_id", break_id, + LLDB_INVALID_BREAK_ID); + stop_info_sp = + StopInfo::CreateStopReasonWithBreakpointSiteID(*this, break_id); + } break; + case lldb::eStopReasonSignal: { + int signal; + llvm::StringRef description; + data_dict->GetValueForKeyAsInteger("signal", signal, + LLDB_INVALID_SIGNAL_NUMBER); + data_dict->GetValueForKeyAsString("desc", description); + stop_info_sp = + StopInfo::CreateStopReasonWithSignal(*this, signal, description.data()); + } break; + default: + return GetInterface()->ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Unsupported stop reason type (" + + llvm::Twine(stop_reason_type) + llvm::Twine(").")) + .str(), + error, LIBLLDB_LOG_THREAD); + } + + SetStopInfo(stop_info_sp); + return true; +} + +void ScriptedThread::RefreshStateAfterStop() { + GetRegisterContext()->InvalidateIfNeeded(/*force=*/false); +} + +lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const { + return m_scripted_process.GetInterface().GetScriptedThreadInterface(); +} + +std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() { + CheckInterpreterAndScriptObject(); + + if (!m_register_info_sp) { + StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo(); + if (!reg_info) + return nullptr; + + m_register_info_sp = std::make_shared<DynamicRegisterInfo>( + *reg_info, m_scripted_process.GetTarget().GetArchitecture()); + assert(m_register_info_sp->GetNumRegisters() > 0); + assert(m_register_info_sp->GetNumRegisterSets() > 0); + } + + return m_register_info_sp; +} |