This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG70665844915e: [lldb/Plugin] Add artificial stackframe 
loading in ScriptedThread (authored by mib).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119388/new/

https://reviews.llvm.org/D119388

Files:
  lldb/examples/python/scripted_process/scripted_process.py
  lldb/include/lldb/Target/StackFrameList.h
  lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
  lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
  lldb/source/Plugins/Process/scripted/ScriptedThread.h
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
  lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
  lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
  lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
  lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py

Index: lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
+++ lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
@@ -139,21 +139,6 @@
 
         return stop_reason
 
-    def get_stackframes(self):
-        class ScriptedStackFrame:
-            def __init__(idx, cfa, pc, symbol_ctx):
-                self.idx = idx
-                self.cfa = cfa
-                self.pc = pc
-                self.symbol_ctx = symbol_ctx
-
-
-        symbol_ctx = lldb.SBSymbolContext()
-        frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
-        self.frames.append(frame_zero)
-
-        return self.frame_zero[0:0]
-
     def get_register_context(self) -> str:
         if not self.corefile_thread or self.corefile_thread.GetNumFrames() == 0:
             return None
Index: lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
+++ lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
@@ -57,21 +57,6 @@
             "signal": signal.SIGTRAP
         } }
 
-    def get_stackframes(self):
-        class ScriptedStackFrame:
-            def __init__(idx, cfa, pc, symbol_ctx):
-                self.idx = idx
-                self.cfa = cfa
-                self.pc = pc
-                self.symbol_ctx = symbol_ctx
-
-
-        symbol_ctx = lldb.SBSymbolContext()
-        frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
-        self.frames.append(frame_zero)
-
-        return self.frame_zero[0:0]
-
     def get_register_context(self) -> str:
         return None
 
Index: lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
+++ lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -46,6 +46,7 @@
 class DummyScriptedThread(ScriptedThread):
     def __init__(self, process, args):
         super().__init__(process, args)
+        self.frames.append({"pc": 0x0100001b00 })
 
     def get_thread_id(self) -> int:
         return 0x19
@@ -61,21 +62,6 @@
             "signal": signal.SIGINT
         } }
 
-    def get_stackframes(self):
-        class ScriptedStackFrame:
-            def __init__(idx, cfa, pc, symbol_ctx):
-                self.idx = idx
-                self.cfa = cfa
-                self.pc = pc
-                self.symbol_ctx = symbol_ctx
-
-
-        symbol_ctx = lldb.SBSymbolContext()
-        frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
-        self.frames.append(frame_zero)
-
-        return self.frame_zero[0:0]
-
     def get_register_context(self) -> str:
         return struct.pack(
                 '21Q', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
@@ -88,4 +74,4 @@
                                      DummyScriptedProcess.__name__))
     else:
         print("Name of the class that will manage the scripted process: '%s.%s'"
-                % (__name__, DummyScriptedProcess.__name__))
\ No newline at end of file
+                % (__name__, DummyScriptedProcess.__name__))
Index: lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
+++ lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
@@ -133,3 +133,6 @@
                 break
             self.assertEqual(idx, int(reg.value, 16))
 
+        self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
+        pc = frame.GetPCAddress().GetLoadAddress(target)
+        self.assertEqual(pc, 0x0100001b00)
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
@@ -112,7 +112,14 @@
 }
 
 StructuredData::ArraySP ScriptedThreadPythonInterface::GetStackFrames() {
-  return nullptr;
+  Status error;
+  StructuredData::ArraySP arr =
+      Dispatch<StructuredData::ArraySP>("get_stackframes", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
+    return {};
+
+  return arr;
 }
 
 StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() {
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
@@ -126,6 +126,11 @@
   ScriptInterpreterPythonImpl &m_interpreter;
 };
 
+template <>
+StructuredData::ArraySP
+ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
+    python::PythonObject &p, Status &error);
+
 template <>
 StructuredData::DictionarySP
 ScriptedPythonInterface::ExtractValueFromPythonObject<
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
@@ -34,6 +34,14 @@
   return error;
 }
 
+template <>
+StructuredData::ArraySP
+ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
+    python::PythonObject &p, Status &error) {
+  python::PythonList result_list(python::PyRefType::Borrowed, p.get());
+  return result_list.CreateStructuredArray();
+}
+
 template <>
 StructuredData::DictionarySP
 ScriptedPythonInterface::ExtractValueFromPythonObject<
Index: lldb/source/Plugins/Process/scripted/ScriptedThread.h
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedThread.h
+++ lldb/source/Plugins/Process/scripted/ScriptedThread.h
@@ -42,6 +42,8 @@
   lldb::RegisterContextSP
   CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
 
+  bool LoadArtificialStackFrames();
+
   bool CalculateStopInfo() override;
 
   const char *GetInfo() override { return nullptr; }
Index: lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -147,6 +147,73 @@
   return m_reg_context_sp;
 }
 
+bool ScriptedThread::LoadArtificialStackFrames() {
+  StructuredData::ArraySP arr_sp = GetInterface()->GetStackFrames();
+
+  Status error;
+  if (!arr_sp)
+    return GetInterface()->ErrorWithMessage<bool>(
+        LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stackframes.",
+        error, LLDBLog::Thread);
+
+  size_t arr_size = arr_sp->GetSize();
+  if (arr_size > std::numeric_limits<uint32_t>::max())
+    return GetInterface()->ErrorWithMessage<bool>(
+        LLVM_PRETTY_FUNCTION,
+        llvm::Twine(
+            "StackFrame array size (" + llvm::Twine(arr_size) +
+            llvm::Twine(
+                ") is greater than maximum autorized for a StackFrameList."))
+            .str(),
+        error, LLDBLog::Thread);
+
+  StackFrameListSP frames = GetStackFrameList();
+
+  for (size_t idx = 0; idx < arr_size; idx++) {
+
+    StructuredData::Dictionary *dict;
+
+    if (!arr_sp->GetItemAtIndexAsDictionary(idx, dict) || !dict)
+      return GetInterface()->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);
+
+    lldb::addr_t pc;
+    if (!dict->GetValueForKeyAsInteger("pc", pc))
+      return ScriptedInterface::ErrorWithMessage<bool>(
+          LLVM_PRETTY_FUNCTION,
+          "Couldn't find value for key 'pc' in stackframe dictionary.", error,
+          LLDBLog::Thread);
+
+    Address symbol_addr;
+    symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget());
+
+    lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
+    bool cfa_is_valid = 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);
+
+    if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
+      return GetInterface()->ErrorWithMessage<bool>(
+          LLVM_PRETTY_FUNCTION,
+          llvm::Twine("Couldn't add frame (" + llvm::Twine(idx) +
+                      llvm::Twine(") to ScriptedThread StackFrameList."))
+              .str(),
+          error, LLDBLog::Thread);
+  }
+
+  return true;
+}
+
 bool ScriptedThread::CalculateStopInfo() {
   StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason();
 
@@ -216,6 +283,7 @@
 
 void ScriptedThread::RefreshStateAfterStop() {
   GetRegisterContext()->InvalidateIfNeeded(/*force=*/false);
+  LoadArtificialStackFrames();
 }
 
 lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const {
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -359,6 +359,7 @@
 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) {
Index: lldb/include/lldb/Target/StackFrameList.h
===================================================================
--- lldb/include/lldb/Target/StackFrameList.h
+++ lldb/include/lldb/Target/StackFrameList.h
@@ -17,6 +17,8 @@
 
 namespace lldb_private {
 
+class ScriptedThread;
+
 class StackFrameList {
 public:
   // Constructors and Destructors
@@ -86,6 +88,7 @@
 
 protected:
   friend class Thread;
+  friend class ScriptedThread;
 
   bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp);
 
Index: lldb/examples/python/scripted_process/scripted_process.py
===================================================================
--- lldb/examples/python/scripted_process/scripted_process.py
+++ lldb/examples/python/scripted_process/scripted_process.py
@@ -306,9 +306,9 @@
                 containing for each entry, the frame index, the canonical
                 frame address, the program counter value for that frame
                 and a symbol context.
-                None if the list is empty.
+                The list can be empty.
         """
-        return 0
+        return self.frames
 
     def get_register_info(self):
         if self.register_info is None:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to