aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (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.cpp211
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;
+}