diff options
Diffstat (limited to 'lldb/source')
6 files changed, 133 insertions, 1 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 5f5dd3e79d5..5e031e74e59 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -87,6 +87,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), + m_supports_QPassSignals(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -150,6 +151,13 @@ bool GDBRemoteCommunicationClient::GetEchoSupported() { return m_supports_qEcho == eLazyBoolYes; } +bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() { + if (m_supports_QPassSignals == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_QPassSignals == eLazyBoolYes; +} + bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() { if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) { GetRemoteQSupported(); @@ -419,6 +427,11 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { else m_supports_qEcho = eLazyBoolNo; + if (::strstr(response_cstr, "QPassSignals+")) + m_supports_QPassSignals = eLazyBoolYes; + else + m_supports_QPassSignals = eLazyBoolNo; + const char *packet_size_str = ::strstr(response_cstr, "PacketSize="); if (packet_size_str) { StringExtractorGDBRemote packet_response(packet_size_str + @@ -3570,6 +3583,26 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { : nullptr; } +Error GDBRemoteCommunicationClient::SendSignalsToIgnore( + llvm::ArrayRef<int32_t> signals) { + // Format packet: + // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN> + auto range = llvm::make_range(signals.begin(), signals.end()); + std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str(); + + StringExtractorGDBRemote response; + auto send_status = SendPacketAndWaitForResponse(packet, response, false); + + if (send_status != GDBRemoteCommunication::PacketResult::Success) + return Error("Sending QPassSignals packet failed"); + + if (response.IsOKResponse()) { + return Error(); + } else { + return Error("Unknown error happened during sending QPassSignals packet."); + } +} + Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { Error error; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 83162a662e0..63b9708cc9a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -347,6 +347,8 @@ public: bool GetEchoSupported(); + bool GetQPassSignalsSupported(); + bool GetAugmentedLibrariesSVR4ReadSupported(); bool GetQXferFeaturesReadSupported(); @@ -450,6 +452,9 @@ public: void ServeSymbolLookups(lldb_private::Process *process); + // Sends QPassSignals packet to the server with given signals to ignore. + Error SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals); + //------------------------------------------------------------------ /// Return the feature set supported by the gdb-remote server. /// @@ -527,6 +532,7 @@ protected: LazyBool m_supports_jThreadExtendedInfo; LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; + LazyBool m_supports_QPassSignals; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 5ff6e809dcd..3eb3152f03d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -80,8 +80,8 @@ #include "lldb/Host/Host.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Threading.h" +#include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" using namespace lldb; @@ -3739,6 +3739,43 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( return false; } +Error ProcessGDBRemote::UpdateAutomaticSignalFiltering() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG(log, "Check if need to update ignored signals"); + + // QPassSignals package is not supported by the server, + // there is no way we can ignore any signals on server side. + if (!m_gdb_comm.GetQPassSignalsSupported()) + return Error(); + + // No signals, nothing to send. + if (m_unix_signals_sp == nullptr) + return Error(); + + // Signals' version hasn't changed, no need to send anything. + uint64_t new_signals_version = m_unix_signals_sp->GetVersion(); + if (new_signals_version == m_last_signals_version) { + LLDB_LOG(log, "Signals' version hasn't changed. version={0}", + m_last_signals_version); + return Error(); + } + + auto signals_to_ignore = + m_unix_signals_sp->GetFilteredSignals(false, false, false); + Error error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore); + + LLDB_LOG(log, + "Signals' version changed. old version={0}, new version={1}, " + "signals ignored={2}, update result={3}", + m_last_signals_version, new_signals_version, + signals_to_ignore.size(), error); + + if (error.Success()) + m_last_signals_version = new_signals_version; + + return error; +} + bool ProcessGDBRemote::StartNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_thread_create_bp_sp) { diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index bb00af8ae6c..ec8827ad102 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -397,12 +397,15 @@ protected: lldb::addr_t base_addr, bool value_is_offset); + Error UpdateAutomaticSignalFiltering() override; + private: //------------------------------------------------------------------ // For ProcessGDBRemote only //------------------------------------------------------------------ std::string m_partial_profile_data; std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map; + uint64_t m_last_signals_version = 0; static bool NewThreadNotifyBreakpointHit(void *baton, StoppointCallbackContext *context, diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index d0651e6bda7..e2006f4bbc3 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2778,6 +2778,10 @@ Error Process::Launch(ProcessLaunchInfo &launch_info) { if (!m_os_ap) LoadOperatingSystemPlugin(false); + // We successfully launched the process and stopped, + // now it the right time to set up signal filters before resuming. + UpdateAutomaticSignalFiltering(); + // Note, the stop event was consumed above, but not handled. This // was done // to give DidLaunch a chance to run. The target is either stopped @@ -3257,6 +3261,10 @@ Error Process::PrivateResume() { m_mod_id.GetStopID(), StateAsCString(m_public_state.GetValue()), StateAsCString(m_private_state.GetValue())); + // If signals handing status changed we might want to update + // our signal filters before resuming. + UpdateAutomaticSignalFiltering(); + Error error(WillResume()); // Tell the process it is about to resume before the thread list if (error.Success()) { @@ -6219,3 +6227,9 @@ bool Process::RouteAsyncStructuredData( find_it->second->HandleArrivalOfStructuredData(*this, type_name, object_sp); return true; } + +Error Process::UpdateAutomaticSignalFiltering() { + // Default implementation does nothign. + // No automatic signal filtering to speak of. + return Error(); +} diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp index cee69bf67db..a4ec32bd007 100644 --- a/lldb/source/Target/UnixSignals.cpp +++ b/lldb/source/Target/UnixSignals.cpp @@ -123,12 +123,14 @@ void UnixSignals::AddSignal(int signo, const char *name, bool default_suppress, Signal new_signal(name, default_suppress, default_stop, default_notify, description, alias); m_signals.insert(std::make_pair(signo, new_signal)); + ++m_version; } void UnixSignals::RemoveSignal(int signo) { collection::iterator pos = m_signals.find(signo); if (pos != m_signals.end()) m_signals.erase(pos); + ++m_version; } const char *UnixSignals::GetSignalAsCString(int signo) const { @@ -217,6 +219,7 @@ bool UnixSignals::SetShouldSuppress(int signo, bool value) { collection::iterator pos = m_signals.find(signo); if (pos != m_signals.end()) { pos->second.m_suppress = value; + ++m_version; return true; } return false; @@ -240,6 +243,7 @@ bool UnixSignals::SetShouldStop(int signo, bool value) { collection::iterator pos = m_signals.find(signo); if (pos != m_signals.end()) { pos->second.m_stop = value; + ++m_version; return true; } return false; @@ -263,6 +267,7 @@ bool UnixSignals::SetShouldNotify(int signo, bool value) { collection::iterator pos = m_signals.find(signo); if (pos != m_signals.end()) { pos->second.m_notify = value; + ++m_version; return true; } return false; @@ -284,3 +289,37 @@ int32_t UnixSignals::GetSignalAtIndex(int32_t index) const { std::advance(it, index); return it->first; } + +uint64_t UnixSignals::GetVersion() const { return m_version; } + +std::vector<int32_t> +UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress, + llvm::Optional<bool> should_stop, + llvm::Optional<bool> should_notify) { + std::vector<int32_t> result; + for (int32_t signo = GetFirstSignalNumber(); + signo != LLDB_INVALID_SIGNAL_NUMBER; + signo = GetNextSignalNumber(signo)) { + + bool signal_suppress = false; + bool signal_stop = false; + bool signal_notify = false; + GetSignalInfo(signo, signal_suppress, signal_stop, signal_notify); + + // If any of filtering conditions are not met, + // we move on to the next signal. + if (should_suppress.hasValue() && + signal_suppress != should_suppress.getValue()) + continue; + + if (should_stop.hasValue() && signal_stop != should_stop.getValue()) + continue; + + if (should_notify.hasValue() && signal_notify != should_notify.getValue()) + continue; + + result.push_back(signo); + } + + return result; +} |