strace: Print detailed signal information
- Add support for retrieving the `siginfo_t` structure of a signal event from the Debugger API. - Add code to `strace` to display this information every time a signal event occurs, similar to the Linux `strace` tool. Change-Id: If4e92bbae049ee0b52efaf9fc911d66511da62f4 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6393 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
0992009d13
commit
bfd3d33765
@@ -533,6 +533,7 @@ typedef struct {
|
|||||||
debug_origin origin;
|
debug_origin origin;
|
||||||
int signal; // the signal
|
int signal; // the signal
|
||||||
struct sigaction handler; // the signal handler
|
struct sigaction handler; // the signal handler
|
||||||
|
siginfo_t info; // the signal info
|
||||||
bool deadly; // true, if handling the signal will kill
|
bool deadly; // true, if handling the signal will kill
|
||||||
// the team
|
// the team
|
||||||
} debug_signal_received;
|
} debug_signal_received;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ void user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
|
|||||||
bigtime_t startTime);
|
bigtime_t startTime);
|
||||||
bool user_debug_exception_occurred(debug_exception_type exception, int signal);
|
bool user_debug_exception_occurred(debug_exception_type exception, int signal);
|
||||||
bool user_debug_handle_signal(int signal, struct sigaction *handler,
|
bool user_debug_handle_signal(int signal, struct sigaction *handler,
|
||||||
bool deadly);
|
siginfo_t *info, bool deadly);
|
||||||
void user_debug_stop_thread();
|
void user_debug_stop_thread();
|
||||||
void user_debug_team_created(team_id teamID);
|
void user_debug_team_created(team_id teamID);
|
||||||
void user_debug_team_deleted(team_id teamID, port_id debuggerPort);
|
void user_debug_team_deleted(team_id teamID, port_id debuggerPort);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ local straceSources =
|
|||||||
fcntl.cpp
|
fcntl.cpp
|
||||||
ioctl.cpp
|
ioctl.cpp
|
||||||
network.cpp
|
network.cpp
|
||||||
|
signals.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
# Our compiler badly chokes when compiling the generated file. So will
|
# Our compiler badly chokes when compiling the generated file. So will
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023, Trung Nguyen, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "signals.h"
|
||||||
|
|
||||||
|
|
||||||
|
// signal names
|
||||||
|
static const char *kSignalName[] = {
|
||||||
|
/* 0 */ "SIG0",
|
||||||
|
/* 1 */ "SIGHUP",
|
||||||
|
/* 2 */ "SIGINT",
|
||||||
|
/* 3 */ "SIGQUIT",
|
||||||
|
/* 4 */ "SIGILL",
|
||||||
|
/* 5 */ "SIGCHLD",
|
||||||
|
/* 6 */ "SIGABRT",
|
||||||
|
/* 7 */ "SIGPIPE",
|
||||||
|
/* 8 */ "SIGFPE",
|
||||||
|
/* 9 */ "SIGKILL",
|
||||||
|
/* 10 */ "SIGSTOP",
|
||||||
|
/* 11 */ "SIGSEGV",
|
||||||
|
/* 12 */ "SIGCONT",
|
||||||
|
/* 13 */ "SIGTSTP",
|
||||||
|
/* 14 */ "SIGALRM",
|
||||||
|
/* 15 */ "SIGTERM",
|
||||||
|
/* 16 */ "SIGTTIN",
|
||||||
|
/* 17 */ "SIGTTOU",
|
||||||
|
/* 18 */ "SIGUSR1",
|
||||||
|
/* 19 */ "SIGUSR2",
|
||||||
|
/* 20 */ "SIGWINCH",
|
||||||
|
/* 21 */ "SIGKILLTHR",
|
||||||
|
/* 22 */ "SIGTRAP",
|
||||||
|
/* 23 */ "SIGPOLL",
|
||||||
|
/* 24 */ "SIGPROF",
|
||||||
|
/* 25 */ "SIGSYS",
|
||||||
|
/* 26 */ "SIGURG",
|
||||||
|
/* 27 */ "SIGVTALRM",
|
||||||
|
/* 28 */ "SIGXCPU",
|
||||||
|
/* 29 */ "SIGXFSZ",
|
||||||
|
/* 30 */ "SIGBUS",
|
||||||
|
/* 31 */ "SIGRESERVED1",
|
||||||
|
/* 32 */ "SIGRESERVED2",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
signal_name(int signal)
|
||||||
|
{
|
||||||
|
if (signal >= 0 && signal <= SIGRESERVED2)
|
||||||
|
return kSignalName[signal];
|
||||||
|
|
||||||
|
static char buffer[32];
|
||||||
|
sprintf(buffer, "%d", signal);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
signal_code(int signal, int code)
|
||||||
|
{
|
||||||
|
#define CASE(X) case X: return #X;
|
||||||
|
switch (code) {
|
||||||
|
CASE(SI_USER)
|
||||||
|
CASE(SI_QUEUE)
|
||||||
|
CASE(SI_TIMER)
|
||||||
|
CASE(SI_ASYNCIO)
|
||||||
|
CASE(SI_MESGQ)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (signal) {
|
||||||
|
case SIGILL:
|
||||||
|
switch (code) {
|
||||||
|
CASE(ILL_ILLOPC)
|
||||||
|
CASE(ILL_ILLOPN)
|
||||||
|
CASE(ILL_ILLADR)
|
||||||
|
CASE(ILL_ILLTRP)
|
||||||
|
CASE(ILL_PRVOPC)
|
||||||
|
CASE(ILL_PRVREG)
|
||||||
|
CASE(ILL_COPROC)
|
||||||
|
CASE(ILL_BADSTK)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGFPE:
|
||||||
|
switch (code) {
|
||||||
|
CASE(FPE_INTDIV)
|
||||||
|
CASE(FPE_INTOVF)
|
||||||
|
CASE(FPE_FLTDIV)
|
||||||
|
CASE(FPE_FLTOVF)
|
||||||
|
CASE(FPE_FLTUND)
|
||||||
|
CASE(FPE_FLTRES)
|
||||||
|
CASE(FPE_FLTINV)
|
||||||
|
CASE(FPE_FLTSUB)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGSEGV:
|
||||||
|
switch (code) {
|
||||||
|
CASE(SEGV_MAPERR)
|
||||||
|
CASE(SEGV_ACCERR)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGBUS:
|
||||||
|
switch (code) {
|
||||||
|
CASE(BUS_ADRALN)
|
||||||
|
CASE(BUS_ADRERR)
|
||||||
|
CASE(BUS_OBJERR)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGTRAP:
|
||||||
|
switch (code) {
|
||||||
|
CASE(TRAP_BRKPT)
|
||||||
|
CASE(TRAP_TRACE)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGCHLD:
|
||||||
|
switch (code) {
|
||||||
|
CASE(CLD_EXITED)
|
||||||
|
CASE(CLD_KILLED)
|
||||||
|
CASE(CLD_DUMPED)
|
||||||
|
CASE(CLD_TRAPPED)
|
||||||
|
CASE(CLD_STOPPED)
|
||||||
|
CASE(CLD_CONTINUED)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIGPOLL:
|
||||||
|
switch (code) {
|
||||||
|
CASE(POLL_IN)
|
||||||
|
CASE(POLL_OUT)
|
||||||
|
CASE(POLL_MSG)
|
||||||
|
CASE(POLL_ERR)
|
||||||
|
CASE(POLL_PRI)
|
||||||
|
CASE(POLL_HUP)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#undef CASE
|
||||||
|
|
||||||
|
static char buffer[32];
|
||||||
|
sprintf(buffer, "%d", code);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
signal_info(siginfo_t& info)
|
||||||
|
{
|
||||||
|
static char buffer[32];
|
||||||
|
std::string string;
|
||||||
|
|
||||||
|
string.reserve(256);
|
||||||
|
|
||||||
|
string += "{";
|
||||||
|
string += "si_signo=";
|
||||||
|
string += signal_name(info.si_signo);
|
||||||
|
string += ", si_code=";
|
||||||
|
string += signal_code(info.si_signo, info.si_code);
|
||||||
|
|
||||||
|
if (info.si_errno != 0) {
|
||||||
|
string += ", si_errno=0x";
|
||||||
|
sprintf(buffer, "%x", info.si_errno);
|
||||||
|
string += buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
string += ", si_pid=";
|
||||||
|
sprintf(buffer, "%d", (int)info.si_pid);
|
||||||
|
string += buffer;
|
||||||
|
string += ", si_uid=";
|
||||||
|
sprintf(buffer, "%d", (int)info.si_uid);
|
||||||
|
string += buffer;
|
||||||
|
|
||||||
|
if (info.si_signo == SIGILL || info.si_signo == SIGFPE || info.si_signo == SIGSEGV
|
||||||
|
|| info.si_signo == SIGBUS || info.si_signo == SIGTRAP) {
|
||||||
|
string += ", si_addr=";
|
||||||
|
sprintf(buffer, "%p", info.si_addr);
|
||||||
|
string += buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.si_signo == SIGCHLD) {
|
||||||
|
string += ", si_status=";
|
||||||
|
sprintf(buffer, "%d", info.si_status);
|
||||||
|
string += buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.si_signo == SIGPOLL) {
|
||||||
|
string += ", si_band=";
|
||||||
|
sprintf(buffer, "%ld", info.si_band);
|
||||||
|
string += buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
string += ", si_value=";
|
||||||
|
sprintf(buffer, "%p", info.si_value.sival_ptr);
|
||||||
|
string += buffer;
|
||||||
|
string += "}";
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023, Trung Nguyen, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef STRACE_SIGNAL_H
|
||||||
|
#define STRACE_SIGNAL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
std::string signal_name(int signal);
|
||||||
|
std::string signal_info(siginfo_t& info);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // STRACE_SIGNAL_H
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "debug_utils.h"
|
#include "debug_utils.h"
|
||||||
|
|
||||||
|
#include "signals.h"
|
||||||
#include "Context.h"
|
#include "Context.h"
|
||||||
#include "MemoryReader.h"
|
#include "MemoryReader.h"
|
||||||
#include "Syscall.h"
|
#include "Syscall.h"
|
||||||
@@ -115,44 +116,6 @@ static const char *kTerminalTextMagenta = "\33[35m";
|
|||||||
static const char *kTerminalTextBlue = "\33[34m";
|
static const char *kTerminalTextBlue = "\33[34m";
|
||||||
|
|
||||||
|
|
||||||
// signal names
|
|
||||||
static const char *kSignalName[] = {
|
|
||||||
/* 0 */ "SIG0",
|
|
||||||
/* 1 */ "SIGHUP",
|
|
||||||
/* 2 */ "SIGINT",
|
|
||||||
/* 3 */ "SIGQUIT",
|
|
||||||
/* 4 */ "SIGILL",
|
|
||||||
/* 5 */ "SIGCHLD",
|
|
||||||
/* 6 */ "SIGABRT",
|
|
||||||
/* 7 */ "SIGPIPE",
|
|
||||||
/* 8 */ "SIGFPE",
|
|
||||||
/* 9 */ "SIGKILL",
|
|
||||||
/* 10 */ "SIGSTOP",
|
|
||||||
/* 11 */ "SIGSEGV",
|
|
||||||
/* 12 */ "SIGCONT",
|
|
||||||
/* 13 */ "SIGTSTP",
|
|
||||||
/* 14 */ "SIGALRM",
|
|
||||||
/* 15 */ "SIGTERM",
|
|
||||||
/* 16 */ "SIGTTIN",
|
|
||||||
/* 17 */ "SIGTTOU",
|
|
||||||
/* 18 */ "SIGUSR1",
|
|
||||||
/* 19 */ "SIGUSR2",
|
|
||||||
/* 20 */ "SIGWINCH",
|
|
||||||
/* 21 */ "SIGKILLTHR",
|
|
||||||
/* 22 */ "SIGTRAP",
|
|
||||||
/* 23 */ "SIGPOLL",
|
|
||||||
/* 24 */ "SIGPROF",
|
|
||||||
/* 25 */ "SIGSYS",
|
|
||||||
/* 26 */ "SIGURG",
|
|
||||||
/* 27 */ "SIGVTALRM",
|
|
||||||
/* 28 */ "SIGXCPU",
|
|
||||||
/* 29 */ "SIGXFSZ",
|
|
||||||
/* 30 */ "SIGBUS",
|
|
||||||
/* 31 */ "SIGRESERVED1",
|
|
||||||
/* 32 */ "SIGRESERVED2",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// command line args
|
// command line args
|
||||||
static int sArgc;
|
static int sArgc;
|
||||||
static const char *const *sArgv;
|
static const char *const *sArgv;
|
||||||
@@ -507,18 +470,6 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
signal_name(int signal)
|
|
||||||
{
|
|
||||||
if (signal >= 0 && signal <= SIGRESERVED2)
|
|
||||||
return kSignalName[signal];
|
|
||||||
|
|
||||||
static char buffer[32];
|
|
||||||
sprintf(buffer, "%d", signal);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_signal(FILE *outputFile, debug_signal_received &message,
|
print_signal(FILE *outputFile, debug_signal_received &message,
|
||||||
bool colorize)
|
bool colorize)
|
||||||
@@ -529,13 +480,14 @@ print_signal(FILE *outputFile, debug_signal_received &message,
|
|||||||
|
|
||||||
// print signal name
|
// print signal name
|
||||||
if (colorize) {
|
if (colorize) {
|
||||||
print_to_string(&string, &length, "[%6" B_PRId32 "] --- %s%s (%s) %s---\n",
|
print_to_string(&string, &length, "[%6" B_PRId32 "] --- %s%s (%s)%s %s ---\n",
|
||||||
message.origin.thread, kTerminalTextRed, signal_name(signalNumber),
|
message.origin.thread, kTerminalTextRed,
|
||||||
strsignal(signalNumber), kTerminalTextNormal);
|
signal_name(signalNumber).c_str(), strsignal(signalNumber),
|
||||||
|
kTerminalTextNormal, signal_info(message.info).c_str());
|
||||||
} else {
|
} else {
|
||||||
print_to_string(&string, &length, "[%6" B_PRId32 "] --- %s (%s) ---\n",
|
print_to_string(&string, &length, "[%6" B_PRId32 "] --- %s (%s) %s ---\n",
|
||||||
message.origin.thread, signal_name(signalNumber),
|
message.origin.thread, signal_name(signalNumber).c_str(),
|
||||||
strsignal(signalNumber));
|
strsignal(signalNumber), signal_info(message.info).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
print_buffer(outputFile, buffer, sizeof(buffer) - length);
|
print_buffer(outputFile, buffer, sizeof(buffer) - length);
|
||||||
|
|||||||
@@ -928,7 +928,8 @@ user_debug_exception_occurred(debug_exception_type exception, int signal)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
|
user_debug_handle_signal(int signal, struct sigaction *handler, siginfo_t *info,
|
||||||
|
bool deadly)
|
||||||
{
|
{
|
||||||
// check, if a debugger is installed and is interested in signals
|
// check, if a debugger is installed and is interested in signals
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread *thread = thread_get_current_thread();
|
||||||
@@ -942,6 +943,7 @@ user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
|
|||||||
debug_signal_received message;
|
debug_signal_received message;
|
||||||
message.signal = signal;
|
message.signal = signal;
|
||||||
message.handler = *handler;
|
message.handler = *handler;
|
||||||
|
message.info = *info;
|
||||||
message.deadly = deadly;
|
message.deadly = deadly;
|
||||||
|
|
||||||
status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,
|
status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,
|
||||||
|
|||||||
@@ -821,8 +821,19 @@ notify_debugger(Thread* thread, Signal* signal, struct sigaction& handler,
|
|||||||
|
|
||||||
threadDebugInfoLocker.Unlock();
|
threadDebugInfoLocker.Unlock();
|
||||||
|
|
||||||
|
siginfo_t info;
|
||||||
|
info.si_signo = signal->Number();
|
||||||
|
info.si_code = signal->SignalCode();
|
||||||
|
info.si_errno = signal->ErrorCode();
|
||||||
|
info.si_pid = signal->SendingProcess();
|
||||||
|
info.si_uid = signal->SendingUser();
|
||||||
|
info.si_addr = signal->Address();
|
||||||
|
info.si_status = signal->Status();
|
||||||
|
info.si_band = signal->PollBand();
|
||||||
|
info.si_value = signal->UserValue();
|
||||||
|
|
||||||
// deliver the event
|
// deliver the event
|
||||||
return user_debug_handle_signal(signal->Number(), &handler, deadly);
|
return user_debug_handle_signal(signal->Number(), &handler, &info, deadly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user