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