forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			361 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			361 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.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "lldb/Target/UnixSignals.h"
 | 
						|
 | 
						|
// C Includes
 | 
						|
// C++ Includes
 | 
						|
// Other libraries and framework includes
 | 
						|
// Project includes
 | 
						|
#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)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
// Destructor
 | 
						|
//----------------------------------------------------------------------
 | 
						|
UnixSignals::~UnixSignals ()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
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 NULL;
 | 
						|
    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 NULL;
 | 
						|
    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;
 | 
						|
}
 |