QEMU-Nyx-fork/nyx/debug.c
Steffen Schulz 1609eee66a wait for gdb attach only when compiled for debug
Waiting for gdb attach is not useful/expected for normal use and has
a tendendency to create hanging qemu instances.
2022-11-22 09:58:32 +01:00

129 lines
3.2 KiB
C

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "qemu/osdep.h"
#include "nyx/debug.h"
#include "signal.h"
#ifdef ENABLE_BACKTRACES
#define BT_BUF_SIZE 100
void qemu_backtrace(void)
{
void *buffer[BT_BUF_SIZE];
int nptrs = 0;
int j;
nptrs = backtrace(buffer, BT_BUF_SIZE);
fprintf(stderr, "backtrace() returned %d addresses\n", nptrs);
char **strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
fprintf(stderr, "backtrace_symbols failed!\n");
return;
// exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
fprintf(stderr, "%s\n", strings[j]);
free(strings);
}
static void sigsegfault_handler(int signo, siginfo_t *info, void *extra)
{
fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(),
signo);
qemu_backtrace();
#ifdef NYX_DEBUG
fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
while (1) {
sleep(1);
}
#endif /* NYX_DEBUG */
}
static void sigabrt_handler(int signo, siginfo_t *info, void *extra)
{
fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(),
signo);
qemu_backtrace();
#ifdef NYX_DEBUG
fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
while (1) {
sleep(1);
}
#endif /* NYX_DEBUG */
}
static void sigint_handler(int signo, siginfo_t *info, void *extra)
{
fprintf(stderr, "[qemu-nyx] bye! (pid: %d / signal: %d)\n", getpid(), signo);
exit(0);
}
void init_crash_handler(void)
{
struct sigaction action;
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = sigsegfault_handler;
if (sigaction(SIGSEGV, &action, NULL) == -1) {
fprintf(stderr, "SIGSEGV: sigaction failed");
_exit(1);
}
action.sa_sigaction = sigabrt_handler;
if (sigaction(SIGABRT, &action, NULL) == -1) {
fprintf(stderr, "SIGABRT: sigaction failed");
_exit(1);
}
/* don't install a SIGINT handler if the nyx block cow cache layer is disabled */
if (!getenv("NYX_DISABLE_BLOCK_COW")) {
action.sa_sigaction = sigint_handler;
if (sigaction(SIGINT, &action, NULL) == -1) {
fprintf(stderr, "SIGINT: sigaction failed");
_exit(1);
}
}
}
void hexdump_kafl(const void *data, size_t size)
{
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
printf("%02X ", ((unsigned char *)data)[i]);
if (((unsigned char *)data)[i] >= ' ' && ((unsigned char *)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char *)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i + 1) % 8 == 0 || i + 1 == size) {
printf(" ");
if ((i + 1) % 16 == 0) {
printf("| %s \n", ascii);
} else if (i + 1 == size) {
ascii[(i + 1) % 16] = '\0';
if ((i + 1) % 16 <= 8) {
printf(" ");
}
for (j = (i + 1) % 16; j < 16; ++j) {
printf(" ");
}
printf("| %s \n", ascii);
}
}
}
}
#endif