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 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 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 //---------------------------------------------------------------------- 76 UnixSignals::UnixSignals () 77 { 78 Reset (); 79 } 80 81 UnixSignals::UnixSignals(const UnixSignals &rhs) 82 : m_signals(rhs.m_signals) 83 { 84 } 85 86 //---------------------------------------------------------------------- 87 // Destructor 88 //---------------------------------------------------------------------- 89 UnixSignals::~UnixSignals () 90 { 91 } 92 93 void 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 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 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 * 160 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 171 UnixSignals::SignalIsValid (int32_t signo) const 172 { 173 return m_signals.find (signo) != m_signals.end(); 174 } 175 176 177 int32_t 178 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 196 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 205 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 * 222 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 244 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 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 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 274 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 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 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 304 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 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 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 334 UnixSignals::GetNumSignals() const 335 { 336 return m_signals.size(); 337 } 338 339 int32_t 340 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