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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits