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
18using namespace lldb_private;
19
20UnixSignals::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//----------------------------------------------------------------------
43UnixSignals::UnixSignals ()
44{
45    Reset ();
46}
47
48//----------------------------------------------------------------------
49// Destructor
50//----------------------------------------------------------------------
51UnixSignals::~UnixSignals ()
52{
53}
54
55void
56UnixSignals::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
97void
98UnixSignals::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
113void
114UnixSignals::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
121const char *
122UnixSignals::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
132bool
133UnixSignals::SignalIsValid (int32_t signo) const
134{
135    return m_signals.find (signo) != m_signals.end();
136}
137
138
139int32_t
140UnixSignals::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
157int32_t
158UnixSignals::GetFirstSignalNumber () const
159{
160    if (m_signals.empty())
161        return LLDB_INVALID_SIGNAL_NUMBER;
162
163    return (*m_signals.begin ()).first;
164}
165
166int32_t
167UnixSignals::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
183const char *
184UnixSignals::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
205bool
206UnixSignals::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
214bool
215UnixSignals::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
226bool
227UnixSignals::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
235bool
236UnixSignals::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
244bool
245UnixSignals::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
256bool
257UnixSignals::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
265bool
266UnixSignals::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
274bool
275UnixSignals::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
286bool
287UnixSignals::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