[Lldb-commits] [lldb] [lldb] Add alternative SBThread::GetStopDescription (PR #165379)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Oct 28 05:09:40 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Ebuka Ezike (da-viper)
<details>
<summary>Changes</summary>
the function signature for `GetStopDescription` is `lldb::SBThread::GetStopDescription(char *dst_or_null, size_t len)`.
To get a description you need to call the function first time to get the buffer size. a second time to get the description.
This is little worse from the python size as the signature is `lldb.SBThread.GetStopDescription(int: len) -> list[str]` the user has to pass the max size as possible with no way of checking if it is enough.
This patch adds a new api
`lldb.SBThread.GetStopDescription(desc: lldb.SBStream()) -> bool` `bool lldb::SBThread::GetStopDescription(lldb::SBStream &description)` which handles this case.
Adds test case for lua.
---
Full diff: https://github.com/llvm/llvm-project/pull/165379.diff
8 Files Affected:
- (modified) lldb/bindings/lua/lua-typemaps.swig (+8-1)
- (modified) lldb/bindings/python/python-typemaps.swig (+7)
- (modified) lldb/include/lldb/API/SBThread.h (+8)
- (modified) lldb/source/API/SBThread.cpp (+29-6)
- (added) lldb/test/API/lua_api/TestThreadAPI.lua (+25)
- (modified) lldb/test/API/python_api/default-constructor/sb_thread.py (+1)
- (modified) lldb/test/API/python_api/thread/TestThreadAPI.py (+5)
- (modified) lldb/tools/lldb-rpc-gen/RPCCommon.cpp (+1)
``````````diff
diff --git a/lldb/bindings/lua/lua-typemaps.swig b/lldb/bindings/lua/lua-typemaps.swig
index 56756936a532c..26163c1ad3328 100644
--- a/lldb/bindings/lua/lua-typemaps.swig
+++ b/lldb/bindings/lua/lua-typemaps.swig
@@ -121,9 +121,16 @@ LLDB_NUMBER_TYPEMAP(enum SWIGTYPE);
$1 = (char *)malloc($2);
}
+// Remove the default type check for this match.
+// because if the match function has an overload and a typemap,
+// it will typecheck against the original function instead of the
+// typemap.
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (char *dst_or_null, size_t dst_len) ""
+
%typemap(argout) (char *dst_or_null, size_t dst_len) {
lua_pop(L, 1); // Blow away the previous result
- lua_pushlstring(L, (const char *)$1, $result);
+ llvm::StringRef ref($1);
+ lua_pushlstring(L, (const char *)$1, ref.size());
free($1);
// SWIG_arg was already incremented
}
diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig
index 715914fe745f8..a7fa40445b5d0 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -224,6 +224,13 @@ AND call SWIG_fail at the same time, because it will result in a double free.
}
$1 = (char *)malloc($2);
}
+
+// Remove the default type check for this match.
+// because if the match function has an overload and a typemap,
+// it will typecheck against the original function instead of the
+// typemap.
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (char *dst_or_null, size_t dst_len) ""
+
%typemap(argout) (char *dst_or_null, size_t dst_len) {
Py_XDECREF($result); /* Blow away any previous result */
llvm::StringRef ref($1);
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index e9fe5858d125e..2411dfd376519 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -81,6 +81,14 @@ class LLDB_API SBThread {
SBThreadCollection
GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type);
+ /// Gets a human-readable description of why the thread stopped.
+ ///
+ /// \param stream Output stream to receive the stop description text
+ /// \return
+ /// true if obtained and written to the stream,
+ // false if there was an error retrieving the description.
+ bool GetStopDescription(lldb::SBStream &stream) const;
+
size_t GetStopDescription(char *dst_or_null, size_t dst_len);
SBValue GetStopReturnValue();
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 4e4aa48bc9a2e..f58a1b52afa91 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -239,11 +239,34 @@ SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
return threads;
}
-size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
- LLDB_INSTRUMENT_VA(this, dst, dst_len);
+bool SBThread::GetStopDescription(lldb::SBStream &stream) const {
+ LLDB_INSTRUMENT_VA(this, stream);
+
+ if (!m_opaque_sp)
+ return false;
+
+ llvm::Expected<StoppedExecutionContext> exe_ctx =
+ GetStoppedExecutionContext(m_opaque_sp);
+ if (!exe_ctx) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
+ return false;
+ }
+
+ if (!exe_ctx->HasThreadScope())
+ return false;
+
+ Stream &strm = stream.ref();
+ const std::string stop_desc = exe_ctx->GetThreadPtr()->GetStopDescription();
+ strm.PutCString(stop_desc);
+
+ return true;
+}
+
+size_t SBThread::GetStopDescription(char *dst_or_null, size_t dst_len) {
+ LLDB_INSTRUMENT_VA(this, dst_or_null, dst_len);
- if (dst)
- *dst = 0;
+ if (dst_or_null)
+ *dst_or_null = 0;
llvm::Expected<StoppedExecutionContext> exe_ctx =
GetStoppedExecutionContext(m_opaque_sp);
@@ -259,8 +282,8 @@ size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
if (thread_stop_desc.empty())
return 0;
- if (dst)
- return ::snprintf(dst, dst_len, "%s", thread_stop_desc.c_str()) + 1;
+ if (dst_or_null)
+ return ::snprintf(dst_or_null, dst_len, "%s", thread_stop_desc.c_str()) + 1;
// NULL dst passed in, return the length needed to contain the
// description.
diff --git a/lldb/test/API/lua_api/TestThreadAPI.lua b/lldb/test/API/lua_api/TestThreadAPI.lua
new file mode 100644
index 0000000000000..5a38d0ba9192f
--- /dev/null
+++ b/lldb/test/API/lua_api/TestThreadAPI.lua
@@ -0,0 +1,25 @@
+_T = require('lua_lldb_test').create_test('TestThreadAPI')
+
+function _T:TestGetStopDescription()
+ local target = self:create_target()
+ local breakpoint = target:BreakpointCreateByName("main", "a.out")
+ assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
+
+ local process = target:LaunchSimple({ 'arg1', 'arg2' }, nil, nil)
+ local thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+ assertNotNil(thread)
+ assertTrue(thread:IsValid())
+
+ assertEqual("breakpoint", thread:GetStopDescription(string.len("breakpoint") + 1))
+ assertEqual("break", thread:GetStopDescription(string.len("break") + 1))
+ assertEqual("b", thread:GetStopDescription(string.len("b") + 1))
+ assertEqual("breakpoint 1.1", thread:GetStopDescription(string.len("breakpoint 1.1") + 100))
+
+ -- Test stream variation
+ local stream = lldb.SBStream()
+ assertTrue(thread:GetStopDescription(stream))
+ assertNotNil(stream)
+ assertEqual("breakpoint 1.1", stream:GetData())
+end
+
+os.exit(_T:run())
diff --git a/lldb/test/API/python_api/default-constructor/sb_thread.py b/lldb/test/API/python_api/default-constructor/sb_thread.py
index 34eb3db852c38..4252fa0321fff 100644
--- a/lldb/test/API/python_api/default-constructor/sb_thread.py
+++ b/lldb/test/API/python_api/default-constructor/sb_thread.py
@@ -10,6 +10,7 @@ def fuzz_obj(obj):
obj.GetStopReasonDataCount()
obj.GetStopReasonDataAtIndex(100)
obj.GetStopDescription(256)
+ obj.GetStopDescription(lldb.SBStream())
obj.GetThreadID()
obj.GetIndexID()
obj.GetName()
diff --git a/lldb/test/API/python_api/thread/TestThreadAPI.py b/lldb/test/API/python_api/thread/TestThreadAPI.py
index 5583434a742a9..acad7583eec19 100644
--- a/lldb/test/API/python_api/thread/TestThreadAPI.py
+++ b/lldb/test/API/python_api/thread/TestThreadAPI.py
@@ -138,6 +138,11 @@ def get_stop_description(self):
"breakpoint 1.1", thread.GetStopDescription(len("breakpoint 1.1") + 100)
)
+ # Test the stream variation
+ stream = lldb.SBStream()
+ self.assertTrue(thread.GetStopDescription(stream))
+ self.assertEqual("breakpoint 1.1", stream.GetData())
+
def step_out_of_malloc_into_function_b(self, exe_name):
"""Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b()."""
exe = self.getBuildArtifact(exe_name)
diff --git a/lldb/tools/lldb-rpc-gen/RPCCommon.cpp b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp
index 7af6ee37f248b..5405f77b31d96 100644
--- a/lldb/tools/lldb-rpc-gen/RPCCommon.cpp
+++ b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp
@@ -118,6 +118,7 @@ static constexpr llvm::StringRef MethodsWithPointerPlusLen[] = {
"_ZN4lldb8SBTarget15GetInstructionsEyPKvm",
"_ZN4lldb8SBTarget25GetInstructionsWithFlavorEyPKcPKvm",
"_ZN4lldb8SBThread18GetStopDescriptionEPcm",
+ "_ZNK4lldb8SBThread18GetStopDescriptionERNS_8SBStreamE",
// The below mangled names are used for dummy methods in shell tests
// that test the emitters' output. If you're adding any new mangled names
// from the actual SB API to this list please add them above.
``````````
</details>
https://github.com/llvm/llvm-project/pull/165379
More information about the lldb-commits
mailing list