================
@@ -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();
----------------
jimingham wrote:

Do you need to keep re-calling this?  Seems like if either of the interpreter 
or script object were bad at the start, we should refuse to make the 
ScriptedFrame at all.  Then once successfully created these objects can't go 
bad, can they?  So checking here should be a no-op.

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

Reply via email to