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