1 //===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/UnixSignals.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Interpreter/Args.h"
17 
18 using namespace lldb_private;
19 
Signal(const char * name,const char * short_name,bool default_suppress,bool default_stop,bool default_notify,const char * description)20 UnixSignals::Signal::Signal
21 (
22     const char *name,
23     const char *short_name,
24     bool default_suppress,
25     bool default_stop,
26     bool default_notify,
27     const char *description
28 ) :
29     m_name (name),
30     m_short_name (short_name),
31     m_description (),
32     m_suppress (default_suppress),
33     m_stop (default_stop),
34     m_notify (default_notify)
35 {
36     if (description)
37         m_description.assign (description);
38 }
39 
40 //----------------------------------------------------------------------
41 // UnixSignals constructor
42 //----------------------------------------------------------------------
UnixSignals()43 UnixSignals::UnixSignals ()
44 {
45     Reset ();
46 }
47 
48 //----------------------------------------------------------------------
49 // Destructor
50 //----------------------------------------------------------------------
~UnixSignals()51 UnixSignals::~UnixSignals ()
52 {
53 }
54 
55 void
Reset()56 UnixSignals::Reset ()
57 {
58     // This builds one standard set of Unix Signals.  If yours aren't quite in this
59     // order, you can either subclass this class, and use Add & Remove to change them
60     // or you can subclass and build them afresh in your constructor;
61     m_signals.clear();
62     //        SIGNO  NAME         SHORT NAME SUPPRESS STOP   NOTIFY DESCRIPTION
63     //        ====== ============ ========== ======== ====== ====== ===================================================
64     AddSignal (1,    "SIGHUP",    "HUP",     false,   true , true , "hangup");
65     AddSignal (2,    "SIGINT",    "INT",     true ,   true , true , "interrupt");
66     AddSignal (3,    "SIGQUIT",   "QUIT",    false,   true , true , "quit");
67     AddSignal (4,    "SIGILL",    "ILL",     false,   true , true , "illegal instruction");
68     AddSignal (5,    "SIGTRAP",   "TRAP",    true ,   true , true , "trace trap (not reset when caught)");
69     AddSignal (6,    "SIGABRT",   "ABRT",    false,   true , true , "abort()");
70     AddSignal (7,    "SIGEMT",    "EMT",     false,   true , true , "pollable event");
71     AddSignal (8,    "SIGFPE",    "FPE",     false,   true , true , "floating point exception");
72     AddSignal (9,    "SIGKILL",   "KILL",    false,   true , true , "kill");
73     AddSignal (10,   "SIGBUS",    "BUS",     false,   true , true , "bus error");
74     AddSignal (11,   "SIGSEGV",   "SEGV",    false,   true , true , "segmentation violation");
75     AddSignal (12,   "SIGSYS",    "SYS",     false,   true , true , "bad argument to system call");
76     AddSignal (13,   "SIGPIPE",   "PIPE",    false,   true , true , "write on a pipe with no one to read it");
77     AddSignal (14,   "SIGALRM",   "ALRM",    false,   false, true , "alarm clock");
78     AddSignal (15,   "SIGTERM",   "TERM",    false,   true , true , "software termination signal from kill");
79     AddSignal (16,   "SIGURG",    "URG",     false,   false, false, "urgent condition on IO channel");
80     AddSignal (17,   "SIGSTOP",   "STOP",    true ,   true , true , "sendable stop signal not from tty");
81     AddSignal (18,   "SIGTSTP",   "TSTP",    false,   true , true , "stop signal from tty");
82     AddSignal (19,   "SIGCONT",   "CONT",    false,   true , true , "continue a stopped process");
83     AddSignal (20,   "SIGCHLD",   "CHLD",    false,   false, true , "to parent on child stop or exit");
84     AddSignal (21,   "SIGTTIN",   "TTIN",    false,   true , true , "to readers process group upon background tty read");
85     AddSignal (22,   "SIGTTOU",   "TTOU",    false,   true , true , "to readers process group upon background tty write");
86     AddSignal (23,   "SIGIO",     "IO",      false,   false, false, "input/output possible signal");
87     AddSignal (24,   "SIGXCPU",   "XCPU",    false,   true , true , "exceeded CPU time limit");
88     AddSignal (25,   "SIGXFSZ",   "XFSZ",    false,   true , true , "exceeded file size limit");
89     AddSignal (26,   "SIGVTALRM", "VTALRM",  false,   false, false, "virtual time alarm");
90     AddSignal (27,   "SIGPROF",   "PROF",    false,   false, false, "profiling time alarm");
91     AddSignal (28,   "SIGWINCH",  "WINCH",   false,   false, false, "window size changes");
92     AddSignal (29,   "SIGINFO",   "INFO",    false,   true , true , "information request");
93     AddSignal (30,   "SIGUSR1",   "USR1",    false,   true , true , "user defined signal 1");
94     AddSignal (31,   "SIGUSR2",   "USR2",    false,   true , true , "user defined signal 2");
95 }
96 
97 void
AddSignal(int signo,const char * name,const char * short_name,bool default_suppress,bool default_stop,bool default_notify,const char * description)98 UnixSignals::AddSignal
99 (
100     int signo,
101     const char *name,
102     const char *short_name,
103     bool default_suppress,
104     bool default_stop,
105     bool default_notify,
106     const char *description
107 )
108 {
109     Signal new_signal (name, short_name, default_suppress, default_stop, default_notify, description);
110     m_signals.insert (std::make_pair(signo, new_signal));
111 }
112 
113 void
RemoveSignal(int signo)114 UnixSignals::RemoveSignal (int signo)
115 {
116     collection::iterator pos = m_signals.find (signo);
117     if (pos != m_signals.end())
118         m_signals.erase (pos);
119 }
120 
121 const char *
GetSignalAsCString(int signo) const122 UnixSignals::GetSignalAsCString (int signo) const
123 {
124     collection::const_iterator pos = m_signals.find (signo);
125     if (pos == m_signals.end())
126         return NULL;
127     else
128         return pos->second.m_name.GetCString ();
129 }
130 
131 
132 bool
SignalIsValid(int32_t signo) const133 UnixSignals::SignalIsValid (int32_t signo) const
134 {
135     return m_signals.find (signo) != m_signals.end();
136 }
137 
138 
139 int32_t
GetSignalNumberFromName(const char * name) const140 UnixSignals::GetSignalNumberFromName (const char *name) const
141 {
142     ConstString const_name (name);
143 
144     collection::const_iterator pos, end = m_signals.end ();
145     for (pos = m_signals.begin (); pos != end; pos++)
146     {
147         if ((const_name == pos->second.m_name) || (const_name == pos->second.m_short_name))
148             return pos->first;
149     }
150 
151     const int32_t signo = Args::StringToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
152     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
153         return signo;
154     return LLDB_INVALID_SIGNAL_NUMBER;
155 }
156 
157 int32_t
GetFirstSignalNumber() const158 UnixSignals::GetFirstSignalNumber () const
159 {
160     if (m_signals.empty())
161         return LLDB_INVALID_SIGNAL_NUMBER;
162 
163     return (*m_signals.begin ()).first;
164 }
165 
166 int32_t
GetNextSignalNumber(int32_t current_signal) const167 UnixSignals::GetNextSignalNumber (int32_t current_signal) const
168 {
169     collection::const_iterator pos = m_signals.find (current_signal);
170     collection::const_iterator end = m_signals.end();
171     if (pos == end)
172         return LLDB_INVALID_SIGNAL_NUMBER;
173     else
174     {
175         pos++;
176         if (pos == end)
177             return LLDB_INVALID_SIGNAL_NUMBER;
178         else
179             return pos->first;
180     }
181 }
182 
183 const char *
GetSignalInfo(int32_t signo,bool & should_suppress,bool & should_stop,bool & should_notify) const184 UnixSignals::GetSignalInfo
185 (
186     int32_t signo,
187     bool &should_suppress,
188     bool &should_stop,
189     bool &should_notify
190 ) const
191 {
192     collection::const_iterator pos = m_signals.find (signo);
193     if (pos == m_signals.end())
194         return NULL;
195     else
196     {
197         const Signal &signal = pos->second;
198         should_suppress = signal.m_suppress;
199         should_stop     = signal.m_stop;
200         should_notify   = signal.m_notify;
201         return signal.m_name.AsCString("");
202     }
203 }
204 
205 bool
GetShouldSuppress(int signo) const206 UnixSignals::GetShouldSuppress (int signo) const
207 {
208     collection::const_iterator pos = m_signals.find (signo);
209     if (pos != m_signals.end())
210         return pos->second.m_suppress;
211     return false;
212 }
213 
214 bool
SetShouldSuppress(int signo,bool value)215 UnixSignals::SetShouldSuppress (int signo, bool value)
216 {
217     collection::iterator pos = m_signals.find (signo);
218     if (pos != m_signals.end())
219     {
220         pos->second.m_suppress = value;
221         return true;
222     }
223     return false;
224 }
225 
226 bool
SetShouldSuppress(const char * signal_name,bool value)227 UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
228 {
229     const int32_t signo = GetSignalNumberFromName (signal_name);
230     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
231         return SetShouldSuppress (signo, value);
232     return false;
233 }
234 
235 bool
GetShouldStop(int signo) const236 UnixSignals::GetShouldStop (int signo) const
237 {
238     collection::const_iterator pos = m_signals.find (signo);
239     if (pos != m_signals.end())
240         return pos->second.m_stop;
241     return false;
242 }
243 
244 bool
SetShouldStop(int signo,bool value)245 UnixSignals::SetShouldStop (int signo, bool value)
246 {
247     collection::iterator pos = m_signals.find (signo);
248     if (pos != m_signals.end())
249     {
250         pos->second.m_stop = value;
251         return true;
252     }
253     return false;
254 }
255 
256 bool
SetShouldStop(const char * signal_name,bool value)257 UnixSignals::SetShouldStop (const char *signal_name, bool value)
258 {
259     const int32_t signo = GetSignalNumberFromName (signal_name);
260     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
261         return SetShouldStop (signo, value);
262     return false;
263 }
264 
265 bool
GetShouldNotify(int signo) const266 UnixSignals::GetShouldNotify (int signo) const
267 {
268     collection::const_iterator pos = m_signals.find (signo);
269     if (pos != m_signals.end())
270         return pos->second.m_notify;
271     return false;
272 }
273 
274 bool
SetShouldNotify(int signo,bool value)275 UnixSignals::SetShouldNotify (int signo, bool value)
276 {
277     collection::iterator pos = m_signals.find (signo);
278     if (pos != m_signals.end())
279     {
280         pos->second.m_notify = value;
281         return true;
282     }
283     return false;
284 }
285 
286 bool
SetShouldNotify(const char * signal_name,bool value)287 UnixSignals::SetShouldNotify (const char *signal_name, bool value)
288 {
289     const int32_t signo = GetSignalNumberFromName (signal_name);
290     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
291         return SetShouldNotify (signo, value);
292     return false;
293 }
294