[Lldb-commits] [lldb] ac666d1 - [lldb] [gdb-remote] Support getting siginfo via API
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 28 08:47:58 PST 2022
Author: Michał Górny
Date: 2022-01-28T17:47:47+01:00
New Revision: ac666d1799c45a1ecd59f7503e1fc649deffd4d4
URL: https://github.com/llvm/llvm-project/commit/ac666d1799c45a1ecd59f7503e1fc649deffd4d4
DIFF: https://github.com/llvm/llvm-project/commit/ac666d1799c45a1ecd59f7503e1fc649deffd4d4.diff
LOG: [lldb] [gdb-remote] Support getting siginfo via API
Add Thread::GetSiginfo() and SBThread::GetSiginfo() methods to retrieve
the siginfo value from server.
Differential Revision: https://reviews.llvm.org/D118055
Added:
Modified:
lldb/bindings/interface/SBThread.i
lldb/include/lldb/API/SBThread.h
lldb/include/lldb/Target/Thread.h
lldb/source/API/SBThread.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
lldb/source/Target/Thread.cpp
lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
Removed:
################################################################################
diff --git a/lldb/bindings/interface/SBThread.i b/lldb/bindings/interface/SBThread.i
index d847d38f0d66..1e46bd6e21f6 100644
--- a/lldb/bindings/interface/SBThread.i
+++ b/lldb/bindings/interface/SBThread.i
@@ -405,6 +405,12 @@ public:
bool
SafeToCallFunctions ();
+ %feature("autodoc","
+ Retruns a SBValue object representing the siginfo for the current signal.
+ ") GetSiginfo;
+ lldb::SBValue
+ GetSiginfo();
+
STRING_EXTENSION(SBThread)
#ifdef SWIGPYTHON
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index ac1b8407a220..924aae2f109a 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -208,6 +208,8 @@ class LLDB_API SBThread {
bool SafeToCallFunctions();
+ SBValue GetSiginfo();
+
private:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 587b29eb4c66..2fd7d8859f52 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -22,6 +22,7 @@
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/StructuredData.h"
+#include "lldb/Utility/UnimplementedError.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
@@ -1184,6 +1185,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
lldb::ThreadSP GetCurrentExceptionBacktrace();
+ lldb::ValueObjectSP GetSiginfoValue();
+
protected:
friend class ThreadPlan;
friend class ThreadList;
@@ -1233,6 +1236,11 @@ class Thread : public std::enable_shared_from_this<Thread>,
void FrameSelectedCallback(lldb_private::StackFrame *frame);
+ virtual llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ GetSiginfo(size_t max_size) const {
+ return llvm::make_error<UnimplementedError>();
+ }
+
// Classes that inherit from Process can see and modify these
lldb::ProcessWP m_process_wp; ///< The process that owns this thread.
lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 46a6c2759140..a08cb741814b 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -1317,3 +1317,12 @@ lldb_private::Thread *SBThread::operator->() {
lldb_private::Thread *SBThread::get() {
return m_opaque_sp->GetThreadSP().get();
}
+
+SBValue SBThread::GetSiginfo() {
+ LLDB_INSTRUMENT_VA(this);
+
+ ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
+ if (!thread_sp)
+ return SBValue();
+ return thread_sp->GetSiginfoValue();
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b5b105351de5..f6526d03863b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -173,6 +173,13 @@ bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
return m_supports_qXfer_memory_map_read == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() {
+ if (m_supports_qXfer_siginfo_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_siginfo_read == eLazyBoolYes;
+}
+
uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
if (m_max_packet_size == 0) {
GetRemoteQSupported();
@@ -273,6 +280,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qXfer_features_read = eLazyBoolCalculate;
m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_uses_native_signals = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
@@ -320,6 +328,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
m_supports_qXfer_memory_map_read = eLazyBoolNo;
+ m_supports_qXfer_siginfo_read = eLazyBoolNo;
m_supports_multiprocess = eLazyBoolNo;
m_supports_qEcho = eLazyBoolNo;
m_supports_QPassSignals = eLazyBoolNo;
@@ -362,6 +371,8 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_features_read = eLazyBoolYes;
else if (x == "qXfer:memory-map:read+")
m_supports_qXfer_memory_map_read = eLazyBoolYes;
+ else if (x == "qXfer:siginfo:read+")
+ m_supports_qXfer_siginfo_read = eLazyBoolYes;
else if (x == "qEcho")
m_supports_qEcho = eLazyBoolYes;
else if (x == "QPassSignals+")
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index c69c33bb1c15..58ed22187747 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -337,6 +337,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
bool GetQXferMemoryMapReadSupported();
+ bool GetQXferSigInfoReadSupported();
+
LazyBool SupportsAllocDeallocMemory() // const
{
// Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -551,6 +553,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate;
LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate;
LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index ba73115e4ad6..3d23c074c1be 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -346,3 +346,23 @@ bool ThreadGDBRemote::CalculateStopInfo() {
->CalculateThreadStopInfo(this);
return false;
}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ThreadGDBRemote::GetSiginfo(size_t max_size) const {
+ ProcessSP process_sp(GetProcess());
+ if (!process_sp)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "no process");
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ if (!gdb_process->m_gdb_comm.GetQXferSigInfoReadSupported())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "qXfer:siginfo:read not supported");
+
+ llvm::Expected<std::string> response =
+ gdb_process->m_gdb_comm.ReadExtFeature("siginfo", "");
+ if (!response)
+ return response.takeError();
+
+ return llvm::MemoryBuffer::getMemBufferCopy(response.get());
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index b7d75021c062..5bc90a3dedce 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -115,6 +115,9 @@ class ThreadGDBRemote : public Thread {
void SetStopInfoFromPacket(StringExtractor &stop_packet, uint32_t stop_id);
bool CalculateStopInfo() override;
+
+ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ GetSiginfo(size_t max_size) const override;
};
} // namespace process_gdb_remote
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index c5f16b4e6c1d..bde6dad554e7 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -2005,3 +2006,26 @@ ThreadSP Thread::GetCurrentExceptionBacktrace() {
return ThreadSP();
}
+
+lldb::ValueObjectSP Thread::GetSiginfoValue() {
+ ProcessSP process_sp = GetProcess();
+ assert(process_sp);
+ Target &target = process_sp->GetTarget();
+ PlatformSP platform_sp = target.GetPlatform();
+ assert(platform_sp);
+ ArchSpec arch = target.GetArchitecture();
+
+ CompilerType type = platform_sp->GetSiginfoType(arch.GetTriple());
+ if (!type.IsValid())
+ return ValueObjectConstResult::Create(&target, Status("no siginfo_t for the platform"));
+
+ llvm::Optional<uint64_t> type_size = type.GetByteSize(nullptr);
+ assert(type_size);
+ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = GetSiginfo(type_size.getValue());
+ if (!data)
+ return ValueObjectConstResult::Create(&target, Status(data.takeError()));
+
+ DataExtractor data_extractor{data.get()->getBufferStart(), data.get()->getBufferSize(),
+ process_sp->GetByteOrder(), arch.GetAddressByteSize()};
+ return ValueObjectConstResult::Create(&target, type, ConstString("__lldb_siginfo"), data_extractor);
+}
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
index 16cf4b4547c3..8d12bd7247b6 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
@@ -490,3 +490,98 @@ def cont(self):
lldb.eStopReasonSignal)
self.assertEqual(process.threads[0].GetStopDescription(100),
'signal SIGUSR1')
+
+ def do_siginfo_test(self, platform, target_yaml, raw_data, expected):
+ class MyResponder(MockGDBServerResponder):
+ def qSupported(self, client_supported):
+ return "PacketSize=3fff;QStartNoAckMode+;qXfer:siginfo:read+"
+
+ def qXferRead(self, obj, annex, offset, length):
+ if obj == "siginfo":
+ return raw_data, False
+ else:
+ return None, False
+
+ def haltReason(self):
+ return "T02"
+
+ def cont(self):
+ return self.haltReason()
+
+ self.server.responder = MyResponder()
+
+ self.runCmd("platform select " + platform)
+ target = self.createTarget(target_yaml)
+ process = self.connect(target)
+
+ siginfo = process.threads[0].GetSiginfo()
+ self.assertTrue(siginfo.GetError().Success(), siginfo.GetError())
+
+ for key, value in expected.items():
+ self.assertEqual(siginfo.GetValueForExpressionPath("." + key)
+ .GetValueAsUnsigned(),
+ value)
+
+
+ def test_siginfo_linux_amd64(self):
+ data = (
+ # si_signo si_errno si_code
+ "\x11\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
+ # __pad0 si_pid si_uid
+ "\x00\x00\x00\x00\xbf\xf7\x0b\x00\xe8\x03\x00\x00"
+ # si_status
+ "\x0c\x00\x00\x00" + "\x00" * 100)
+ expected = {
+ "si_signo": 17, # SIGCHLD
+ "si_errno": 0,
+ "si_code": 1, # CLD_EXITED
+ "_sifields._sigchld.si_pid": 784319,
+ "_sifields._sigchld.si_uid": 1000,
+ "_sifields._sigchld.si_status": 12,
+ "_sifields._sigchld.si_utime": 0,
+ "_sifields._sigchld.si_stime": 0,
+ }
+ self.do_siginfo_test("remote-linux", "basic_eh_frame.yaml",
+ data, expected)
+
+ def test_siginfo_linux_i386(self):
+ data = (
+ # si_signo si_errno si_code
+ "\x11\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
+ # si_pid si_uid si_status
+ "\x49\x43\x07\x00\xe8\x03\x00\x00\x0c\x00\x00\x00"
+ + "\x00" * 104)
+ expected = {
+ "si_signo": 17, # SIGCHLD
+ "si_errno": 0,
+ "si_code": 1, # CLD_EXITED
+ "_sifields._sigchld.si_pid": 475977,
+ "_sifields._sigchld.si_uid": 1000,
+ "_sifields._sigchld.si_status": 12,
+ "_sifields._sigchld.si_utime": 0,
+ "_sifields._sigchld.si_stime": 0,
+ }
+ self.do_siginfo_test("remote-linux", "basic_eh_frame-i386.yaml",
+ data, expected)
+
+ def test_siginfo_freebsd_amd64(self):
+ data = (
+ # si_signo si_errno si_code
+ "\x0b\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
+ # si_pid si_uid si_status
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ # si_addr
+ "\x76\x98\xba\xdc\xfe\x00\x00\x00"
+ # si_status si_trapno
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00"
+ + "\x00" * 36)
+
+ expected = {
+ "si_signo": 11, # SIGSEGV
+ "si_errno": 0,
+ "si_code": 1, # SEGV_MAPERR
+ "si_addr": 0xfedcba9876,
+ "_reason._fault._trapno": 12,
+ }
+ self.do_siginfo_test("remote-freebsd", "basic_eh_frame.yaml",
+ data, expected)
More information about the lldb-commits
mailing list