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/Core/ArchSpec.h"
17 #include "lldb/Host/StringConvert.h"
18 
19 #include "Plugins/Process/Utility/FreeBSDSignals.h"
20 #include "Plugins/Process/Utility/LinuxSignals.h"
21 #include "Plugins/Process/Utility/MipsLinuxSignals.h"
22 #include "Plugins/Process/Utility/NetBSDSignals.h"
23 
24 using namespace lldb_private;
25 
26 UnixSignals::Signal::Signal
27 (
28     const char *name,
29     bool default_suppress,
30     bool default_stop,
31     bool default_notify,
32     const char *description,
33     const char *alias
34 ) :
35     m_name (name),
36     m_alias (alias),
37     m_description (),
38     m_suppress (default_suppress),
39     m_stop (default_stop),
40     m_notify (default_notify)
41 {
42     if (description)
43         m_description.assign (description);
44 }
45 
46 lldb::UnixSignalsSP
47 UnixSignals::Create(const ArchSpec &arch)
48 {
49     const auto &triple = arch.GetTriple();
50     switch (triple.getOS())
51     {
52         case llvm::Triple::Linux:
53         {
54             switch (triple.getArch())
55             {
56                 case llvm::Triple::mips:
57                 case llvm::Triple::mipsel:
58                 case llvm::Triple::mips64:
59                 case llvm::Triple::mips64el:
60                     return std::make_shared<MipsLinuxSignals>();
61                 default:
62                     return std::make_shared<LinuxSignals>();
63             }
64         }
65         case llvm::Triple::FreeBSD:
66         case llvm::Triple::OpenBSD:
67             return std::make_shared<FreeBSDSignals>();
68         case llvm::Triple::NetBSD:
69             return std::make_shared<NetBSDSignals>();
70         default:
71             return std::make_shared<UnixSignals>();
72     }
73 }
74 
75 //----------------------------------------------------------------------
76 // UnixSignals constructor
77 //----------------------------------------------------------------------
78 UnixSignals::UnixSignals ()
79 {
80     Reset ();
81 }
82 
83 UnixSignals::UnixSignals(const UnixSignals &rhs)
84     : m_signals(rhs.m_signals)
85 {
86 }
87 
88 //----------------------------------------------------------------------
89 // Destructor
90 //----------------------------------------------------------------------
91 UnixSignals::~UnixSignals ()
92 {
93 }
94 
95 void
96 UnixSignals::Reset ()
97 {
98     // This builds one standard set of Unix Signals.  If yours aren't quite in this
99     // order, you can either subclass this class, and use Add & Remove to change them
100     // or you can subclass and build them afresh in your constructor;
101     m_signals.clear();
102     //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION
103     //        ====== ============  ======== ====== ====== ===================================================
104     AddSignal (1,    "SIGHUP",     false,   true , true , "hangup");
105     AddSignal (2,    "SIGINT",     true ,   true , true , "interrupt");
106     AddSignal (3,    "SIGQUIT",    false,   true , true , "quit");
107     AddSignal (4,    "SIGILL",     false,   true , true , "illegal instruction");
108     AddSignal (5,    "SIGTRAP",    true ,   true , true , "trace trap (not reset when caught)");
109     AddSignal (6,    "SIGABRT",    false,   true , true , "abort()");
110     AddSignal (7,    "SIGEMT",     false,   true , true , "pollable event");
111     AddSignal (8,    "SIGFPE",     false,   true , true , "floating point exception");
112     AddSignal (9,    "SIGKILL",    false,   true , true , "kill");
113     AddSignal (10,   "SIGBUS",     false,   true , true , "bus error");
114     AddSignal (11,   "SIGSEGV",    false,   true , true , "segmentation violation");
115     AddSignal (12,   "SIGSYS",     false,   true , true , "bad argument to system call");
116     AddSignal (13,   "SIGPIPE",    false,   true , true , "write on a pipe with no one to read it");
117     AddSignal (14,   "SIGALRM",    false,   false, false, "alarm clock");
118     AddSignal (15,   "SIGTERM",    false,   true , true , "software termination signal from kill");
119     AddSignal (16,   "SIGURG",     false,   false, false, "urgent condition on IO channel");
120     AddSignal (17,   "SIGSTOP",    true ,   true , true , "sendable stop signal not from tty");
121     AddSignal (18,   "SIGTSTP",    false,   true , true , "stop signal from tty");
122     AddSignal (19,   "SIGCONT",    false,   true , true , "continue a stopped process");
123     AddSignal (20,   "SIGCHLD",    false,   false, false, "to parent on child stop or exit");
124     AddSignal (21,   "SIGTTIN",    false,   true , true , "to readers process group upon background tty read");
125     AddSignal (22,   "SIGTTOU",    false,   true , true , "to readers process group upon background tty write");
126     AddSignal (23,   "SIGIO",      false,   false, false, "input/output possible signal");
127     AddSignal (24,   "SIGXCPU",    false,   true , true , "exceeded CPU time limit");
128     AddSignal (25,   "SIGXFSZ",    false,   true , true , "exceeded file size limit");
129     AddSignal (26,   "SIGVTALRM",  false,   false, false, "virtual time alarm");
130     AddSignal (27,   "SIGPROF",    false,   false, false, "profiling time alarm");
131     AddSignal (28,   "SIGWINCH",   false,   false, false, "window size changes");
132     AddSignal (29,   "SIGINFO",    false,   true , true , "information request");
133     AddSignal (30,   "SIGUSR1",    false,   true , true , "user defined signal 1");
134     AddSignal (31,   "SIGUSR2",    false,   true , true , "user defined signal 2");
135 }
136 
137 void
138 UnixSignals::AddSignal
139 (
140     int signo,
141     const char *name,
142     bool default_suppress,
143     bool default_stop,
144     bool default_notify,
145     const char *description,
146     const char *alias
147 )
148 {
149     Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias);
150     m_signals.insert (std::make_pair(signo, new_signal));
151 }
152 
153 void
154 UnixSignals::RemoveSignal (int signo)
155 {
156     collection::iterator pos = m_signals.find (signo);
157     if (pos != m_signals.end())
158         m_signals.erase (pos);
159 }
160 
161 const char *
162 UnixSignals::GetSignalAsCString (int signo) const
163 {
164     collection::const_iterator pos = m_signals.find (signo);
165     if (pos == m_signals.end())
166         return NULL;
167     else
168         return pos->second.m_name.GetCString ();
169 }
170 
171 
172 bool
173 UnixSignals::SignalIsValid (int32_t signo) const
174 {
175     return m_signals.find (signo) != m_signals.end();
176 }
177 
178 ConstString
179 UnixSignals::GetShortName(ConstString name) const
180 {
181     if (name)
182     {
183       const char* signame = name.AsCString();
184       return ConstString(signame + 3); // Remove "SIG" from name
185     }
186     return name;
187 }
188 
189 int32_t
190 UnixSignals::GetSignalNumberFromName (const char *name) const
191 {
192     ConstString const_name (name);
193 
194     collection::const_iterator pos, end = m_signals.end ();
195     for (pos = m_signals.begin (); pos != end; pos++)
196     {
197         if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) ||
198             (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias)))
199             return pos->first;
200     }
201 
202     const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
203     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
204         return signo;
205     return LLDB_INVALID_SIGNAL_NUMBER;
206 }
207 
208 int32_t
209 UnixSignals::GetFirstSignalNumber () const
210 {
211     if (m_signals.empty())
212         return LLDB_INVALID_SIGNAL_NUMBER;
213 
214     return (*m_signals.begin ()).first;
215 }
216 
217 int32_t
218 UnixSignals::GetNextSignalNumber (int32_t current_signal) const
219 {
220     collection::const_iterator pos = m_signals.find (current_signal);
221     collection::const_iterator end = m_signals.end();
222     if (pos == end)
223         return LLDB_INVALID_SIGNAL_NUMBER;
224     else
225     {
226         pos++;
227         if (pos == end)
228             return LLDB_INVALID_SIGNAL_NUMBER;
229         else
230             return pos->first;
231     }
232 }
233 
234 const char *
235 UnixSignals::GetSignalInfo
236 (
237     int32_t signo,
238     bool &should_suppress,
239     bool &should_stop,
240     bool &should_notify
241 ) const
242 {
243     collection::const_iterator pos = m_signals.find (signo);
244     if (pos == m_signals.end())
245         return NULL;
246     else
247     {
248         const Signal &signal = pos->second;
249         should_suppress = signal.m_suppress;
250         should_stop     = signal.m_stop;
251         should_notify   = signal.m_notify;
252         return signal.m_name.AsCString("");
253     }
254 }
255 
256 bool
257 UnixSignals::GetShouldSuppress (int signo) const
258 {
259     collection::const_iterator pos = m_signals.find (signo);
260     if (pos != m_signals.end())
261         return pos->second.m_suppress;
262     return false;
263 }
264 
265 bool
266 UnixSignals::SetShouldSuppress (int signo, bool value)
267 {
268     collection::iterator pos = m_signals.find (signo);
269     if (pos != m_signals.end())
270     {
271         pos->second.m_suppress = value;
272         return true;
273     }
274     return false;
275 }
276 
277 bool
278 UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
279 {
280     const int32_t signo = GetSignalNumberFromName (signal_name);
281     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
282         return SetShouldSuppress (signo, value);
283     return false;
284 }
285 
286 bool
287 UnixSignals::GetShouldStop (int signo) const
288 {
289     collection::const_iterator pos = m_signals.find (signo);
290     if (pos != m_signals.end())
291         return pos->second.m_stop;
292     return false;
293 }
294 
295 bool
296 UnixSignals::SetShouldStop (int signo, bool value)
297 {
298     collection::iterator pos = m_signals.find (signo);
299     if (pos != m_signals.end())
300     {
301         pos->second.m_stop = value;
302         return true;
303     }
304     return false;
305 }
306 
307 bool
308 UnixSignals::SetShouldStop (const char *signal_name, bool value)
309 {
310     const int32_t signo = GetSignalNumberFromName (signal_name);
311     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
312         return SetShouldStop (signo, value);
313     return false;
314 }
315 
316 bool
317 UnixSignals::GetShouldNotify (int signo) const
318 {
319     collection::const_iterator pos = m_signals.find (signo);
320     if (pos != m_signals.end())
321         return pos->second.m_notify;
322     return false;
323 }
324 
325 bool
326 UnixSignals::SetShouldNotify (int signo, bool value)
327 {
328     collection::iterator pos = m_signals.find (signo);
329     if (pos != m_signals.end())
330     {
331         pos->second.m_notify = value;
332         return true;
333     }
334     return false;
335 }
336 
337 bool
338 UnixSignals::SetShouldNotify (const char *signal_name, bool value)
339 {
340     const int32_t signo = GetSignalNumberFromName (signal_name);
341     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
342         return SetShouldNotify (signo, value);
343     return false;
344 }
345 
346 int32_t
347 UnixSignals::GetNumSignals() const
348 {
349     return m_signals.size();
350 }
351 
352 int32_t
353 UnixSignals::GetSignalAtIndex(int32_t index) const
354 {
355     if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
356         return LLDB_INVALID_SIGNAL_NUMBER;
357     auto it = m_signals.begin();
358     std::advance(it, index);
359     return it->first;
360 }
361