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@google.com>

llvm-svn: 296101
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index b8f4997..0beabc6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -181,6 +181,9 @@
                                 &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 @@
   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));