[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