[Lldb-commits] [lldb] r296101 - Implement QPassSignals GDB package in lldb-server

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 24 01:29:14 PST 2017


Author: labath
Date: Fri Feb 24 03:29:14 2017
New Revision: 296101

URL: http://llvm.org/viewvc/llvm-project?rev=296101&view=rev
Log:
Implement QPassSignals GDB package in lldb-server

Summary: QPassSignals package allows lldb client to tell lldb-server to ignore certain types of signals and re-inject them back to inferior without stopping execution.

Reviewers: jmajors, labath

Subscribers: danalbert, srhines, emaste, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D30286
Author: Eugene Zemtsov <ezemtsov at google.com>

Added:
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp
Modified:
    lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
    lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/POSIX/CrashReason.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
    lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp
    lldb/trunk/source/Utility/StringExtractorGDBRemote.h

Modified: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h Fri Feb 24 03:29:14 2017
@@ -17,6 +17,8 @@
 #include "lldb/Utility/Error.h"
 #include "lldb/lldb-private-forward.h"
 #include "lldb/lldb-types.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringRef.h"
 
 #include "NativeBreakpointList.h"
@@ -64,6 +66,12 @@ public:
 
   virtual Error Kill() = 0;
 
+  //------------------------------------------------------------------
+  // Tells a process not to stop the inferior on given signals
+  // and just reinject them back.
+  //------------------------------------------------------------------
+  virtual Error IgnoreSignals(llvm::ArrayRef<int> signals);
+
   //----------------------------------------------------------------------
   // Memory and memory region functions
   //----------------------------------------------------------------------
@@ -308,6 +316,10 @@ protected:
   int m_terminal_fd;
   uint32_t m_stop_id;
 
+  // Set of signal numbers that LLDB directly injects back to inferior
+  // without stopping it.
+  llvm::DenseSet<int> m_signals_to_ignore;
+
   // lldb_private::Host calls should be used to launch a process for debugging,
   // and
   // then the process should be attached to. When attaching to a process

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py Fri Feb 24 03:29:14 2017
@@ -929,7 +929,8 @@ class GdbRemoteTestCaseBase(TestBase):
         "qXfer:libraries:read",
         "qXfer:libraries-svr4:read",
         "qXfer:features:read",
-        "qEcho"
+        "qEcho",
+        "QPassSignals"
     ]
 
     def parse_qSupported_response(self, context):

Added: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile?rev=296101&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile Fri Feb 24 03:29:14 2017
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py?rev=296101&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py Fri Feb 24 03:29:14 2017
@@ -0,0 +1,113 @@
+from __future__ import print_function
+
+import gdbremote_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestGdbRemote_QPassSignals(gdbremote_testcase.GdbRemoteTestCaseBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def expect_signal(self, expected_signo):
+        self.test_sequence.add_log_lines(["read packet: $vCont;c#a8",
+                                          {"direction": "send",
+                                           "regex": r"^\$T([0-9a-fA-F]{2}).*#[0-9a-fA-F]{2}$",
+                                           "capture": {1: "hex_exit_code"}},
+                                          ],
+                                         True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        hex_exit_code = context.get("hex_exit_code")
+        self.assertIsNotNone(hex_exit_code)
+        self.assertEqual(int(hex_exit_code, 16), expected_signo)
+
+    def expect_exit_code(self, exit_code):
+        self.test_sequence.add_log_lines(
+            ["read packet: $vCont;c#a8",
+             "send packet: $W{0:02x}#00".format(exit_code)],
+            True)
+        self.expect_gdbremote_sequence()
+
+
+    def ignore_signals(self, signals):
+        def signal_name_to_hex(signame):
+            return format(lldbutil.get_signal_number(signame), 'x')
+        signals_str = ";".join(map(signal_name_to_hex, signals))
+
+        self.test_sequence.add_log_lines(["read packet: $QPassSignals:"
+                                          + signals_str + " #00",
+                                          "send packet: $OK#00"],
+                                         True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+    @llgs_test
+    @skipUnlessPlatform(["linux", "android"])
+    def test_q_pass_signals(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        procs = self.prep_debug_monitor_and_inferior()
+        expected_signals = ["SIGSEGV",
+            "SIGALRM", "SIGFPE", "SIGBUS", "SIGINT", "SIGHUP"]
+        signals_to_ignore = ["SIGUSR1", "SIGUSR2"]
+        self.ignore_signals(signals_to_ignore)
+        for signal_name in expected_signals:
+            signo = lldbutil.get_signal_number(signal_name)
+            self.expect_signal(signo)
+        self.expect_exit_code(len(signals_to_ignore))
+
+    @llgs_test
+    @skipUnlessPlatform(["linux", "android"])
+    def test_change_signals_at_runtime(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        procs = self.prep_debug_monitor_and_inferior()
+        expected_signals = ["SIGSEGV", "SIGUSR1", "SIGUSR2",
+            "SIGALRM", "SIGHUP"]
+        signals_to_ignore = ["SIGFPE", "SIGBUS", "SIGINT"]
+
+        for signal_name in expected_signals:
+            signo = lldbutil.get_signal_number(signal_name)
+            self.expect_signal(signo)
+            if signal_name == "SIGALRM":
+                self.ignore_signals(signals_to_ignore)
+        self.expect_exit_code(len(signals_to_ignore))
+
+    @llgs_test
+    def test_default_signals_behavior(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        procs = self.prep_debug_monitor_and_inferior()
+        expected_signals = ["SIGSEGV", "SIGUSR1", "SIGUSR2",
+            "SIGALRM", "SIGFPE", "SIGBUS", "SIGINT", "SIGHUP"]
+        for signal_name in expected_signals:
+            signo = lldbutil.get_signal_number(signal_name)
+            self.expect_signal(signo)
+        self.expect_exit_code(0)
+
+
+    @llgs_test
+    @skipUnlessPlatform(["linux", "android"])
+    def test_support_q_pass_signals(self):
+        self.init_llgs_test()
+        self.build()
+
+        # Start up the stub and start/prep the inferior.
+        self.set_inferior_startup_launch()
+        procs = self.prep_debug_monitor_and_inferior()
+        self.add_qSupported_packets()
+
+        # Run the packet stream.
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        # Retrieve the qSupported features and check QPassSignals+
+        supported_dict = self.parse_qSupported_response(context)
+        self.assertEqual(supported_dict["QPassSignals"], "+")

Added: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp?rev=296101&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp Fri Feb 24 03:29:14 2017
@@ -0,0 +1,37 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <signal.h>
+#include <stdio.h>
+#include <vector>
+
+static int signal_counter = 0;
+
+static void count_signal(int signo) {
+  ++signal_counter;
+  printf("Signal %d\n", signo);
+}
+
+static void raise_signals() {
+  std::vector<int> signals(
+      {SIGSEGV, SIGUSR1, SIGUSR2, SIGALRM, SIGFPE, SIGBUS, SIGINT, SIGHUP});
+
+  for (int signal_num : signals) {
+    signal(signal_num, count_signal);
+  }
+
+  for (int signal_num : signals) {
+    raise(signal_num);
+  }
+}
+
+int main() {
+  raise_signals();
+  return signal_counter;
+}

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Fri Feb 24 03:29:14 2017
@@ -46,6 +46,12 @@ lldb_private::Error NativeProcessProtoco
 #endif
 }
 
+Error NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef<int> signals) {
+  m_signals_to_ignore.clear();
+  m_signals_to_ignore.insert(signals.begin(), signals.end());
+  return Error();
+}
+
 lldb_private::Error
 NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr,
                                            MemoryRegionInfo &range_info) {

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Fri Feb 24 03:29:14 2017
@@ -1037,6 +1037,13 @@ void NativeProcessLinux::MonitorSignal(c
     return;
   }
 
+  // Check if debugger should stop at this signal or just ignore it
+  // and resume the inferior.
+  if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) {
+     ResumeThread(thread, thread.GetState(), signo);
+     return;
+  }
+
   // This thread is stopped.
   LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo));
   thread.SetStoppedBySignal(signo, &info);

Modified: lldb/trunk/source/Plugins/Process/POSIX/CrashReason.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/CrashReason.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/CrashReason.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/CrashReason.cpp Fri Feb 24 03:29:14 2017
@@ -62,7 +62,6 @@ CrashReason GetCrashReasonForSIGSEGV(con
     return CrashReason::eBoundViolation;
   }
 
-  assert(false && "unexpected si_code for SIGSEGV");
   return CrashReason::eInvalidCrashReason;
 }
 
@@ -88,7 +87,6 @@ CrashReason GetCrashReasonForSIGILL(cons
     return CrashReason::eInternalStackError;
   }
 
-  assert(false && "unexpected si_code for SIGILL");
   return CrashReason::eInvalidCrashReason;
 }
 
@@ -114,7 +112,6 @@ CrashReason GetCrashReasonForSIGFPE(cons
     return CrashReason::eFloatSubscriptRange;
   }
 
-  assert(false && "unexpected si_code for SIGFPE");
   return CrashReason::eInvalidCrashReason;
 }
 
@@ -130,7 +127,6 @@ CrashReason GetCrashReasonForSIGBUS(cons
     return CrashReason::eHardwareError;
   }
 
-  assert(false && "unexpected si_code for SIGBUS");
   return CrashReason::eInvalidCrashReason;
 }
 }
@@ -158,7 +154,7 @@ std::string GetCrashReasonString(CrashRe
 
   switch (reason) {
   default:
-    assert(false && "invalid CrashReason");
+    str = "unknown crash reason";
     break;
 
   case CrashReason::eInvalidAddress:

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp Fri Feb 24 03:29:14 2017
@@ -838,6 +838,7 @@ GDBRemoteCommunicationServerCommon::Hand
   response.PutCString(";QListThreadsInStopReply+");
   response.PutCString(";qEcho+");
 #if defined(__linux__)
+  response.PutCString(";QPassSignals+");
   response.PutCString(";qXfer:auxv:read+");
 #endif
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Fri Feb 24 03:29:14 2017
@@ -181,6 +181,9 @@ void GDBRemoteCommunicationServerLLGS::R
                                 &GDBRemoteCommunicationServerLLGS::Handle_Z);
   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
                                 &GDBRemoteCommunicationServerLLGS::Handle_z);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_QPassSignals,
+      &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
 
   RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
                         [this](StringExtractorGDBRemote packet, Error &error,
@@ -3072,6 +3075,40 @@ GDBRemoteCommunicationServerLLGS::Handle
   return SendPacketNoLock(response.GetString());
 }
 
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
+    StringExtractorGDBRemote &packet) {
+  std::vector<int> signals;
+  packet.SetFilePos(strlen("QPassSignals:"));
+
+  // Read sequence of hex signal numbers divided by a semicolon and
+  // optionally spaces.
+  while (packet.GetBytesLeft() > 0) {
+    int signal = packet.GetS32(-1, 16);
+    if (signal < 0)
+      return SendIllFormedResponse(packet, "Failed to parse signal number.");
+    signals.push_back(signal);
+
+    packet.SkipSpaces();
+    char separator = packet.GetChar();
+    if (separator == '\0')
+      break; // End of string
+    if (separator != ';')
+      return SendIllFormedResponse(packet, "Invalid separator,"
+                                            " expected semicolon.");
+  }
+
+  // Fail if we don't have a current process.
+  if (!m_debugged_process_sp)
+    return SendErrorResponse(68);
+
+  Error error = m_debugged_process_sp->IgnoreSignals(signals);
+  if (error.Fail())
+    return SendErrorResponse(69);
+
+  return SendOKResponse();
+}
+
 void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h Fri Feb 24 03:29:14 2017
@@ -203,6 +203,8 @@ protected:
 
   PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet);
 
+  PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet);
+
   void SetCurrentThreadID(lldb::tid_t tid);
 
   lldb::tid_t GetCurrentThreadID() const;

Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp (original)
+++ lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp Fri Feb 24 03:29:14 2017
@@ -91,6 +91,10 @@ StringExtractorGDBRemote::GetServerPacke
         return eServerPacketType_QEnvironmentHexEncoded;
       break;
 
+    case 'P':
+      if (PACKET_STARTS_WITH("QPassSignals:"))
+        return eServerPacketType_QPassSignals;
+
     case 'S':
       if (PACKET_MATCHES("QStartNoAckMode"))
         return eServerPacketType_QStartNoAckMode;

Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.h?rev=296101&r1=296100&r2=296101&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractorGDBRemote.h (original)
+++ lldb/trunk/source/Utility/StringExtractorGDBRemote.h Fri Feb 24 03:29:14 2017
@@ -96,6 +96,7 @@ public:
     // debug server packages
     eServerPacketType_QEnvironmentHexEncoded,
     eServerPacketType_QListThreadsInStopReply,
+    eServerPacketType_QPassSignals,
     eServerPacketType_QRestoreRegisterState,
     eServerPacketType_QSaveRegisterState,
     eServerPacketType_QSetLogging,




More information about the lldb-commits mailing list