summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/scripted
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/scripted')
-rw-r--r--lldb/source/Plugins/Process/scripted/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp191
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedFrame.h63
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.cpp82
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.h5
5 files changed, 331 insertions, 11 deletions
diff --git a/lldb/source/Plugins/Process/scripted/CMakeLists.txt b/lldb/source/Plugins/Process/scripted/CMakeLists.txt
index 590166591a41..1516ad3132e3 100644
--- a/lldb/source/Plugins/Process/scripted/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/scripted/CMakeLists.txt
@@ -1,6 +1,7 @@
add_lldb_library(lldbPluginScriptedProcess PLUGIN
ScriptedProcess.cpp
ScriptedThread.cpp
+ ScriptedFrame.cpp
LINK_COMPONENTS
BinaryFormat
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
new file mode 100644
index 000000000000..6519df9185df
--- /dev/null
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -0,0 +1,191 @@
+//===----------------------------------------------------------------------===//
+//
+// 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)
+ return llvm::createStringError(
+ "failed to create script object: %s",
+ llvm::toString(obj_or_err.takeError()).c_str());
+
+ 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_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);
+
+ m_register_info_sp = DynamicRegisterInfo::Create(
+ *reg_info, process_sp->GetTarget().GetArchitecture());
+ }
+
+ return m_register_info_sp;
+}
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
new file mode 100644
index 000000000000..6e01e2fd7653
--- /dev/null
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_FRAME_H
+#define LLDB_SOURCE_PLUGINS_SCRIPTED_FRAME_H
+
+#include "Plugins/Process/Utility/RegisterContextMemory.h"
+#include "ScriptedThread.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/StackFrame.h"
+#include <string>
+
+namespace lldb_private {
+class ScriptedThread;
+}
+
+namespace lldb_private {
+
+class ScriptedFrame : public lldb_private::StackFrame {
+
+public:
+ ScriptedFrame(ScriptedThread &thread,
+ lldb::ScriptedFrameInterfaceSP interface_sp,
+ lldb::user_id_t frame_idx, lldb::addr_t pc,
+ SymbolContext &sym_ctx, lldb::RegisterContextSP reg_ctx_sp,
+ std::shared_ptr<DynamicRegisterInfo> reg_info_sp,
+ StructuredData::GenericSP script_object_sp = nullptr);
+
+ ~ScriptedFrame() override;
+
+ static llvm::Expected<std::shared_ptr<ScriptedFrame>>
+ Create(ScriptedThread &thread, StructuredData::DictionarySP args_sp,
+ StructuredData::Generic *script_object = nullptr);
+
+ bool IsInlined() override;
+ bool IsArtificial() const override;
+ bool IsHidden() override;
+ const char *GetFunctionName() override;
+ const char *GetDisplayFunctionName() override;
+
+private:
+ void CheckInterpreterAndScriptObject() const;
+ lldb::ScriptedFrameInterfaceSP GetInterface() const;
+
+ ScriptedFrame(const ScriptedFrame &) = delete;
+ const ScriptedFrame &operator=(const ScriptedFrame &) = delete;
+
+ std::shared_ptr<DynamicRegisterInfo> GetDynamicRegisterInfo();
+
+ lldb::ScriptedFrameInterfaceSP m_scripted_frame_interface_sp;
+ lldb_private::StructuredData::GenericSP m_script_object_sp;
+ std::shared_ptr<DynamicRegisterInfo> m_register_info_sp;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_FRAME_H
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index d0d1508e8517..491efac5aade 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "ScriptedThread.h"
+#include "ScriptedFrame.h"
#include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
@@ -173,40 +174,101 @@ bool ScriptedThread::LoadArtificialStackFrames() {
.str(),
error, LLDBLog::Thread);
- StackFrameListSP frames = GetStackFrameList();
-
- for (size_t idx = 0; idx < arr_size; idx++) {
+ auto create_frame_from_dict =
+ [this, arr_sp](size_t idx) -> llvm::Expected<StackFrameSP> {
+ Status error;
std::optional<StructuredData::Dictionary *> maybe_dict =
arr_sp->GetItemAtIndexAsDictionary(idx);
- if (!maybe_dict)
- return ScriptedInterface::ErrorWithMessage<bool>(
+ if (!maybe_dict) {
+ ScriptedInterface::ErrorWithMessage<bool>(
LLVM_PRETTY_FUNCTION,
llvm::Twine(
"Couldn't get artificial stackframe dictionary at index (" +
llvm::Twine(idx) + llvm::Twine(") from stackframe array."))
.str(),
error, LLDBLog::Thread);
+ return error.ToError();
+ }
StructuredData::Dictionary *dict = *maybe_dict;
lldb::addr_t pc;
- if (!dict->GetValueForKeyAsInteger("pc", pc))
- return ScriptedInterface::ErrorWithMessage<bool>(
+ if (!dict->GetValueForKeyAsInteger("pc", pc)) {
+ ScriptedInterface::ErrorWithMessage<bool>(
LLVM_PRETTY_FUNCTION,
"Couldn't find value for key 'pc' in stackframe dictionary.", error,
LLDBLog::Thread);
+ return error.ToError();
+ }
Address symbol_addr;
symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget());
lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
bool cfa_is_valid = false;
+ const bool artificial = false;
const bool behaves_like_zeroth_frame = false;
SymbolContext sc;
symbol_addr.CalculateSymbolContext(&sc);
- StackFrameSP synth_frame_sp = std::make_shared<StackFrame>(
- this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
- StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc);
+ return std::make_shared<StackFrame>(this->shared_from_this(), idx, idx, cfa,
+ cfa_is_valid, pc,
+ StackFrame::Kind::Synthetic, artificial,
+ behaves_like_zeroth_frame, &sc);
+ };
+
+ auto create_frame_from_script_object =
+ [this, arr_sp](size_t idx) -> llvm::Expected<StackFrameSP> {
+ Status error;
+ StructuredData::ObjectSP object_sp = arr_sp->GetItemAtIndex(idx);
+ if (!object_sp || !object_sp->GetAsGeneric()) {
+ ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION,
+ llvm::Twine("Couldn't get artificial stackframe object at index (" +
+ llvm::Twine(idx) +
+ llvm::Twine(") from stackframe array."))
+ .str(),
+ error, LLDBLog::Thread);
+ return error.ToError();
+ }
+
+ auto frame_or_error =
+ ScriptedFrame::Create(*this, nullptr, object_sp->GetAsGeneric());
+
+ if (!frame_or_error) {
+ ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION, toString(frame_or_error.takeError()), error);
+ return error.ToError();
+ }
+
+ StackFrameSP frame_sp = frame_or_error.get();
+ lldbassert(frame_sp && "Couldn't initialize scripted frame.");
+
+ return frame_sp;
+ };
+
+ StackFrameListSP frames = GetStackFrameList();
+
+ for (size_t idx = 0; idx < arr_size; idx++) {
+ StackFrameSP synth_frame_sp = nullptr;
+
+ auto frame_from_dict_or_err = create_frame_from_dict(idx);
+ if (!frame_from_dict_or_err) {
+ auto frame_from_script_obj_or_err = create_frame_from_script_object(idx);
+
+ if (!frame_from_script_obj_or_err) {
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION,
+ llvm::Twine("Couldn't add artificial frame (" + llvm::Twine(idx) +
+ llvm::Twine(") to ScriptedThread StackFrameList."))
+ .str(),
+ error, LLDBLog::Thread);
+ } else {
+ llvm::consumeError(frame_from_dict_or_err.takeError());
+ synth_frame_sp = *frame_from_script_obj_or_err;
+ }
+ } else {
+ synth_frame_sp = *frame_from_dict_or_err;
+ }
if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
return ScriptedInterface::ErrorWithMessage<bool>(
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
index cd224d60ceef..ee5ace405967 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
@@ -15,11 +15,12 @@
#include "Plugins/Process/Utility/RegisterContextMemory.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Target//DynamicRegisterInfo.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
#include "lldb/Target/Thread.h"
namespace lldb_private {
class ScriptedProcess;
+class ScriptedFrame;
}
namespace lldb_private {
@@ -61,6 +62,8 @@ public:
StructuredData::ObjectSP FetchThreadExtendedInfo() override;
private:
+ friend class ScriptedFrame;
+
void CheckInterpreterAndScriptObject() const;
lldb::ScriptedThreadInterfaceSP GetInterface() const;