This revision was automatically updated to reflect the committed changes.
Closed by commit rG1a8f60f5f5b8: [lldb] [gdb-remote] Support getting siginfo 
via API (authored by mgorny).
Herald added a project: LLDB.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118055/new/

https://reviews.llvm.org/D118055

Files:
  lldb/bindings/interface/SBThread.i
  lldb/include/lldb/API/SBPlatform.h
  lldb/include/lldb/API/SBTarget.h
  lldb/include/lldb/API/SBThread.h
  lldb/include/lldb/API/SBType.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/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py

Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
@@ -490,3 +490,99 @@
                          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)
+
+        error = lldb.SBError()
+        siginfo = process.threads[0].GetSiginfo(error)
+        self.assertTrue(siginfo, error)
+
+        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)
Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -90,6 +90,9 @@
 
   StructuredData::ObjectSP FetchThreadExtendedInfo() override;
 
+  llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+  GetSiginfo(size_t max_size) const override;
+
 protected:
   friend class ProcessGDBRemote;
 
Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -346,3 +346,23 @@
         ->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());
+}
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -337,6 +337,8 @@
 
   bool GetQXferMemoryMapReadSupported();
 
+  bool GetQXferSigInfoReadSupported();
+
   LazyBool SupportsAllocDeallocMemory() // const
   {
     // Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -551,6 +553,7 @@
   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;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -173,6 +173,13 @@
   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 @@
     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 @@
   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 @@
         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+")
Index: lldb/source/API/SBThread.cpp
===================================================================
--- lldb/source/API/SBThread.cpp
+++ lldb/source/API/SBThread.cpp
@@ -1317,3 +1317,50 @@
 lldb_private::Thread *SBThread::get() {
   return m_opaque_sp->GetThreadSP().get();
 }
+
+SBValue SBThread::GetSiginfo(SBError &error) {
+  LLDB_INSTRUMENT_VA(this, error);
+
+  SBValue value;
+  SBProcess process = GetProcess();
+  if (!process.IsValid()) {
+    error.SetErrorString("no process");
+    return value;
+  }
+  SBTarget target = process.GetTarget();
+  if (!target.IsValid()) {
+    error.SetErrorString("unable to get target");
+    return value;
+  }
+  SBPlatform platform = target.GetPlatform();
+  if (!platform.IsValid()) {
+    error.SetErrorString("unable to get platform");
+    return value;
+  }
+  CompilerType type = platform.GetSP()->GetSiginfoType(
+      target.GetSP()->GetArchitecture().GetTriple());
+  if (!type.IsValid()) {
+    error.SetErrorString("no siginfo_t for the platform");
+    return value;
+  }
+  llvm::Optional<uint64_t> type_size = type.GetByteSize(nullptr);
+  assert(type_size);
+  ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
+  if (!thread_sp) {
+    error.SetErrorString("unable to get thread");
+    return value;
+  }
+  llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data =
+      thread_sp->GetSiginfo(type_size.getValue());
+  if (!data) {
+    error.SetErrorString(llvm::toString(data.takeError()).c_str());
+    return value;
+  }
+  SBData sb_data;
+  sb_data.SetData(error, data.get()->getBufferStart(),
+                  data.get()->getBufferSize(), process.GetByteOrder(), 0);
+  if (!sb_data.IsValid())
+    return value;
+
+  return target.CreateValueFromData("siginfo", sb_data, type);
+}
Index: lldb/include/lldb/Target/Thread.h
===================================================================
--- lldb/include/lldb/Target/Thread.h
+++ 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,11 @@
 
   lldb::ThreadSP GetCurrentExceptionBacktrace();
 
+  virtual llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+  GetSiginfo(size_t max_size) const {
+    return llvm::make_error<UnimplementedError>();
+  }
+
 protected:
   friend class ThreadPlan;
   friend class ThreadList;
Index: lldb/include/lldb/API/SBType.h
===================================================================
--- lldb/include/lldb/API/SBType.h
+++ lldb/include/lldb/API/SBType.h
@@ -225,6 +225,7 @@
   friend class SBFunction;
   friend class SBModule;
   friend class SBTarget;
+  friend class SBThread;
   friend class SBTypeEnumMember;
   friend class SBTypeEnumMemberList;
   friend class SBTypeNameSpecifier;
Index: lldb/include/lldb/API/SBThread.h
===================================================================
--- lldb/include/lldb/API/SBThread.h
+++ lldb/include/lldb/API/SBThread.h
@@ -208,6 +208,8 @@
 
   bool SafeToCallFunctions();
 
+  SBValue GetSiginfo(SBError &error);
+
 private:
   friend class SBBreakpoint;
   friend class SBBreakpointLocation;
Index: lldb/include/lldb/API/SBTarget.h
===================================================================
--- lldb/include/lldb/API/SBTarget.h
+++ lldb/include/lldb/API/SBTarget.h
@@ -875,6 +875,7 @@
   friend class SBSection;
   friend class SBSourceManager;
   friend class SBSymbol;
+  friend class SBThread;
   friend class SBValue;
   friend class SBVariablesOptions;
 
Index: lldb/include/lldb/API/SBPlatform.h
===================================================================
--- lldb/include/lldb/API/SBPlatform.h
+++ lldb/include/lldb/API/SBPlatform.h
@@ -172,6 +172,7 @@
 protected:
   friend class SBDebugger;
   friend class SBTarget;
+  friend class SBThread;
 
   lldb::PlatformSP GetSP() const;
 
Index: lldb/bindings/interface/SBThread.i
===================================================================
--- lldb/bindings/interface/SBThread.i
+++ lldb/bindings/interface/SBThread.i
@@ -405,6 +405,12 @@
     bool
     SafeToCallFunctions ();
 
+    %feature("autodoc","
+    Retruns a SBValue object representing the siginfo for the current signal.
+    ") GetSiginfo;
+    lldb::SBValue
+    GetSiginfo(SBError &error);
+
     STRING_EXTENSION(SBThread)
 
 #ifdef SWIGPYTHON
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to