[Lldb-commits] [lldb] [lldb-server] Handle jThreadExtendedInfo (PR #227472)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 1 10:56:00 PDT 2026
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/227472
>From 2631319d78ebda25546cf7e792ddb8ad32815953 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Tue, 29 Sep 2026 22:59:04 +0200
Subject: [PATCH] [lldb-server] Handle jThreadExtendedInfo
---
.../lldb/Host/common/NativeThreadProtocol.h | 3 ++
.../lldb/Utility/StringExtractorGDBRemote.h | 1 +
.../Windows/Common/NativeThreadWindows.cpp | 4 ++
.../Windows/Common/NativeThreadWindows.h | 2 +
.../GDBRemoteCommunicationServerLLGS.cpp | 49 +++++++++++++++++++
.../GDBRemoteCommunicationServerLLGS.h | 2 +
.../Utility/StringExtractorGDBRemote.cpp | 2 +
.../API/windows/thread-extended-info/Makefile | 3 ++
.../TestThreadExtendedInfo.py | 42 ++++++++++++++++
.../API/windows/thread-extended-info/main.c | 3 ++
10 files changed, 111 insertions(+)
create mode 100644 lldb/test/API/windows/thread-extended-info/Makefile
create mode 100644 lldb/test/API/windows/thread-extended-info/TestThreadExtendedInfo.py
create mode 100644 lldb/test/API/windows/thread-extended-info/main.c
diff --git a/lldb/include/lldb/Host/common/NativeThreadProtocol.h b/lldb/include/lldb/Host/common/NativeThreadProtocol.h
index 1bd16cfa26c1e..cb50794249747 100644
--- a/lldb/include/lldb/Host/common/NativeThreadProtocol.h
+++ b/lldb/include/lldb/Host/common/NativeThreadProtocol.h
@@ -13,6 +13,7 @@
#include <string>
#include "lldb/Host/Debug.h"
+#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UnimplementedError.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-types.h"
@@ -57,6 +58,8 @@ class NativeThreadProtocol {
return llvm::make_error<UnimplementedError>();
}
+ virtual StructuredData::ObjectSP GetExtendedInfo() const { return nullptr; }
+
protected:
void ClearStopInfo() {
m_stop_info = ThreadStopInfo();
diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index fec3c09f225d7..b70372db4b610 100644
--- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -178,6 +178,7 @@ class StringExtractorGDBRemote : public StringExtractor {
eServerPacketType_jAcceleratorPluginInitialize,
eServerPacketType_jAcceleratorPluginBreakpointHit,
eServerPacketType_jAcceleratorPluginGetDynamicLoaderLibraryInfo,
+ eServerPacketType_jThreadExtendedInfo,
eServerPacketType_qMemTags, // read memory tags
eServerPacketType_QMemTags, // write memory tags
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
index 0842968f25d60..b6363616cf31a 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
@@ -194,3 +194,7 @@ Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Status::FromErrorString("unimplemented.");
}
+
+StructuredData::ObjectSP NativeThreadWindows::GetExtendedInfo() const {
+ return m_host_thread.GetNativeThread().GetExtendedInfo();
+}
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
index 392a5b9a2a7d4..b867489a2fd28 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
@@ -48,6 +48,8 @@ class NativeThreadWindows : public NativeThreadProtocol {
Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
+ StructuredData::ObjectSP GetExtendedInfo() const override;
+
void SetStopReason(ThreadStopInfo stop_info, std::string description);
const HostThread &GetHostThread() { return m_host_thread; }
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 516f88aaf6076..af757691359d6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -228,6 +228,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_jMultiBreakpoint,
&GDBRemoteCommunicationServerLLGS::Handle_jMultiBreakpoint);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jThreadExtendedInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_jThreadExtendedInfo);
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_jAcceleratorPluginInitialize,
&GDBRemoteCommunicationServerLLGS::Handle_jAcceleratorPluginInitialize);
@@ -4732,3 +4735,49 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::
return SendErrorResponse(
Status::FromErrorString("unknown accelerator plugin name"));
}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jThreadExtendedInfo(
+ StringExtractorGDBRemote &packet) {
+ llvm::StringRef packet_str = packet.GetStringRef();
+ if (!packet_str.consume_front("jThreadExtendedInfo:"))
+ return SendIllFormedResponse(packet,
+ "Invalid jThreadExtendedInfo packet prefix");
+ // Empty packet is sent to check if we support jThreadExtendedInfo.
+ if (packet_str.empty())
+ return SendOKResponse();
+
+ llvm::Expected<llvm::json::Value> parsed = llvm::json::parse(packet_str);
+ if (!parsed) {
+ llvm::consumeError(parsed.takeError());
+ return SendIllFormedResponse(
+ packet, "jThreadExtendedInfo did not contain valid JSON");
+ }
+ llvm::json::Object *request_dict = parsed->getAsObject();
+ if (!request_dict)
+ return SendIllFormedResponse(
+ packet, "jThreadExtendedInfo did not contain a JSON dictionary");
+
+ std::optional<int64_t> thread_id = request_dict->getInteger("thread");
+ if (!thread_id)
+ return SendIllFormedResponse(packet, "jThreadExtendedInfo did not contain "
+ "a valid 'breakpoint_requests' field");
+
+ if (!m_current_process)
+ return SendIllFormedResponse(packet, "no current process");
+
+ NativeThreadProtocol *thread = m_current_process->GetThreadByID(*thread_id);
+ if (!thread)
+ return SendIllFormedResponse(packet, "no thread with specified ID");
+
+ StructuredData::ObjectSP ext_info = thread->GetExtendedInfo();
+
+ StreamString stream;
+ if (ext_info)
+ ext_info->Dump(stream, false);
+
+ StringRef response_str = stream.GetString();
+ StreamGDBRemote response;
+ response.PutEscapedBytes(response_str.data(), response_str.size());
+ return SendPacketNoLock(response.GetString());
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 873f24d10a627..ac24c69dee0fa 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -313,6 +313,8 @@ class GDBRemoteCommunicationServerLLGS
PacketResult Handle_jAcceleratorPluginGetDynamicLoaderLibraryInfo(
StringExtractorGDBRemote &packet);
+ PacketResult Handle_jThreadExtendedInfo(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index a015e7c3c5c8b..ed15926d621bf 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -342,6 +342,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_jAcceleratorPluginBreakpointHit;
if (PACKET_STARTS_WITH("jAcceleratorPluginGetDynamicLoaderLibraryInfo:"))
return eServerPacketType_jAcceleratorPluginGetDynamicLoaderLibraryInfo;
+ if (PACKET_STARTS_WITH("jThreadExtendedInfo:"))
+ return eServerPacketType_jThreadExtendedInfo;
break;
case 'v':
diff --git a/lldb/test/API/windows/thread-extended-info/Makefile b/lldb/test/API/windows/thread-extended-info/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/windows/thread-extended-info/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/windows/thread-extended-info/TestThreadExtendedInfo.py b/lldb/test/API/windows/thread-extended-info/TestThreadExtendedInfo.py
new file mode 100644
index 0000000000000..d530979d1e2c2
--- /dev/null
+++ b/lldb/test/API/windows/thread-extended-info/TestThreadExtendedInfo.py
@@ -0,0 +1,42 @@
+"""
+Test that the extended info of a thread contains the TEB address.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+ at requireWindows
+class TestThreadExtendedInfo(TestBase):
+ def tearDown(self):
+ self.runCmd("settings clear thread-format")
+ return super().tearDown()
+
+ @no_debug_info_test
+ def test(self):
+ self.build()
+
+ target, process, thread, _ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.c")
+ )
+
+ err = lldb.SBError()
+ fmt = lldb.SBFormat("${thread.id%%zu};${thread.info.teb_address%%zu}", err)
+ self.assertSuccess(err)
+ stream = lldb.SBStream()
+ self.assertSuccess(thread.GetDescriptionWithFormat(fmt, stream))
+ data = (stream.GetData() or "").split(";")
+ self.assertEqual(len(data), 2)
+ tid = int(data[0])
+ teb_addr = int(data[1])
+ self.assertNotEqual(tid, 0)
+ self.assertNotEqual(teb_addr, 0)
+
+ # Check that the address we got is correct by reading the thread ID out
+ # of the block.
+ tid_off = 0x48 if target.GetAddressByteSize() == 8 else 0x24
+ tid_from_teb = process.ReadUnsignedFromMemory(teb_addr + tid_off, 4, err)
+ self.assertSuccess(err)
+ self.assertEqual(tid, tid_from_teb)
diff --git a/lldb/test/API/windows/thread-extended-info/main.c b/lldb/test/API/windows/thread-extended-info/main.c
new file mode 100644
index 0000000000000..ba45ee316cd42
--- /dev/null
+++ b/lldb/test/API/windows/thread-extended-info/main.c
@@ -0,0 +1,3 @@
+int main() {
+ return 0; // break here
+}
More information about the lldb-commits
mailing list