forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			345 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| 
 | |
| // C Includes
 | |
| // C++ Includes
 | |
| // Other libraries and framework includes
 | |
| // Project includes
 | |
| #include "lldb/Target/UnixSignals.h"
 | |
| #include "lldb/Core/ArchSpec.h"
 | |
| #include "lldb/Host/StringConvert.h"
 | |
| #include "Plugins/Process/Utility/FreeBSDSignals.h"
 | |
| #include "Plugins/Process/Utility/LinuxSignals.h"
 | |
| #include "Plugins/Process/Utility/MipsLinuxSignals.h"
 | |
| #include "Plugins/Process/Utility/NetBSDSignals.h"
 | |
| 
 | |
| using namespace lldb_private;
 | |
| 
 | |
| UnixSignals::Signal::Signal(const char *name,
 | |
|                             bool default_suppress,
 | |
|                             bool default_stop,
 | |
|                             bool default_notify,
 | |
|                             const char *description,
 | |
|                             const char *alias) :
 | |
|     m_name (name),
 | |
|     m_alias (alias),
 | |
|     m_description (),
 | |
|     m_suppress (default_suppress),
 | |
|     m_stop (default_stop),
 | |
|     m_notify (default_notify)
 | |
| {
 | |
|     if (description)
 | |
|         m_description.assign (description);
 | |
| }
 | |
| 
 | |
| lldb::UnixSignalsSP
 | |
| UnixSignals::Create(const ArchSpec &arch)
 | |
| {
 | |
|     const auto &triple = arch.GetTriple();
 | |
|     switch (triple.getOS())
 | |
|     {
 | |
|         case llvm::Triple::Linux:
 | |
|         {
 | |
|             switch (triple.getArch())
 | |
|             {
 | |
|                 case llvm::Triple::mips:
 | |
|                 case llvm::Triple::mipsel:
 | |
|                 case llvm::Triple::mips64:
 | |
|                 case llvm::Triple::mips64el:
 | |
|                     return std::make_shared<MipsLinuxSignals>();
 | |
|                 default:
 | |
|                     return std::make_shared<LinuxSignals>();
 | |
|             }
 | |
|         }
 | |
|         case llvm::Triple::FreeBSD:
 | |
|         case llvm::Triple::OpenBSD:
 | |
|             return std::make_shared<FreeBSDSignals>();
 | |
|         case llvm::Triple::NetBSD:
 | |
|             return std::make_shared<NetBSDSignals>();
 | |
|         default:
 | |
|             return std::make_shared<UnixSignals>();
 | |
|     }
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| // UnixSignals constructor
 | |
| //----------------------------------------------------------------------
 | |
| UnixSignals::UnixSignals ()
 | |
| {
 | |
|     Reset ();
 | |
| }
 | |
| 
 | |
| UnixSignals::UnixSignals(const UnixSignals &rhs)
 | |
|     : m_signals(rhs.m_signals)
 | |
| {
 | |
| }
 | |
| 
 | |
| UnixSignals::~UnixSignals() = default;
 | |
| 
 | |
| void
 | |
| UnixSignals::Reset ()
 | |
| {
 | |
|     // This builds one standard set of Unix Signals.  If yours aren't quite in this
 | |
|     // order, you can either subclass this class, and use Add & Remove to change them
 | |
|     // or you can subclass and build them afresh in your constructor;
 | |
|     m_signals.clear();
 | |
|     //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION
 | |
|     //        ====== ============  ======== ====== ====== ===================================================
 | |
|     AddSignal (1,    "SIGHUP",     false,   true , true , "hangup");
 | |
|     AddSignal (2,    "SIGINT",     true ,   true , true , "interrupt");
 | |
|     AddSignal (3,    "SIGQUIT",    false,   true , true , "quit");
 | |
|     AddSignal (4,    "SIGILL",     false,   true , true , "illegal instruction");
 | |
|     AddSignal (5,    "SIGTRAP",    true ,   true , true , "trace trap (not reset when caught)");
 | |
|     AddSignal (6,    "SIGABRT",    false,   true , true , "abort()");
 | |
|     AddSignal (7,    "SIGEMT",     false,   true , true , "pollable event");
 | |
|     AddSignal (8,    "SIGFPE",     false,   true , true , "floating point exception");
 | |
|     AddSignal (9,    "SIGKILL",    false,   true , true , "kill");
 | |
|     AddSignal (10,   "SIGBUS",     false,   true , true , "bus error");
 | |
|     AddSignal (11,   "SIGSEGV",    false,   true , true , "segmentation violation");
 | |
|     AddSignal (12,   "SIGSYS",     false,   true , true , "bad argument to system call");
 | |
|     AddSignal (13,   "SIGPIPE",    false,   true , true , "write on a pipe with no one to read it");
 | |
|     AddSignal (14,   "SIGALRM",    false,   false, false, "alarm clock");
 | |
|     AddSignal (15,   "SIGTERM",    false,   true , true , "software termination signal from kill");
 | |
|     AddSignal (16,   "SIGURG",     false,   false, false, "urgent condition on IO channel");
 | |
|     AddSignal (17,   "SIGSTOP",    true ,   true , true , "sendable stop signal not from tty");
 | |
|     AddSignal (18,   "SIGTSTP",    false,   true , true , "stop signal from tty");
 | |
|     AddSignal (19,   "SIGCONT",    false,   true , true , "continue a stopped process");
 | |
|     AddSignal (20,   "SIGCHLD",    false,   false, false, "to parent on child stop or exit");
 | |
|     AddSignal (21,   "SIGTTIN",    false,   true , true , "to readers process group upon background tty read");
 | |
|     AddSignal (22,   "SIGTTOU",    false,   true , true , "to readers process group upon background tty write");
 | |
|     AddSignal (23,   "SIGIO",      false,   false, false, "input/output possible signal");
 | |
|     AddSignal (24,   "SIGXCPU",    false,   true , true , "exceeded CPU time limit");
 | |
|     AddSignal (25,   "SIGXFSZ",    false,   true , true , "exceeded file size limit");
 | |
|     AddSignal (26,   "SIGVTALRM",  false,   false, false, "virtual time alarm");
 | |
|     AddSignal (27,   "SIGPROF",    false,   false, false, "profiling time alarm");
 | |
|     AddSignal (28,   "SIGWINCH",   false,   false, false, "window size changes");
 | |
|     AddSignal (29,   "SIGINFO",    false,   true , true , "information request");
 | |
|     AddSignal (30,   "SIGUSR1",    false,   true , true , "user defined signal 1");
 | |
|     AddSignal (31,   "SIGUSR2",    false,   true , true , "user defined signal 2");
 | |
| }
 | |
| 
 | |
| void
 | |
| UnixSignals::AddSignal(int signo,
 | |
|                        const char *name,
 | |
|                        bool default_suppress,
 | |
|                        bool default_stop,
 | |
|                        bool default_notify,
 | |
|                        const char *description,
 | |
|                        const char *alias)
 | |
| {
 | |
|     Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias);
 | |
|     m_signals.insert (std::make_pair(signo, new_signal));
 | |
| }
 | |
| 
 | |
| void
 | |
| UnixSignals::RemoveSignal (int signo)
 | |
| {
 | |
|     collection::iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|         m_signals.erase (pos);
 | |
| }
 | |
| 
 | |
| const char *
 | |
| UnixSignals::GetSignalAsCString (int signo) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (signo);
 | |
|     if (pos == m_signals.end())
 | |
|         return nullptr;
 | |
|     else
 | |
|         return pos->second.m_name.GetCString ();
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SignalIsValid (int32_t signo) const
 | |
| {
 | |
|     return m_signals.find (signo) != m_signals.end();
 | |
| }
 | |
| 
 | |
| ConstString
 | |
| UnixSignals::GetShortName(ConstString name) const
 | |
| {
 | |
|     if (name)
 | |
|     {
 | |
|       const char* signame = name.AsCString();
 | |
|       return ConstString(signame + 3); // Remove "SIG" from name
 | |
|     }
 | |
|     return name;
 | |
| }
 | |
| 
 | |
| int32_t
 | |
| UnixSignals::GetSignalNumberFromName (const char *name) const
 | |
| {
 | |
|     ConstString const_name (name);
 | |
| 
 | |
|     collection::const_iterator pos, end = m_signals.end ();
 | |
|     for (pos = m_signals.begin (); pos != end; pos++)
 | |
|     {
 | |
|         if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) ||
 | |
|             (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias)))
 | |
|             return pos->first;
 | |
|     }
 | |
|     
 | |
|     const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
 | |
|     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
 | |
|         return signo;
 | |
|     return LLDB_INVALID_SIGNAL_NUMBER;
 | |
| }
 | |
| 
 | |
| int32_t
 | |
| UnixSignals::GetFirstSignalNumber () const
 | |
| {
 | |
|     if (m_signals.empty())
 | |
|         return LLDB_INVALID_SIGNAL_NUMBER;
 | |
| 
 | |
|     return (*m_signals.begin ()).first;
 | |
| }
 | |
| 
 | |
| int32_t
 | |
| UnixSignals::GetNextSignalNumber (int32_t current_signal) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (current_signal);
 | |
|     collection::const_iterator end = m_signals.end();
 | |
|     if (pos == end)
 | |
|         return LLDB_INVALID_SIGNAL_NUMBER;
 | |
|     else
 | |
|     {
 | |
|         pos++;
 | |
|         if (pos == end)
 | |
|             return LLDB_INVALID_SIGNAL_NUMBER;
 | |
|         else
 | |
|             return pos->first;
 | |
|     }
 | |
| }
 | |
| 
 | |
| const char *
 | |
| UnixSignals::GetSignalInfo(int32_t signo,
 | |
|                            bool &should_suppress,
 | |
|                            bool &should_stop,
 | |
|                            bool &should_notify) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (signo);
 | |
|     if (pos == m_signals.end())
 | |
|         return nullptr;
 | |
|     else
 | |
|     {
 | |
|         const Signal &signal = pos->second;
 | |
|         should_suppress = signal.m_suppress;
 | |
|         should_stop     = signal.m_stop;
 | |
|         should_notify   = signal.m_notify;
 | |
|         return signal.m_name.AsCString("");
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::GetShouldSuppress (int signo) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|         return pos->second.m_suppress;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldSuppress (int signo, bool value)
 | |
| {
 | |
|     collection::iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|     {
 | |
|         pos->second.m_suppress = value;
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
 | |
| {
 | |
|     const int32_t signo = GetSignalNumberFromName (signal_name);
 | |
|     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
 | |
|         return SetShouldSuppress (signo, value);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::GetShouldStop (int signo) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|         return pos->second.m_stop;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldStop (int signo, bool value)
 | |
| {
 | |
|     collection::iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|     {
 | |
|         pos->second.m_stop = value;
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldStop (const char *signal_name, bool value)
 | |
| {
 | |
|     const int32_t signo = GetSignalNumberFromName (signal_name);
 | |
|     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
 | |
|         return SetShouldStop (signo, value);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::GetShouldNotify (int signo) const
 | |
| {
 | |
|     collection::const_iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|         return pos->second.m_notify;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldNotify (int signo, bool value)
 | |
| {
 | |
|     collection::iterator pos = m_signals.find (signo);
 | |
|     if (pos != m_signals.end())
 | |
|     {
 | |
|         pos->second.m_notify = value;
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| UnixSignals::SetShouldNotify (const char *signal_name, bool value)
 | |
| {
 | |
|     const int32_t signo = GetSignalNumberFromName (signal_name);
 | |
|     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
 | |
|         return SetShouldNotify (signo, value);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| int32_t
 | |
| UnixSignals::GetNumSignals() const
 | |
| {
 | |
|     return m_signals.size();
 | |
| }
 | |
| 
 | |
| int32_t
 | |
| UnixSignals::GetSignalAtIndex(int32_t index) const
 | |
| {
 | |
|     if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
 | |
|         return LLDB_INVALID_SIGNAL_NUMBER;
 | |
|     auto it = m_signals.begin();
 | |
|     std::advance(it, index);
 | |
|     return it->first;
 | |
| }
 |