Created
February 2, 2020 20:27
-
-
Save Shviderskiy/248e82bf73931a4b38e33e2da275312c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "crash.h" | |
#define _GNU_SOURCE | |
#include <stddef.h> // NULL | |
#include <stdlib.h> // EXIT_FAILURE | |
#include <string.h> // strsignal | |
#include <stdarg.h> // va_list | |
#include <stdio.h> // vsnprintf | |
#include <signal.h> | |
#include <dlfcn.h> // Dl_info, dladdr | |
#include <link.h> // dl_phdr_info, dl_iterate_phdr | |
#include <execinfo.h> // backtrace, backtrace_symbols | |
/* https://sourceforge.net/p/predef/wiki/Architectures/ */ | |
#if defined(__amd64__) || \ | |
defined(__amd64) || \ | |
defined(__x86_64__) || \ | |
defined(__x86_64) | |
#define GET_CURRENT_STACK_FRAME(POINTER_) \ | |
__asm__ __volatile__("movq %%rbp, %0": "=r"(POINTER_)) | |
#elif defined(i386) || defined(__i386) || defined(__i386__) | |
#define GET_CURRENT_STACK_FRAME(POINTER_) \ | |
__asm__ __volatile__("mov %%ebp, %0": "=r"(POINTER_)) | |
#else | |
#error "Processor architecture is not supported!" | |
#endif | |
typedef struct _stack_frame_t | |
{ | |
struct _stack_frame_t * next; | |
void * ret_addr; | |
} | |
stack_frame_t; | |
static void(* __log)(char const * line_) = NULL; | |
static __sighandler_t __prev_signal_handler = NULL; | |
static void log(char const * format_, ...) | |
{ | |
if (__log == NULL) | |
return; | |
va_list args; | |
va_start(args, format_); | |
static __thread char buffer[256]; | |
vsnprintf(buffer, sizeof(buffer), format_, args); | |
va_end(args); | |
__log(buffer); | |
} | |
static int print_one_module( | |
struct dl_phdr_info * info_, size_t size_, void * data_) | |
{ | |
(void)size_; | |
(void)data_; | |
log("%s [%p]", info_->dlpi_name, (void *)info_->dlpi_addr); | |
return 0; | |
} | |
static void print_modules() | |
{ | |
log("========== MODULES =========="); | |
dl_iterate_phdr(print_one_module, NULL); | |
} | |
static void print_callstack() | |
{ | |
log("========== CALLSTACK =========="); | |
stack_frame_t * stack_frame = NULL; | |
GET_CURRENT_STACK_FRAME(stack_frame); | |
for ( ; stack_frame != NULL; stack_frame = stack_frame->next) | |
{ | |
Dl_info info; | |
if (dladdr(stack_frame->ret_addr, &info) == 0) | |
{ | |
log("???: ??? [???:%p]", stack_frame->ret_addr); | |
} | |
else | |
{ | |
log("%s: %s [%p:%p]", | |
info.dli_fname == NULL ? "???" : info.dli_fname, | |
info.dli_sname == NULL ? "???" : info.dli_sname, | |
info.dli_fbase, stack_frame->ret_addr); | |
} | |
} | |
} | |
static void print_callstack_default() | |
{ | |
log("========== CALLSTACK =========="); | |
void * addresses[1024]; | |
int addresses_count = backtrace(addresses, 1024); | |
if (addresses_count == 0) | |
{ | |
log("no backtrace"); | |
return; | |
} | |
char * * symbols = backtrace_symbols(addresses, addresses_count); | |
if (symbols == NULL) | |
{ | |
log("no symbols"); | |
return; | |
} | |
for (int i = 0; i < addresses_count; i++) | |
{ | |
if (symbols[i] != NULL) | |
log("%s", symbols[i]); | |
else log("%p", addresses[i]); | |
} | |
free(symbols); | |
} | |
static void signal_handler(int signal_) | |
{ | |
signal(signal_, __prev_signal_handler); | |
log("[%s] caught signal %d (%s)", __func__, signal_, strsignal(signal_)); | |
print_modules(); | |
print_callstack(); | |
print_callstack_default(); | |
} | |
void init_crash_handler(void(* log_)(char const * line_)) | |
{ | |
__log = log_; | |
log("[%s]", __func__); | |
__prev_signal_handler = signal(SIGSEGV, signal_handler); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment