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;
|
|
}
|