summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/scripted
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
commitc0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch)
treef42add1021b9f2ac6a69ac7cf6c4499962739a45 /lldb/source/Plugins/Process/scripted
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'lldb/source/Plugins/Process/scripted')
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp97
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedProcess.h28
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.cpp211
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.h68
4 files changed, 355 insertions, 49 deletions
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index 09e9375b6f66..15d3d43d9993 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -20,9 +20,6 @@
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/RegisterContext.h"
-
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h"
#include "lldb/Utility/State.h"
#include <mutex>
@@ -32,12 +29,7 @@ LLDB_PLUGIN_DEFINE(ScriptedProcess)
using namespace lldb;
using namespace lldb_private;
-ConstString ScriptedProcess::GetPluginNameStatic() {
- static ConstString g_name("ScriptedProcess");
- return g_name;
-}
-
-const char *ScriptedProcess::GetPluginDescriptionStatic() {
+llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
return "Scripted Process plug-in.";
}
@@ -109,9 +101,11 @@ ScriptedProcess::ScriptedProcess(
return;
}
- StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
- m_scripted_process_info.GetClassName().c_str(), target_sp,
- m_scripted_process_info.GetDictionarySP());
+ ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
+
+ StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
+ m_scripted_process_info.GetClassName().c_str(), exe_ctx,
+ m_scripted_process_info.GetArgsSP());
if (!object_sp || !object_sp->IsValid()) {
error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
@@ -145,10 +139,6 @@ void ScriptedProcess::Terminate() {
PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
}
-ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
-
-uint32_t ScriptedProcess::GetPluginVersion() { return 1; }
-
Status ScriptedProcess::DoLoadCore() {
ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
@@ -234,26 +224,22 @@ bool ScriptedProcess::IsAlive() {
size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
-
- auto error_with_message = [&error](llvm::StringRef message) {
- error.SetErrorString(message);
- return 0;
- };
-
if (!m_interpreter)
- return error_with_message("No interpreter.");
+ return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION,
+ "No interpreter.", error);
lldb::DataExtractorSP data_extractor_sp =
GetInterface().ReadMemoryAtAddress(addr, size, error);
- if (!data_extractor_sp || error.Fail())
+ if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
return 0;
offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
- return error_with_message("Failed to copy read memory to buffer.");
+ return GetInterface().ErrorWithMessage<size_t>(
+ LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
return size;
}
@@ -262,26 +248,36 @@ ArchSpec ScriptedProcess::GetArchitecture() {
return GetTarget().GetArchitecture();
}
-Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &region) {
- // TODO: Implement
- return Status();
+Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &region) {
+ CheckInterpreterAndScriptObject();
+
+ Status error;
+ if (auto region_or_err =
+ GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
+ region = *region_or_err;
+
+ return error;
}
Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
CheckInterpreterAndScriptObject();
+ Status error;
lldb::addr_t address = 0;
- lldb::MemoryRegionInfoSP mem_region_sp = nullptr;
- while ((mem_region_sp =
- GetInterface().GetMemoryRegionContainingAddress(address))) {
- auto range = mem_region_sp->GetRange();
+ while (auto region_or_err =
+ GetInterface().GetMemoryRegionContainingAddress(address, error)) {
+ if (error.Fail())
+ break;
+
+ MemoryRegionInfo &mem_region = *region_or_err;
+ auto range = mem_region.GetRange();
address += range.GetRangeBase() + range.GetByteSize();
- region_list.push_back(*mem_region_sp.get());
+ region_list.push_back(mem_region);
}
- return {};
+ return error;
}
void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
@@ -292,9 +288,40 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
// This is supposed to get the current set of threads, if any of them are in
// old_thread_list then they get copied to new_thread_list, and then any
// actually new threads will get added to new_thread_list.
+
+ CheckInterpreterAndScriptObject();
+ m_thread_plans.ClearThreadCache();
+
+ Status error;
+ ScriptLanguage language = m_interpreter->GetLanguage();
+
+ if (language != eScriptLanguagePython)
+ return GetInterface().ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION,
+ llvm::Twine("ScriptInterpreter language (" +
+ llvm::Twine(m_interpreter->LanguageToString(language)) +
+ llvm::Twine(") not supported."))
+ .str(),
+ error);
+
+ lldb::ThreadSP thread_sp;
+ thread_sp = std::make_shared<ScriptedThread>(*this, error);
+
+ if (!thread_sp || error.Fail())
+ return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
+ error.AsCString(), error);
+
+ new_thread_list.AddThread(thread_sp);
+
return new_thread_list.GetSize(false) > 0;
}
+void ScriptedProcess::RefreshStateAfterStop() {
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
+ m_thread_list.RefreshStateAfterStop();
+}
+
bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
info.Clear();
info.SetProcessID(GetID());
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
index 98c1a1ca4fe9..c8355f35548a 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -13,6 +13,8 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
+#include "ScriptedThread.h"
+
#include <mutex>
namespace lldb_private {
@@ -23,17 +25,15 @@ protected:
public:
ScriptedProcessInfo(const ProcessLaunchInfo &launch_info) {
m_class_name = launch_info.GetScriptedProcessClassName();
- m_dictionary_sp = launch_info.GetScriptedProcessDictionarySP();
+ m_args_sp = launch_info.GetScriptedProcessDictionarySP();
}
std::string GetClassName() const { return m_class_name; }
- StructuredData::DictionarySP GetDictionarySP() const {
- return m_dictionary_sp;
- }
+ StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; }
private:
std::string m_class_name;
- StructuredData::DictionarySP m_dictionary_sp;
+ StructuredData::DictionarySP m_args_sp;
};
public:
@@ -46,9 +46,9 @@ public:
static void Terminate();
- static ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "ScriptedProcess"; }
- static const char *GetPluginDescriptionStatic();
+ static llvm::StringRef GetPluginDescriptionStatic();
ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
const ScriptedProcess::ScriptedProcessInfo &launch_info,
@@ -61,9 +61,7 @@ public:
DynamicLoader *GetDynamicLoader() override { return nullptr; }
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
SystemRuntime *GetSystemRuntime() override { return nullptr; }
@@ -77,7 +75,7 @@ public:
Status DoDestroy() override;
- void RefreshStateAfterStop() override{};
+ void RefreshStateAfterStop() override;
bool IsAlive() override;
@@ -86,9 +84,6 @@ public:
ArchSpec GetArchitecture();
- Status GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info) override;
-
Status
GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) override;
@@ -102,7 +97,12 @@ protected:
bool DoUpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) override;
+ Status DoGetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
+
private:
+ friend class ScriptedThread;
+
void CheckInterpreterAndScriptObject() const;
ScriptedProcessInterface &GetInterface() const;
static bool IsScriptLanguageSupported(lldb::ScriptLanguage language);
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
new file mode 100644
index 000000000000..1adbd4e7799d
--- /dev/null
+++ b/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;
+}
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
new file mode 100644
index 000000000000..cdcd543702a4
--- /dev/null
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
@@ -0,0 +1,68 @@
+//===-- ScriptedThread.h ----------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SCRIPTED_THREAD_H
+#define LLDB_SOURCE_PLUGINS_SCRIPTED_THREAD_H
+
+#include <string>
+
+#include "ScriptedProcess.h"
+
+#include "Plugins/Process/Utility/RegisterContextMemory.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target//DynamicRegisterInfo.h"
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+class ScriptedProcess;
+}
+
+namespace lldb_private {
+
+class ScriptedThread : public lldb_private::Thread {
+public:
+ ScriptedThread(ScriptedProcess &process, Status &error);
+
+ ~ScriptedThread() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+ bool CalculateStopInfo() override;
+
+ const char *GetInfo() override { return nullptr; }
+
+ const char *GetName() override;
+
+ const char *GetQueueName() override;
+
+ void WillResume(lldb::StateType resume_state) override;
+
+ void RefreshStateAfterStop() override;
+
+ void ClearStackFrames() override;
+
+private:
+ void CheckInterpreterAndScriptObject() const;
+ lldb::ScriptedThreadInterfaceSP GetInterface() const;
+
+ ScriptedThread(const ScriptedThread &) = delete;
+ const ScriptedThread &operator=(const ScriptedThread &) = delete;
+
+ std::shared_ptr<DynamicRegisterInfo> GetDynamicRegisterInfo();
+
+ const ScriptedProcess &m_scripted_process;
+ std::shared_ptr<DynamicRegisterInfo> m_register_info_sp = nullptr;
+ lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_THREAD_H