1ac7ddfbfSEd Maste //===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
104bb0738eSEd Maste #include "lldb/Target/UnixSignals.h"
11b91a7dfcSDimitry Andric #include "Plugins/Process/Utility/FreeBSDSignals.h"
12b91a7dfcSDimitry Andric #include "Plugins/Process/Utility/LinuxSignals.h"
13b91a7dfcSDimitry Andric #include "Plugins/Process/Utility/MipsLinuxSignals.h"
149f2f44ceSEd Maste #include "Plugins/Process/Utility/NetBSDSignals.h"
15435933ddSDimitry Andric #include "lldb/Host/StringConvert.h"
16acac075bSDimitry Andric #include "lldb/Utility/ArchSpec.h"
17b91a7dfcSDimitry Andric
18ac7ddfbfSEd Maste using namespace lldb_private;
19ac7ddfbfSEd Maste
Signal(const char * name,bool default_suppress,bool default_stop,bool default_notify,const char * description,const char * alias)20435933ddSDimitry Andric UnixSignals::Signal::Signal(const char *name, bool default_suppress,
21435933ddSDimitry Andric bool default_stop, bool default_notify,
22435933ddSDimitry Andric const char *description, const char *alias)
23435933ddSDimitry Andric : m_name(name), m_alias(alias), m_description(),
24435933ddSDimitry Andric m_suppress(default_suppress), m_stop(default_stop),
25435933ddSDimitry Andric m_notify(default_notify) {
26ac7ddfbfSEd Maste if (description)
27ac7ddfbfSEd Maste m_description.assign(description);
28ac7ddfbfSEd Maste }
29ac7ddfbfSEd Maste
Create(const ArchSpec & arch)30435933ddSDimitry Andric lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) {
31b91a7dfcSDimitry Andric const auto &triple = arch.GetTriple();
32435933ddSDimitry Andric switch (triple.getOS()) {
33435933ddSDimitry Andric case llvm::Triple::Linux: {
34435933ddSDimitry Andric switch (triple.getArch()) {
35b91a7dfcSDimitry Andric case llvm::Triple::mips:
36b91a7dfcSDimitry Andric case llvm::Triple::mipsel:
37b91a7dfcSDimitry Andric case llvm::Triple::mips64:
38b91a7dfcSDimitry Andric case llvm::Triple::mips64el:
39b91a7dfcSDimitry Andric return std::make_shared<MipsLinuxSignals>();
40b91a7dfcSDimitry Andric default:
41b91a7dfcSDimitry Andric return std::make_shared<LinuxSignals>();
42b91a7dfcSDimitry Andric }
43b91a7dfcSDimitry Andric }
44b91a7dfcSDimitry Andric case llvm::Triple::FreeBSD:
45b91a7dfcSDimitry Andric case llvm::Triple::OpenBSD:
46b91a7dfcSDimitry Andric return std::make_shared<FreeBSDSignals>();
479f2f44ceSEd Maste case llvm::Triple::NetBSD:
489f2f44ceSEd Maste return std::make_shared<NetBSDSignals>();
49b91a7dfcSDimitry Andric default:
50b91a7dfcSDimitry Andric return std::make_shared<UnixSignals>();
51b91a7dfcSDimitry Andric }
52b91a7dfcSDimitry Andric }
53b91a7dfcSDimitry Andric
54ac7ddfbfSEd Maste //----------------------------------------------------------------------
55ac7ddfbfSEd Maste // UnixSignals constructor
56ac7ddfbfSEd Maste //----------------------------------------------------------------------
UnixSignals()57435933ddSDimitry Andric UnixSignals::UnixSignals() { Reset(); }
58ac7ddfbfSEd Maste
UnixSignals(const UnixSignals & rhs)59435933ddSDimitry Andric UnixSignals::UnixSignals(const UnixSignals &rhs) : m_signals(rhs.m_signals) {}
60b91a7dfcSDimitry Andric
614bb0738eSEd Maste UnixSignals::~UnixSignals() = default;
62ac7ddfbfSEd Maste
Reset()63435933ddSDimitry Andric void UnixSignals::Reset() {
64435933ddSDimitry Andric // This builds one standard set of Unix Signals. If yours aren't quite in
654ba319b5SDimitry Andric // this order, you can either subclass this class, and use Add & Remove to
664ba319b5SDimitry Andric // change them
67ac7ddfbfSEd Maste // or you can subclass and build them afresh in your constructor;
68435933ddSDimitry Andric //
69435933ddSDimitry Andric // Note: the signals below are the Darwin signals. Do not change these!
70ac7ddfbfSEd Maste m_signals.clear();
719f2f44ceSEd Maste // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
72435933ddSDimitry Andric // ====== ============ ======== ====== ======
73435933ddSDimitry Andric // ===================================================
749f2f44ceSEd Maste AddSignal(1, "SIGHUP", false, true, true, "hangup");
759f2f44ceSEd Maste AddSignal(2, "SIGINT", true, true, true, "interrupt");
769f2f44ceSEd Maste AddSignal(3, "SIGQUIT", false, true, true, "quit");
779f2f44ceSEd Maste AddSignal(4, "SIGILL", false, true, true, "illegal instruction");
78435933ddSDimitry Andric AddSignal(5, "SIGTRAP", true, true, true,
79435933ddSDimitry Andric "trace trap (not reset when caught)");
809f2f44ceSEd Maste AddSignal(6, "SIGABRT", false, true, true, "abort()");
819f2f44ceSEd Maste AddSignal(7, "SIGEMT", false, true, true, "pollable event");
829f2f44ceSEd Maste AddSignal(8, "SIGFPE", false, true, true, "floating point exception");
839f2f44ceSEd Maste AddSignal(9, "SIGKILL", false, true, true, "kill");
849f2f44ceSEd Maste AddSignal(10, "SIGBUS", false, true, true, "bus error");
859f2f44ceSEd Maste AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation");
869f2f44ceSEd Maste AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call");
87*b5893f02SDimitry Andric AddSignal(13, "SIGPIPE", false, false, false,
88435933ddSDimitry Andric "write on a pipe with no one to read it");
899f2f44ceSEd Maste AddSignal(14, "SIGALRM", false, false, false, "alarm clock");
90435933ddSDimitry Andric AddSignal(15, "SIGTERM", false, true, true,
91435933ddSDimitry Andric "software termination signal from kill");
92435933ddSDimitry Andric AddSignal(16, "SIGURG", false, false, false,
93435933ddSDimitry Andric "urgent condition on IO channel");
94435933ddSDimitry Andric AddSignal(17, "SIGSTOP", true, true, true,
95435933ddSDimitry Andric "sendable stop signal not from tty");
969f2f44ceSEd Maste AddSignal(18, "SIGTSTP", false, true, true, "stop signal from tty");
979f2f44ceSEd Maste AddSignal(19, "SIGCONT", false, true, true, "continue a stopped process");
98435933ddSDimitry Andric AddSignal(20, "SIGCHLD", false, false, false,
99435933ddSDimitry Andric "to parent on child stop or exit");
100435933ddSDimitry Andric AddSignal(21, "SIGTTIN", false, true, true,
101435933ddSDimitry Andric "to readers process group upon background tty read");
102435933ddSDimitry Andric AddSignal(22, "SIGTTOU", false, true, true,
103435933ddSDimitry Andric "to readers process group upon background tty write");
1049f2f44ceSEd Maste AddSignal(23, "SIGIO", false, false, false, "input/output possible signal");
1059f2f44ceSEd Maste AddSignal(24, "SIGXCPU", false, true, true, "exceeded CPU time limit");
1069f2f44ceSEd Maste AddSignal(25, "SIGXFSZ", false, true, true, "exceeded file size limit");
1079f2f44ceSEd Maste AddSignal(26, "SIGVTALRM", false, false, false, "virtual time alarm");
1089f2f44ceSEd Maste AddSignal(27, "SIGPROF", false, false, false, "profiling time alarm");
1099f2f44ceSEd Maste AddSignal(28, "SIGWINCH", false, false, false, "window size changes");
1109f2f44ceSEd Maste AddSignal(29, "SIGINFO", false, true, true, "information request");
1119f2f44ceSEd Maste AddSignal(30, "SIGUSR1", false, true, true, "user defined signal 1");
1129f2f44ceSEd Maste AddSignal(31, "SIGUSR2", false, true, true, "user defined signal 2");
113ac7ddfbfSEd Maste }
114ac7ddfbfSEd Maste
AddSignal(int signo,const char * name,bool default_suppress,bool default_stop,bool default_notify,const char * description,const char * alias)115435933ddSDimitry Andric void UnixSignals::AddSignal(int signo, const char *name, bool default_suppress,
116435933ddSDimitry Andric bool default_stop, bool default_notify,
117435933ddSDimitry Andric const char *description, const char *alias) {
118435933ddSDimitry Andric Signal new_signal(name, default_suppress, default_stop, default_notify,
119435933ddSDimitry Andric description, alias);
120ac7ddfbfSEd Maste m_signals.insert(std::make_pair(signo, new_signal));
121f678e45dSDimitry Andric ++m_version;
122ac7ddfbfSEd Maste }
123ac7ddfbfSEd Maste
RemoveSignal(int signo)124435933ddSDimitry Andric void UnixSignals::RemoveSignal(int signo) {
125ac7ddfbfSEd Maste collection::iterator pos = m_signals.find(signo);
126ac7ddfbfSEd Maste if (pos != m_signals.end())
127ac7ddfbfSEd Maste m_signals.erase(pos);
128f678e45dSDimitry Andric ++m_version;
129ac7ddfbfSEd Maste }
130ac7ddfbfSEd Maste
GetSignalAsCString(int signo) const131435933ddSDimitry Andric const char *UnixSignals::GetSignalAsCString(int signo) const {
132ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(signo);
133ac7ddfbfSEd Maste if (pos == m_signals.end())
1344bb0738eSEd Maste return nullptr;
135ac7ddfbfSEd Maste else
136ac7ddfbfSEd Maste return pos->second.m_name.GetCString();
137ac7ddfbfSEd Maste }
138ac7ddfbfSEd Maste
SignalIsValid(int32_t signo) const139435933ddSDimitry Andric bool UnixSignals::SignalIsValid(int32_t signo) const {
140ac7ddfbfSEd Maste return m_signals.find(signo) != m_signals.end();
141ac7ddfbfSEd Maste }
142ac7ddfbfSEd Maste
GetShortName(ConstString name) const143435933ddSDimitry Andric ConstString UnixSignals::GetShortName(ConstString name) const {
144435933ddSDimitry Andric if (name) {
1454bb0738eSEd Maste const char *signame = name.AsCString();
1469f2f44ceSEd Maste return ConstString(signame + 3); // Remove "SIG" from name
1479f2f44ceSEd Maste }
1489f2f44ceSEd Maste return name;
1499f2f44ceSEd Maste }
150ac7ddfbfSEd Maste
GetSignalNumberFromName(const char * name) const151435933ddSDimitry Andric int32_t UnixSignals::GetSignalNumberFromName(const char *name) const {
152ac7ddfbfSEd Maste ConstString const_name(name);
153ac7ddfbfSEd Maste
154ac7ddfbfSEd Maste collection::const_iterator pos, end = m_signals.end();
155435933ddSDimitry Andric for (pos = m_signals.begin(); pos != end; pos++) {
156435933ddSDimitry Andric if ((const_name == pos->second.m_name) ||
157435933ddSDimitry Andric (const_name == pos->second.m_alias) ||
158435933ddSDimitry Andric (const_name == GetShortName(pos->second.m_name)) ||
159435933ddSDimitry Andric (const_name == GetShortName(pos->second.m_alias)))
160ac7ddfbfSEd Maste return pos->first;
161ac7ddfbfSEd Maste }
162ac7ddfbfSEd Maste
163435933ddSDimitry Andric const int32_t signo =
164435933ddSDimitry Andric StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
165ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
166ac7ddfbfSEd Maste return signo;
167ac7ddfbfSEd Maste return LLDB_INVALID_SIGNAL_NUMBER;
168ac7ddfbfSEd Maste }
169ac7ddfbfSEd Maste
GetFirstSignalNumber() const170435933ddSDimitry Andric int32_t UnixSignals::GetFirstSignalNumber() const {
171ac7ddfbfSEd Maste if (m_signals.empty())
172ac7ddfbfSEd Maste return LLDB_INVALID_SIGNAL_NUMBER;
173ac7ddfbfSEd Maste
174ac7ddfbfSEd Maste return (*m_signals.begin()).first;
175ac7ddfbfSEd Maste }
176ac7ddfbfSEd Maste
GetNextSignalNumber(int32_t current_signal) const177435933ddSDimitry Andric int32_t UnixSignals::GetNextSignalNumber(int32_t current_signal) const {
178ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(current_signal);
179ac7ddfbfSEd Maste collection::const_iterator end = m_signals.end();
180ac7ddfbfSEd Maste if (pos == end)
181ac7ddfbfSEd Maste return LLDB_INVALID_SIGNAL_NUMBER;
182435933ddSDimitry Andric else {
183ac7ddfbfSEd Maste pos++;
184ac7ddfbfSEd Maste if (pos == end)
185ac7ddfbfSEd Maste return LLDB_INVALID_SIGNAL_NUMBER;
186ac7ddfbfSEd Maste else
187ac7ddfbfSEd Maste return pos->first;
188ac7ddfbfSEd Maste }
189ac7ddfbfSEd Maste }
190ac7ddfbfSEd Maste
GetSignalInfo(int32_t signo,bool & should_suppress,bool & should_stop,bool & should_notify) const191435933ddSDimitry Andric const char *UnixSignals::GetSignalInfo(int32_t signo, bool &should_suppress,
192ac7ddfbfSEd Maste bool &should_stop,
193435933ddSDimitry Andric bool &should_notify) const {
194ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(signo);
195ac7ddfbfSEd Maste if (pos == m_signals.end())
1964bb0738eSEd Maste return nullptr;
197435933ddSDimitry Andric else {
198ac7ddfbfSEd Maste const Signal &signal = pos->second;
199ac7ddfbfSEd Maste should_suppress = signal.m_suppress;
200ac7ddfbfSEd Maste should_stop = signal.m_stop;
201ac7ddfbfSEd Maste should_notify = signal.m_notify;
202ac7ddfbfSEd Maste return signal.m_name.AsCString("");
203ac7ddfbfSEd Maste }
204ac7ddfbfSEd Maste }
205ac7ddfbfSEd Maste
GetShouldSuppress(int signo) const206435933ddSDimitry Andric bool UnixSignals::GetShouldSuppress(int signo) const {
207ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(signo);
208ac7ddfbfSEd Maste if (pos != m_signals.end())
209ac7ddfbfSEd Maste return pos->second.m_suppress;
210ac7ddfbfSEd Maste return false;
211ac7ddfbfSEd Maste }
212ac7ddfbfSEd Maste
SetShouldSuppress(int signo,bool value)213435933ddSDimitry Andric bool UnixSignals::SetShouldSuppress(int signo, bool value) {
214ac7ddfbfSEd Maste collection::iterator pos = m_signals.find(signo);
215435933ddSDimitry Andric if (pos != m_signals.end()) {
216ac7ddfbfSEd Maste pos->second.m_suppress = value;
217f678e45dSDimitry Andric ++m_version;
218ac7ddfbfSEd Maste return true;
219ac7ddfbfSEd Maste }
220ac7ddfbfSEd Maste return false;
221ac7ddfbfSEd Maste }
222ac7ddfbfSEd Maste
SetShouldSuppress(const char * signal_name,bool value)223435933ddSDimitry Andric bool UnixSignals::SetShouldSuppress(const char *signal_name, bool value) {
224ac7ddfbfSEd Maste const int32_t signo = GetSignalNumberFromName(signal_name);
225ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
226ac7ddfbfSEd Maste return SetShouldSuppress(signo, value);
227ac7ddfbfSEd Maste return false;
228ac7ddfbfSEd Maste }
229ac7ddfbfSEd Maste
GetShouldStop(int signo) const230435933ddSDimitry Andric bool UnixSignals::GetShouldStop(int signo) const {
231ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(signo);
232ac7ddfbfSEd Maste if (pos != m_signals.end())
233ac7ddfbfSEd Maste return pos->second.m_stop;
234ac7ddfbfSEd Maste return false;
235ac7ddfbfSEd Maste }
236ac7ddfbfSEd Maste
SetShouldStop(int signo,bool value)237435933ddSDimitry Andric bool UnixSignals::SetShouldStop(int signo, bool value) {
238ac7ddfbfSEd Maste collection::iterator pos = m_signals.find(signo);
239435933ddSDimitry Andric if (pos != m_signals.end()) {
240ac7ddfbfSEd Maste pos->second.m_stop = value;
241f678e45dSDimitry Andric ++m_version;
242ac7ddfbfSEd Maste return true;
243ac7ddfbfSEd Maste }
244ac7ddfbfSEd Maste return false;
245ac7ddfbfSEd Maste }
246ac7ddfbfSEd Maste
SetShouldStop(const char * signal_name,bool value)247435933ddSDimitry Andric bool UnixSignals::SetShouldStop(const char *signal_name, bool value) {
248ac7ddfbfSEd Maste const int32_t signo = GetSignalNumberFromName(signal_name);
249ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
250ac7ddfbfSEd Maste return SetShouldStop(signo, value);
251ac7ddfbfSEd Maste return false;
252ac7ddfbfSEd Maste }
253ac7ddfbfSEd Maste
GetShouldNotify(int signo) const254435933ddSDimitry Andric bool UnixSignals::GetShouldNotify(int signo) const {
255ac7ddfbfSEd Maste collection::const_iterator pos = m_signals.find(signo);
256ac7ddfbfSEd Maste if (pos != m_signals.end())
257ac7ddfbfSEd Maste return pos->second.m_notify;
258ac7ddfbfSEd Maste return false;
259ac7ddfbfSEd Maste }
260ac7ddfbfSEd Maste
SetShouldNotify(int signo,bool value)261435933ddSDimitry Andric bool UnixSignals::SetShouldNotify(int signo, bool value) {
262ac7ddfbfSEd Maste collection::iterator pos = m_signals.find(signo);
263435933ddSDimitry Andric if (pos != m_signals.end()) {
264ac7ddfbfSEd Maste pos->second.m_notify = value;
265f678e45dSDimitry Andric ++m_version;
266ac7ddfbfSEd Maste return true;
267ac7ddfbfSEd Maste }
268ac7ddfbfSEd Maste return false;
269ac7ddfbfSEd Maste }
270ac7ddfbfSEd Maste
SetShouldNotify(const char * signal_name,bool value)271435933ddSDimitry Andric bool UnixSignals::SetShouldNotify(const char *signal_name, bool value) {
272ac7ddfbfSEd Maste const int32_t signo = GetSignalNumberFromName(signal_name);
273ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
274ac7ddfbfSEd Maste return SetShouldNotify(signo, value);
275ac7ddfbfSEd Maste return false;
276ac7ddfbfSEd Maste }
277b91a7dfcSDimitry Andric
GetNumSignals() const278435933ddSDimitry Andric int32_t UnixSignals::GetNumSignals() const { return m_signals.size(); }
279b91a7dfcSDimitry Andric
GetSignalAtIndex(int32_t index) const280435933ddSDimitry Andric int32_t UnixSignals::GetSignalAtIndex(int32_t index) const {
281b91a7dfcSDimitry Andric if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
282b91a7dfcSDimitry Andric return LLDB_INVALID_SIGNAL_NUMBER;
283b91a7dfcSDimitry Andric auto it = m_signals.begin();
284b91a7dfcSDimitry Andric std::advance(it, index);
285b91a7dfcSDimitry Andric return it->first;
286b91a7dfcSDimitry Andric }
287f678e45dSDimitry Andric
GetVersion() const288f678e45dSDimitry Andric uint64_t UnixSignals::GetVersion() const { return m_version; }
289f678e45dSDimitry Andric
290f678e45dSDimitry Andric std::vector<int32_t>
GetFilteredSignals(llvm::Optional<bool> should_suppress,llvm::Optional<bool> should_stop,llvm::Optional<bool> should_notify)291f678e45dSDimitry Andric UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress,
292f678e45dSDimitry Andric llvm::Optional<bool> should_stop,
293f678e45dSDimitry Andric llvm::Optional<bool> should_notify) {
294f678e45dSDimitry Andric std::vector<int32_t> result;
295f678e45dSDimitry Andric for (int32_t signo = GetFirstSignalNumber();
296f678e45dSDimitry Andric signo != LLDB_INVALID_SIGNAL_NUMBER;
297f678e45dSDimitry Andric signo = GetNextSignalNumber(signo)) {
298f678e45dSDimitry Andric
299f678e45dSDimitry Andric bool signal_suppress = false;
300f678e45dSDimitry Andric bool signal_stop = false;
301f678e45dSDimitry Andric bool signal_notify = false;
302f678e45dSDimitry Andric GetSignalInfo(signo, signal_suppress, signal_stop, signal_notify);
303f678e45dSDimitry Andric
3044ba319b5SDimitry Andric // If any of filtering conditions are not met, we move on to the next
3054ba319b5SDimitry Andric // signal.
306f678e45dSDimitry Andric if (should_suppress.hasValue() &&
307f678e45dSDimitry Andric signal_suppress != should_suppress.getValue())
308f678e45dSDimitry Andric continue;
309f678e45dSDimitry Andric
310f678e45dSDimitry Andric if (should_stop.hasValue() && signal_stop != should_stop.getValue())
311f678e45dSDimitry Andric continue;
312f678e45dSDimitry Andric
313f678e45dSDimitry Andric if (should_notify.hasValue() && signal_notify != should_notify.getValue())
314f678e45dSDimitry Andric continue;
315f678e45dSDimitry Andric
316f678e45dSDimitry Andric result.push_back(signo);
317f678e45dSDimitry Andric }
318f678e45dSDimitry Andric
319f678e45dSDimitry Andric return result;
320f678e45dSDimitry Andric }
321