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 
17 using namespace lldb_private;
18 
19 UnixSignals::Signal::Signal (const char *name, bool default_suppress, bool default_stop, bool default_notify) :
20     m_name (name),
21     m_conditions ()
22 {
23     m_conditions[Signal::eCondSuppress] = default_suppress;
24     m_conditions[Signal::eCondStop]     = default_stop;
25     m_conditions[Signal::eCondNotify]   = default_notify;
26 }
27 
28 //----------------------------------------------------------------------
29 // UnixSignals constructor
30 //----------------------------------------------------------------------
31 UnixSignals::UnixSignals ()
32 {
33     Reset ();
34 }
35 
36 //----------------------------------------------------------------------
37 // Destructor
38 //----------------------------------------------------------------------
39 UnixSignals::~UnixSignals ()
40 {
41 }
42 
43 void
44 UnixSignals::Reset ()
45 {
46     // This builds one standard set of Unix Signals.  If yours aren't quite in this
47     // order, you can either subclass this class, and use Add & Remove to change them
48     // or you can subclass and build them afresh in your constructor;
49     m_signals.clear();
50 
51     AddSignal(1, "SIGHUP",     false, true,  true );    // 1    hangup
52     AddSignal(2, "SIGINT",     true,  true,  true );    // 2    interrupt
53     AddSignal(3, "SIGQUIT",    false, true,  true );    // 3    quit
54     AddSignal(4, "SIGILL",     false, true,  true );    // 4    illegal instruction (not reset when caught)
55     AddSignal(5, "SIGTRAP",    true,  true,  true );    // 5    trace trap (not reset when caught)
56     AddSignal(6, "SIGABRT",    false, true,  true );    // 6    abort()
57     AddSignal(7, "SIGEMT",     false, true,  true );    // 7    pollable event ([XSR] generated, not supported)
58     AddSignal(8, "SIGFPE",     false, true,  true );    // 8    floating point exception
59     AddSignal(9, "SIGKILL",    false, true,  true );    // 9    kill (cannot be caught or ignored)
60     AddSignal(10, "SIGBUS",    false, true,  true );    // 10    bus error
61     AddSignal(11, "SIGSEGV",   false, true,  true );    // 11    segmentation violation
62     AddSignal(12, "SIGSYS",    false, true,  true );    // 12    bad argument to system call
63     AddSignal(13, "SIGPIPE",   false, true,  true );    // 13    write on a pipe with no one to read it
64     AddSignal(14, "SIGALRM",   false, false, true );    // 14    alarm clock
65     AddSignal(15, "SIGTERM",   false, true,  true );    // 15    software termination signal from kill
66     AddSignal(16, "SIGURG",    false, false, false);    // 16    urgent condition on IO channel
67     AddSignal(17, "SIGSTOP",   false, true,  true );    // 17    sendable stop signal not from tty
68     AddSignal(18, "SIGTSTP",   false, true,  true );    // 18    stop signal from tty
69     AddSignal(19, "SIGCONT",   false, true,  true );    // 19    continue a stopped process
70     AddSignal(20, "SIGCHLD",   false, false, true );    // 20    to parent on child stop or exit
71     AddSignal(21, "SIGTTIN",   false, true,  true );    // 21    to readers pgrp upon background tty read
72     AddSignal(22, "SIGTTOU",   false, true,  true );    // 22    like TTIN for output if (tp->t_local&LTOSTOP)
73     AddSignal(23, "SIGIO",     false, false, false);    // 23    input/output possible signal
74     AddSignal(24, "SIGXCPU",   false, true,  true );    // 24    exceeded CPU time limit
75     AddSignal(25, "SIGXFSZ",   false, true,  true );    // 25    exceeded file size limit
76     AddSignal(26, "SIGVTALRM", false, false, false);    // 26    virtual time alarm
77     AddSignal(27, "SIGPROF",   false, false, false);    // 27    profiling time alarm
78     AddSignal(28, "SIGWINCH",  false, false, false);    // 28    window size changes
79     AddSignal(29, "SIGINFO",   false, true,  true );    // 29    information request
80     AddSignal(30, "SIGUSR1",   false, true,  true );    // 30    user defined signal 1
81     AddSignal(31, "SIGUSR2",   false, true,  true );    // 31    user defined signal 2
82 }
83 void
84 UnixSignals::AddSignal (int signo, const char *name, bool default_suppress, bool default_stop, bool default_notify)
85 {
86     collection::iterator iter = m_signals.find (signo);
87     struct Signal new_signal (name, default_suppress, default_stop, default_notify);
88 
89     if (iter != m_signals.end())
90         m_signals.erase (iter);
91 
92     m_signals.insert (iter, collection::value_type (signo, new_signal));
93 }
94 
95 void
96 UnixSignals::RemoveSignal (int signo)
97 {
98     collection::iterator pos = m_signals.find (signo);
99     if (pos != m_signals.end())
100         m_signals.erase (pos);
101 }
102 
103 UnixSignals::Signal *
104 UnixSignals::GetSignalByName (const char *name, int32_t &signo)
105 {
106     ConstString const_name (name);
107 
108     collection::iterator pos, end = m_signals.end ();
109     for (pos = m_signals.begin (); pos != end; pos++)
110     {
111         if (const_name == (*pos).second.m_name)
112         {
113             signo = (*pos).first;
114             return &((*pos).second);
115         }
116     }
117     return NULL;
118 }
119 
120 
121 const UnixSignals::Signal *
122 UnixSignals::GetSignalByName (const char *name, int32_t &signo) const
123 {
124     ConstString const_name (name);
125 
126     collection::const_iterator pos, end = m_signals.end ();
127     for (pos = m_signals.begin (); pos != end; pos++)
128     {
129         if (const_name == (*pos).second.m_name)
130         {
131             signo = (*pos).first;
132             return &((*pos).second);
133         }
134     }
135     return NULL;
136 }
137 
138 const char *
139 UnixSignals::GetSignalAsCString (int signo) const
140 {
141     collection::const_iterator pos = m_signals.find (signo);
142     if (pos == m_signals.end())
143         return NULL;
144     else
145         return (*pos).second.m_name.GetCString ();
146 }
147 
148 
149 bool
150 UnixSignals::SignalIsValid (int32_t signo) const
151 {
152     return m_signals.find (signo) != m_signals.end();
153 }
154 
155 
156 int32_t
157 UnixSignals::GetSignalNumberFromName (const char *name) const
158 {
159     int32_t signo;
160     const Signal *signal = GetSignalByName (name, signo);
161     if (signal == NULL)
162         return LLDB_INVALID_SIGNAL_NUMBER;
163     else
164         return signo;
165 }
166 
167 int32_t
168 UnixSignals::GetFirstSignalNumber () const
169 {
170     if (m_signals.empty())
171         return LLDB_INVALID_SIGNAL_NUMBER;
172 
173     return (*m_signals.begin ()).first;
174 }
175 
176 int32_t
177 UnixSignals::GetNextSignalNumber (int32_t current_signal) const
178 {
179     collection::const_iterator pos = m_signals.find (current_signal);
180     collection::const_iterator end = m_signals.end();
181     if (pos == end)
182         return LLDB_INVALID_SIGNAL_NUMBER;
183     else
184     {
185         pos++;
186         if (pos == end)
187             return LLDB_INVALID_SIGNAL_NUMBER;
188         else
189             return (*pos).first;
190     }
191 }
192 
193 const char *
194 UnixSignals::GetSignalInfo
195 (
196     int32_t signo,
197     bool &should_suppress,
198     bool &should_stop,
199     bool &should_notify
200 ) const
201 {
202     collection::const_iterator pos = m_signals.find (signo);
203     if (pos == m_signals.end())
204         return NULL;
205     else
206     {
207         const Signal &signal = (*pos).second;
208         should_suppress = signal.m_conditions[Signal::eCondSuppress];
209         should_stop     = signal.m_conditions[Signal::eCondStop];
210         should_notify   = signal.m_conditions[Signal::eCondNotify];
211         return signal.m_name.AsCString("");
212     }
213 }
214 
215 bool
216 UnixSignals::GetCondition
217 (
218     int32_t signo,
219     UnixSignals::Signal::Condition cond_pos
220 ) const
221 {
222     collection::const_iterator pos = m_signals.find (signo);
223     if (pos == m_signals.end())
224         return false;
225     else
226         return (*pos).second.m_conditions[cond_pos];
227 }
228 
229 bool
230 UnixSignals::SetCondition (int32_t signo, UnixSignals::Signal::Condition cond_pos, bool value)
231 {
232     collection::iterator pos = m_signals.find (signo);
233     if (pos == m_signals.end())
234         return false;
235     else
236     {
237         bool ret_value = (*pos).second.m_conditions[cond_pos];
238         (*pos).second.m_conditions[cond_pos] = value;
239         return ret_value;
240     }
241 }
242 
243 bool
244 UnixSignals::SetCondition (const char *signal_name, UnixSignals::Signal::Condition cond_pos, bool value)
245 {
246     int32_t signo;
247     Signal *signal = GetSignalByName (signal_name, signo);
248     if (signal == NULL)
249         return false;
250     else
251     {
252         bool ret_value = signal->m_conditions[cond_pos];
253         signal->m_conditions[cond_pos] = value;
254         return ret_value;
255     }
256 }
257 
258 bool
259 UnixSignals::GetShouldSuppress (int signo) const
260 {
261     return GetCondition (signo, Signal::eCondSuppress);
262 }
263 
264 bool
265 UnixSignals::SetShouldSuppress (int signo, bool value)
266 {
267     return SetCondition (signo, Signal::eCondSuppress, value);
268 }
269 
270 bool
271 UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
272 {
273     return SetCondition (signal_name, Signal::eCondSuppress, value);
274 }
275 
276 bool
277 UnixSignals::GetShouldStop (int signo) const
278 {
279     return GetCondition (signo, Signal::eCondStop);
280 }
281 
282 bool
283 UnixSignals::SetShouldStop (int signo, bool value)
284 {
285     return SetCondition (signo, Signal::eCondStop, value);
286 }
287 
288 bool
289 UnixSignals::SetShouldStop (const char *signal_name, bool value)
290 {
291     return SetCondition (signal_name, Signal::eCondStop, value);
292 }
293 
294 bool
295 UnixSignals::GetShouldNotify (int signo) const
296 {
297     return GetCondition (signo, Signal::eCondNotify);
298 }
299 
300 bool
301 UnixSignals::SetShouldNotify (int signo, bool value)
302 {
303     return SetCondition (signo, Signal::eCondNotify, value);
304 }
305 
306 bool
307 UnixSignals::SetShouldNotify (const char *signal_name, bool value)
308 {
309     return SetCondition (signal_name, Signal::eCondNotify, value);
310 }
311