- crash handler
这段代码是一个非常实用的 Linux 崩溃调试工具框架 —— 捕获常见崩溃信号(如 SIGSEGV),打印寄存器、崩溃地址、堆栈回溯等信息,并写入日志文件crash.log,别个大佬开源出来,仅做记录
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <signal.h>
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ucontext.h>
#include <sys/ucontext.h>
#define BACKTRACE_SIZE 100
#define DPRINTF(fd, format, ...) \
if (fd > STDERR_FILENO) \
dprintf(fd, format, ##__VA_ARGS__); \
dprintf(STDERR_FILENO, format, ##__VA_ARGS__)
void signal_handler(int sig, siginfo_t *info, void *ucontext) {
void *buffer[BACKTRACE_SIZE];
int nptrs = BACKTRACE_SIZE;
FILE *log_file = fopen("crash.log", "w");
int fd = fileno(log_file);
if (fd < 0) {
perror("open log file");
fd = STDERR_FILENO;
}
DPRINTF(fd, "========== crash report ========\n");
DPRINTF(fd, "Error: signal %d:\n", sig);
DPRINTF(fd, "Fault address: %p\n", info->si_addr);
DPRINTF(fd, "Fault code: %d\n", info->si_code);
DPRINTF(fd, "========== register info ========\n");
DPRINTF(fd, "register\thex value\t\tdec value\n");
ucontext_t *uc = (ucontext_t *)ucontext;
#if defined(__x86_64__)
DPRINTF(fd, "RIP:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RIP], (unsigned long long)uc->uc_mcontext.gregs[REG_RIP]);
DPRINTF(fd, "RSP:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RSP], (unsigned long long)uc->uc_mcontext.gregs[REG_RSP]);
DPRINTF(fd, "RBP:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RBP], (unsigned long long)uc->uc_mcontext.gregs[REG_RBP]);
DPRINTF(fd, "RAX:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RAX], (unsigned long long)uc->uc_mcontext.gregs[REG_RAX]);
DPRINTF(fd, "RBX:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RBX], (unsigned long long)uc->uc_mcontext.gregs[REG_RBX]);
DPRINTF(fd, "RCX:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RCX], (unsigned long long)uc->uc_mcontext.gregs[REG_RCX]);
DPRINTF(fd, "RDX:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RDX], (unsigned long long)uc->uc_mcontext.gregs[REG_RDX]);
DPRINTF(fd, "RSI:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RSI], (unsigned long long)uc->uc_mcontext.gregs[REG_RSI]);
DPRINTF(fd, "RDI:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_RDI], (unsigned long long)uc->uc_mcontext.gregs[REG_RDI]);
DPRINTF(fd, "R8:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R8], (unsigned long long)uc->uc_mcontext.gregs[REG_R8]);
DPRINTF(fd, "R9:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R9], (unsigned long long)uc->uc_mcontext.gregs[REG_R9]);
DPRINTF(fd, "R10:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R10], (unsigned long long)uc->uc_mcontext.gregs[REG_R10]);
DPRINTF(fd, "R11:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R11], (unsigned long long)uc->uc_mcontext.gregs[REG_R11]);
DPRINTF(fd, "R12:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R12], (unsigned long long)uc->uc_mcontext.gregs[REG_R12]);
DPRINTF(fd, "R13:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R13], (unsigned long long)uc->uc_mcontext.gregs[REG_R13]);
DPRINTF(fd, "R14:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R14], (unsigned long long)uc->uc_mcontext.gregs[REG_R14]);
DPRINTF(fd, "R15:\t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.gregs[REG_R15], (unsigned long long)uc->uc_mcontext.gregs[REG_R15]);
#elif defined(__aarch64__)
DPRINTF(fd, "PC: \t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.pc, (unsigned long long)uc->uc_mcontext.pc);
DPRINTF(fd, "SP: \t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.sp, (unsigned long long)uc->uc_mcontext.sp);
DPRINTF(fd, "FP: \t%16llx\t%20lld\n", (unsigned long long)uc->uc_mcontext.regs[29], (unsigned long long)uc->uc_mcontext.regs[29]);
for (int i = 0; i < 31; i++) {
DPRINTF(fd, "X%d: \t%16llx\t%20lld\n", i, (unsigned long long)uc->uc_mcontext.regs[i], (unsigned long long)uc->uc_mcontext.regs[i]);
}
#endif
DPRINTF(fd, "\n========== backtrace info ========\n");
nptrs = backtrace(buffer, BACKTRACE_SIZE);
if (nptrs == 0) {
DPRINTF(fd, "backtrace failed\n");
}
backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
if (log_file) {
backtrace_symbols_fd(buffer, nptrs, fd);
}
fclose(log_file);
_exit(EXIT_FAILURE);
}
void register_signal_handlers() {
struct sigaction sa;
sa.sa_sigaction = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_RESTART;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
}
void trigger_crash() {
volatile int *p = NULL;
*p = 42;
}
int main() {
register_signal_handlers();
trigger_crash();
return 0;
}