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 bool default_suppress, 29 bool default_stop, 30 bool default_notify, 31 const char *description, 32 const char *alias 33 ) : 34 m_name (name), 35 m_alias (alias), 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 SUPPRESS STOP NOTIFY DESCRIPTION 101 // ====== ============ ======== ====== ====== =================================================== 102 AddSignal (1, "SIGHUP", false, true , true , "hangup"); 103 AddSignal (2, "SIGINT", true , true , true , "interrupt"); 104 AddSignal (3, "SIGQUIT", false, true , true , "quit"); 105 AddSignal (4, "SIGILL", false, true , true , "illegal instruction"); 106 AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)"); 107 AddSignal (6, "SIGABRT", false, true , true , "abort()"); 108 AddSignal (7, "SIGEMT", false, true , true , "pollable event"); 109 AddSignal (8, "SIGFPE", false, true , true , "floating point exception"); 110 AddSignal (9, "SIGKILL", false, true , true , "kill"); 111 AddSignal (10, "SIGBUS", false, true , true , "bus error"); 112 AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation"); 113 AddSignal (12, "SIGSYS", false, true , true , "bad argument to system call"); 114 AddSignal (13, "SIGPIPE", false, true , true , "write on a pipe with no one to read it"); 115 AddSignal (14, "SIGALRM", false, false, false, "alarm clock"); 116 AddSignal (15, "SIGTERM", false, true , true , "software termination signal from kill"); 117 AddSignal (16, "SIGURG", false, false, false, "urgent condition on IO channel"); 118 AddSignal (17, "SIGSTOP", true , true , true , "sendable stop signal not from tty"); 119 AddSignal (18, "SIGTSTP", false, true , true , "stop signal from tty"); 120 AddSignal (19, "SIGCONT", false, true , true , "continue a stopped process"); 121 AddSignal (20, "SIGCHLD", false, false, false, "to parent on child stop or exit"); 122 AddSignal (21, "SIGTTIN", false, true , true , "to readers process group upon background tty read"); 123 AddSignal (22, "SIGTTOU", false, true , true , "to readers process group upon background tty write"); 124 AddSignal (23, "SIGIO", false, false, false, "input/output possible signal"); 125 AddSignal (24, "SIGXCPU", false, true , true , "exceeded CPU time limit"); 126 AddSignal (25, "SIGXFSZ", false, true , true , "exceeded file size limit"); 127 AddSignal (26, "SIGVTALRM", false, false, false, "virtual time alarm"); 128 AddSignal (27, "SIGPROF", false, false, false, "profiling time alarm"); 129 AddSignal (28, "SIGWINCH", false, false, false, "window size changes"); 130 AddSignal (29, "SIGINFO", false, true , true , "information request"); 131 AddSignal (30, "SIGUSR1", false, true , true , "user defined signal 1"); 132 AddSignal (31, "SIGUSR2", false, true , true , "user defined signal 2"); 133 } 134 135 void 136 UnixSignals::AddSignal 137 ( 138 int signo, 139 const char *name, 140 bool default_suppress, 141 bool default_stop, 142 bool default_notify, 143 const char *description, 144 const char *alias 145 ) 146 { 147 Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias); 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 ConstString 177 UnixSignals::GetShortName(ConstString name) const 178 { 179 if (name) 180 { 181 char* signame = (char*)(name.AsCString()); 182 return ConstString(signame + 3); // Remove "SIG" from name 183 } 184 return name; 185 } 186 187 int32_t 188 UnixSignals::GetSignalNumberFromName (const char *name) const 189 { 190 ConstString const_name (name); 191 192 collection::const_iterator pos, end = m_signals.end (); 193 for (pos = m_signals.begin (); pos != end; pos++) 194 { 195 if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) || 196 (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias))) 197 return pos->first; 198 } 199 200 const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0); 201 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 202 return signo; 203 return LLDB_INVALID_SIGNAL_NUMBER; 204 } 205 206 int32_t 207 UnixSignals::GetFirstSignalNumber () const 208 { 209 if (m_signals.empty()) 210 return LLDB_INVALID_SIGNAL_NUMBER; 211 212 return (*m_signals.begin ()).first; 213 } 214 215 int32_t 216 UnixSignals::GetNextSignalNumber (int32_t current_signal) const 217 { 218 collection::const_iterator pos = m_signals.find (current_signal); 219 collection::const_iterator end = m_signals.end(); 220 if (pos == end) 221 return LLDB_INVALID_SIGNAL_NUMBER; 222 else 223 { 224 pos++; 225 if (pos == end) 226 return LLDB_INVALID_SIGNAL_NUMBER; 227 else 228 return pos->first; 229 } 230 } 231 232 const char * 233 UnixSignals::GetSignalInfo 234 ( 235 int32_t signo, 236 bool &should_suppress, 237 bool &should_stop, 238 bool &should_notify 239 ) const 240 { 241 collection::const_iterator pos = m_signals.find (signo); 242 if (pos == m_signals.end()) 243 return NULL; 244 else 245 { 246 const Signal &signal = pos->second; 247 should_suppress = signal.m_suppress; 248 should_stop = signal.m_stop; 249 should_notify = signal.m_notify; 250 return signal.m_name.AsCString(""); 251 } 252 } 253 254 bool 255 UnixSignals::GetShouldSuppress (int signo) const 256 { 257 collection::const_iterator pos = m_signals.find (signo); 258 if (pos != m_signals.end()) 259 return pos->second.m_suppress; 260 return false; 261 } 262 263 bool 264 UnixSignals::SetShouldSuppress (int signo, bool value) 265 { 266 collection::iterator pos = m_signals.find (signo); 267 if (pos != m_signals.end()) 268 { 269 pos->second.m_suppress = value; 270 return true; 271 } 272 return false; 273 } 274 275 bool 276 UnixSignals::SetShouldSuppress (const char *signal_name, bool value) 277 { 278 const int32_t signo = GetSignalNumberFromName (signal_name); 279 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 280 return SetShouldSuppress (signo, value); 281 return false; 282 } 283 284 bool 285 UnixSignals::GetShouldStop (int signo) const 286 { 287 collection::const_iterator pos = m_signals.find (signo); 288 if (pos != m_signals.end()) 289 return pos->second.m_stop; 290 return false; 291 } 292 293 bool 294 UnixSignals::SetShouldStop (int signo, bool value) 295 { 296 collection::iterator pos = m_signals.find (signo); 297 if (pos != m_signals.end()) 298 { 299 pos->second.m_stop = value; 300 return true; 301 } 302 return false; 303 } 304 305 bool 306 UnixSignals::SetShouldStop (const char *signal_name, bool value) 307 { 308 const int32_t signo = GetSignalNumberFromName (signal_name); 309 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 310 return SetShouldStop (signo, value); 311 return false; 312 } 313 314 bool 315 UnixSignals::GetShouldNotify (int signo) const 316 { 317 collection::const_iterator pos = m_signals.find (signo); 318 if (pos != m_signals.end()) 319 return pos->second.m_notify; 320 return false; 321 } 322 323 bool 324 UnixSignals::SetShouldNotify (int signo, bool value) 325 { 326 collection::iterator pos = m_signals.find (signo); 327 if (pos != m_signals.end()) 328 { 329 pos->second.m_notify = value; 330 return true; 331 } 332 return false; 333 } 334 335 bool 336 UnixSignals::SetShouldNotify (const char *signal_name, bool value) 337 { 338 const int32_t signo = GetSignalNumberFromName (signal_name); 339 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 340 return SetShouldNotify (signo, value); 341 return false; 342 } 343 344 int32_t 345 UnixSignals::GetNumSignals() const 346 { 347 return m_signals.size(); 348 } 349 350 int32_t 351 UnixSignals::GetSignalAtIndex(int32_t index) const 352 { 353 if (index < 0 || m_signals.size() <= static_cast<size_t>(index)) 354 return LLDB_INVALID_SIGNAL_NUMBER; 355 auto it = m_signals.begin(); 356 std::advance(it, index); 357 return it->first; 358 } 359