1254721Semaste//===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9309124Sdim#include "lldb/Target/UnixSignals.h" 10288943Sdim#include "Plugins/Process/Utility/FreeBSDSignals.h" 11288943Sdim#include "Plugins/Process/Utility/LinuxSignals.h" 12288943Sdim#include "Plugins/Process/Utility/MipsLinuxSignals.h" 13296417Sdim#include "Plugins/Process/Utility/NetBSDSignals.h" 14353358Sdim#include "lldb/Host/HostInfo.h" 15314564Sdim#include "lldb/Host/StringConvert.h" 16327952Sdim#include "lldb/Utility/ArchSpec.h" 17288943Sdim 18254721Semasteusing namespace lldb_private; 19254721Semaste 20314564SdimUnixSignals::Signal::Signal(const char *name, bool default_suppress, 21314564Sdim bool default_stop, bool default_notify, 22314564Sdim const char *description, const char *alias) 23314564Sdim : m_name(name), m_alias(alias), m_description(), 24314564Sdim m_suppress(default_suppress), m_stop(default_stop), 25314564Sdim m_notify(default_notify) { 26314564Sdim if (description) 27314564Sdim m_description.assign(description); 28254721Semaste} 29254721Semaste 30314564Sdimlldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) { 31314564Sdim const auto &triple = arch.GetTriple(); 32314564Sdim switch (triple.getOS()) { 33314564Sdim case llvm::Triple::Linux: { 34314564Sdim switch (triple.getArch()) { 35314564Sdim case llvm::Triple::mips: 36314564Sdim case llvm::Triple::mipsel: 37314564Sdim case llvm::Triple::mips64: 38314564Sdim case llvm::Triple::mips64el: 39314564Sdim return std::make_shared<MipsLinuxSignals>(); 40314564Sdim default: 41314564Sdim return std::make_shared<LinuxSignals>(); 42288943Sdim } 43314564Sdim } 44314564Sdim case llvm::Triple::FreeBSD: 45314564Sdim case llvm::Triple::OpenBSD: 46314564Sdim return std::make_shared<FreeBSDSignals>(); 47314564Sdim case llvm::Triple::NetBSD: 48314564Sdim return std::make_shared<NetBSDSignals>(); 49314564Sdim default: 50314564Sdim return std::make_shared<UnixSignals>(); 51314564Sdim } 52288943Sdim} 53288943Sdim 54353358Sdimlldb::UnixSignalsSP UnixSignals::CreateForHost() { 55353358Sdim static lldb::UnixSignalsSP s_unix_signals_sp = 56353358Sdim Create(HostInfo::GetArchitecture()); 57353358Sdim return s_unix_signals_sp; 58353358Sdim} 59353358Sdim 60254721Semaste// UnixSignals constructor 61314564SdimUnixSignals::UnixSignals() { Reset(); } 62254721Semaste 63314564SdimUnixSignals::UnixSignals(const UnixSignals &rhs) : m_signals(rhs.m_signals) {} 64288943Sdim 65309124SdimUnixSignals::~UnixSignals() = default; 66254721Semaste 67314564Sdimvoid UnixSignals::Reset() { 68314564Sdim // This builds one standard set of Unix Signals. If yours aren't quite in 69341825Sdim // this order, you can either subclass this class, and use Add & Remove to 70341825Sdim // change them 71314564Sdim // or you can subclass and build them afresh in your constructor; 72314564Sdim // 73314564Sdim // Note: the signals below are the Darwin signals. Do not change these! 74314564Sdim m_signals.clear(); 75314564Sdim // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION 76314564Sdim // ====== ============ ======== ====== ====== 77314564Sdim // =================================================== 78314564Sdim AddSignal(1, "SIGHUP", false, true, true, "hangup"); 79314564Sdim AddSignal(2, "SIGINT", true, true, true, "interrupt"); 80314564Sdim AddSignal(3, "SIGQUIT", false, true, true, "quit"); 81314564Sdim AddSignal(4, "SIGILL", false, true, true, "illegal instruction"); 82314564Sdim AddSignal(5, "SIGTRAP", true, true, true, 83314564Sdim "trace trap (not reset when caught)"); 84314564Sdim AddSignal(6, "SIGABRT", false, true, true, "abort()"); 85314564Sdim AddSignal(7, "SIGEMT", false, true, true, "pollable event"); 86314564Sdim AddSignal(8, "SIGFPE", false, true, true, "floating point exception"); 87314564Sdim AddSignal(9, "SIGKILL", false, true, true, "kill"); 88314564Sdim AddSignal(10, "SIGBUS", false, true, true, "bus error"); 89314564Sdim AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation"); 90314564Sdim AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call"); 91344779Sdim AddSignal(13, "SIGPIPE", false, false, false, 92314564Sdim "write on a pipe with no one to read it"); 93314564Sdim AddSignal(14, "SIGALRM", false, false, false, "alarm clock"); 94314564Sdim AddSignal(15, "SIGTERM", false, true, true, 95314564Sdim "software termination signal from kill"); 96314564Sdim AddSignal(16, "SIGURG", false, false, false, 97314564Sdim "urgent condition on IO channel"); 98314564Sdim AddSignal(17, "SIGSTOP", true, true, true, 99314564Sdim "sendable stop signal not from tty"); 100314564Sdim AddSignal(18, "SIGTSTP", false, true, true, "stop signal from tty"); 101314564Sdim AddSignal(19, "SIGCONT", false, true, true, "continue a stopped process"); 102314564Sdim AddSignal(20, "SIGCHLD", false, false, false, 103314564Sdim "to parent on child stop or exit"); 104314564Sdim AddSignal(21, "SIGTTIN", false, true, true, 105314564Sdim "to readers process group upon background tty read"); 106314564Sdim AddSignal(22, "SIGTTOU", false, true, true, 107314564Sdim "to readers process group upon background tty write"); 108314564Sdim AddSignal(23, "SIGIO", false, false, false, "input/output possible signal"); 109314564Sdim AddSignal(24, "SIGXCPU", false, true, true, "exceeded CPU time limit"); 110314564Sdim AddSignal(25, "SIGXFSZ", false, true, true, "exceeded file size limit"); 111314564Sdim AddSignal(26, "SIGVTALRM", false, false, false, "virtual time alarm"); 112314564Sdim AddSignal(27, "SIGPROF", false, false, false, "profiling time alarm"); 113314564Sdim AddSignal(28, "SIGWINCH", false, false, false, "window size changes"); 114314564Sdim AddSignal(29, "SIGINFO", false, true, true, "information request"); 115314564Sdim AddSignal(30, "SIGUSR1", false, true, true, "user defined signal 1"); 116314564Sdim AddSignal(31, "SIGUSR2", false, true, true, "user defined signal 2"); 117254721Semaste} 118254721Semaste 119314564Sdimvoid UnixSignals::AddSignal(int signo, const char *name, bool default_suppress, 120314564Sdim bool default_stop, bool default_notify, 121314564Sdim const char *description, const char *alias) { 122314564Sdim Signal new_signal(name, default_suppress, default_stop, default_notify, 123314564Sdim description, alias); 124314564Sdim m_signals.insert(std::make_pair(signo, new_signal)); 125321369Sdim ++m_version; 126254721Semaste} 127254721Semaste 128314564Sdimvoid UnixSignals::RemoveSignal(int signo) { 129314564Sdim collection::iterator pos = m_signals.find(signo); 130314564Sdim if (pos != m_signals.end()) 131314564Sdim m_signals.erase(pos); 132321369Sdim ++m_version; 133254721Semaste} 134254721Semaste 135314564Sdimconst char *UnixSignals::GetSignalAsCString(int signo) const { 136314564Sdim collection::const_iterator pos = m_signals.find(signo); 137314564Sdim if (pos == m_signals.end()) 138314564Sdim return nullptr; 139314564Sdim else 140314564Sdim return pos->second.m_name.GetCString(); 141254721Semaste} 142254721Semaste 143314564Sdimbool UnixSignals::SignalIsValid(int32_t signo) const { 144314564Sdim return m_signals.find(signo) != m_signals.end(); 145254721Semaste} 146254721Semaste 147314564SdimConstString UnixSignals::GetShortName(ConstString name) const { 148314564Sdim if (name) { 149314564Sdim const char *signame = name.AsCString(); 150314564Sdim return ConstString(signame + 3); // Remove "SIG" from name 151314564Sdim } 152314564Sdim return name; 153296417Sdim} 154254721Semaste 155314564Sdimint32_t UnixSignals::GetSignalNumberFromName(const char *name) const { 156314564Sdim ConstString const_name(name); 157254721Semaste 158314564Sdim collection::const_iterator pos, end = m_signals.end(); 159314564Sdim for (pos = m_signals.begin(); pos != end; pos++) { 160314564Sdim if ((const_name == pos->second.m_name) || 161314564Sdim (const_name == pos->second.m_alias) || 162314564Sdim (const_name == GetShortName(pos->second.m_name)) || 163314564Sdim (const_name == GetShortName(pos->second.m_alias))) 164314564Sdim return pos->first; 165314564Sdim } 166314564Sdim 167314564Sdim const int32_t signo = 168314564Sdim StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0); 169314564Sdim if (signo != LLDB_INVALID_SIGNAL_NUMBER) 170314564Sdim return signo; 171314564Sdim return LLDB_INVALID_SIGNAL_NUMBER; 172254721Semaste} 173254721Semaste 174314564Sdimint32_t UnixSignals::GetFirstSignalNumber() const { 175314564Sdim if (m_signals.empty()) 176314564Sdim return LLDB_INVALID_SIGNAL_NUMBER; 177254721Semaste 178314564Sdim return (*m_signals.begin()).first; 179254721Semaste} 180254721Semaste 181314564Sdimint32_t UnixSignals::GetNextSignalNumber(int32_t current_signal) const { 182314564Sdim collection::const_iterator pos = m_signals.find(current_signal); 183314564Sdim collection::const_iterator end = m_signals.end(); 184314564Sdim if (pos == end) 185314564Sdim return LLDB_INVALID_SIGNAL_NUMBER; 186314564Sdim else { 187314564Sdim pos++; 188254721Semaste if (pos == end) 189314564Sdim return LLDB_INVALID_SIGNAL_NUMBER; 190254721Semaste else 191314564Sdim return pos->first; 192314564Sdim } 193254721Semaste} 194254721Semaste 195314564Sdimconst char *UnixSignals::GetSignalInfo(int32_t signo, bool &should_suppress, 196314564Sdim bool &should_stop, 197314564Sdim bool &should_notify) const { 198314564Sdim collection::const_iterator pos = m_signals.find(signo); 199314564Sdim if (pos == m_signals.end()) 200314564Sdim return nullptr; 201314564Sdim else { 202314564Sdim const Signal &signal = pos->second; 203314564Sdim should_suppress = signal.m_suppress; 204314564Sdim should_stop = signal.m_stop; 205314564Sdim should_notify = signal.m_notify; 206314564Sdim return signal.m_name.AsCString(""); 207314564Sdim } 208254721Semaste} 209254721Semaste 210314564Sdimbool UnixSignals::GetShouldSuppress(int signo) const { 211314564Sdim collection::const_iterator pos = m_signals.find(signo); 212314564Sdim if (pos != m_signals.end()) 213314564Sdim return pos->second.m_suppress; 214314564Sdim return false; 215254721Semaste} 216254721Semaste 217314564Sdimbool UnixSignals::SetShouldSuppress(int signo, bool value) { 218314564Sdim collection::iterator pos = m_signals.find(signo); 219314564Sdim if (pos != m_signals.end()) { 220314564Sdim pos->second.m_suppress = value; 221321369Sdim ++m_version; 222314564Sdim return true; 223314564Sdim } 224314564Sdim return false; 225254721Semaste} 226254721Semaste 227314564Sdimbool UnixSignals::SetShouldSuppress(const char *signal_name, bool value) { 228314564Sdim const int32_t signo = GetSignalNumberFromName(signal_name); 229314564Sdim if (signo != LLDB_INVALID_SIGNAL_NUMBER) 230314564Sdim return SetShouldSuppress(signo, value); 231314564Sdim return false; 232254721Semaste} 233254721Semaste 234314564Sdimbool UnixSignals::GetShouldStop(int signo) const { 235314564Sdim collection::const_iterator pos = m_signals.find(signo); 236314564Sdim if (pos != m_signals.end()) 237314564Sdim return pos->second.m_stop; 238314564Sdim return false; 239254721Semaste} 240254721Semaste 241314564Sdimbool UnixSignals::SetShouldStop(int signo, bool value) { 242314564Sdim collection::iterator pos = m_signals.find(signo); 243314564Sdim if (pos != m_signals.end()) { 244314564Sdim pos->second.m_stop = value; 245321369Sdim ++m_version; 246314564Sdim return true; 247314564Sdim } 248314564Sdim return false; 249254721Semaste} 250254721Semaste 251314564Sdimbool UnixSignals::SetShouldStop(const char *signal_name, bool value) { 252314564Sdim const int32_t signo = GetSignalNumberFromName(signal_name); 253314564Sdim if (signo != LLDB_INVALID_SIGNAL_NUMBER) 254314564Sdim return SetShouldStop(signo, value); 255314564Sdim return false; 256254721Semaste} 257254721Semaste 258314564Sdimbool UnixSignals::GetShouldNotify(int signo) const { 259314564Sdim collection::const_iterator pos = m_signals.find(signo); 260314564Sdim if (pos != m_signals.end()) 261314564Sdim return pos->second.m_notify; 262314564Sdim return false; 263254721Semaste} 264254721Semaste 265314564Sdimbool UnixSignals::SetShouldNotify(int signo, bool value) { 266314564Sdim collection::iterator pos = m_signals.find(signo); 267314564Sdim if (pos != m_signals.end()) { 268314564Sdim pos->second.m_notify = value; 269321369Sdim ++m_version; 270314564Sdim return true; 271314564Sdim } 272314564Sdim return false; 273254721Semaste} 274254721Semaste 275314564Sdimbool UnixSignals::SetShouldNotify(const char *signal_name, bool value) { 276314564Sdim const int32_t signo = GetSignalNumberFromName(signal_name); 277314564Sdim if (signo != LLDB_INVALID_SIGNAL_NUMBER) 278314564Sdim return SetShouldNotify(signo, value); 279314564Sdim return false; 280254721Semaste} 281288943Sdim 282314564Sdimint32_t UnixSignals::GetNumSignals() const { return m_signals.size(); } 283288943Sdim 284314564Sdimint32_t UnixSignals::GetSignalAtIndex(int32_t index) const { 285314564Sdim if (index < 0 || m_signals.size() <= static_cast<size_t>(index)) 286314564Sdim return LLDB_INVALID_SIGNAL_NUMBER; 287314564Sdim auto it = m_signals.begin(); 288314564Sdim std::advance(it, index); 289314564Sdim return it->first; 290288943Sdim} 291321369Sdim 292321369Sdimuint64_t UnixSignals::GetVersion() const { return m_version; } 293321369Sdim 294321369Sdimstd::vector<int32_t> 295321369SdimUnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress, 296321369Sdim llvm::Optional<bool> should_stop, 297321369Sdim llvm::Optional<bool> should_notify) { 298321369Sdim std::vector<int32_t> result; 299321369Sdim for (int32_t signo = GetFirstSignalNumber(); 300321369Sdim signo != LLDB_INVALID_SIGNAL_NUMBER; 301321369Sdim signo = GetNextSignalNumber(signo)) { 302321369Sdim 303321369Sdim bool signal_suppress = false; 304321369Sdim bool signal_stop = false; 305321369Sdim bool signal_notify = false; 306321369Sdim GetSignalInfo(signo, signal_suppress, signal_stop, signal_notify); 307321369Sdim 308341825Sdim // If any of filtering conditions are not met, we move on to the next 309341825Sdim // signal. 310321369Sdim if (should_suppress.hasValue() && 311321369Sdim signal_suppress != should_suppress.getValue()) 312321369Sdim continue; 313321369Sdim 314321369Sdim if (should_stop.hasValue() && signal_stop != should_stop.getValue()) 315321369Sdim continue; 316321369Sdim 317321369Sdim if (should_notify.hasValue() && signal_notify != should_notify.getValue()) 318321369Sdim continue; 319321369Sdim 320321369Sdim result.push_back(signo); 321321369Sdim } 322321369Sdim 323321369Sdim return result; 324321369Sdim} 325