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