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