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