diff --git a/src/trap.c b/src/trap.c index 0184f1f8..1e92497d 100644 --- a/src/trap.c +++ b/src/trap.c @@ -30,6 +30,7 @@ char tvh_binshasum[20]; #include #include #include +#include #if ENABLE_EXECINFO #include #endif @@ -49,6 +50,7 @@ char tvh_binshasum[20]; static char line1[200]; static char tmpbuf[1024]; static char libs[1024]; +static char self[PATH_MAX]; static void sappend(char *buf, size_t l, const char *fmt, ...) @@ -62,10 +64,76 @@ sappend(char *buf, size_t l, const char *fmt, ...) +/** + * + */ +static int +add2lineresolve(const char *binary, void *addr, char *buf0, size_t buflen) +{ + char *buf = buf0; + int fd[2], r, f; + const char *argv[5]; + pid_t p; + char addrstr[30], *cp; + + argv[0] = "addr2line"; + argv[1] = "-e"; + argv[2] = binary; + argv[3] = addrstr; + argv[4] = NULL; + + snprintf(addrstr, sizeof(addrstr), "%p", (void *)((intptr_t)addr-1)); + + if(pipe(fd) == -1) + return -1; + + if((p = fork()) == -1) + return -1; + + if(p == 0) { + close(0); + close(2); + close(fd[0]); + dup2(fd[1], 1); + close(fd[1]); + if((f = open("/dev/null", O_RDWR)) == -1) + exit(1); + + dup2(f, 0); + dup2(f, 2); + close(f); + + execve("/usr/bin/addr2line", (char *const *) argv, environ); + exit(2); + } + + close(fd[1]); + *buf = 0; + while(buflen > 1) { + r = read(fd[0], buf, buflen); + if(r < 1) + break; + + buf += r; + buflen -= r; + *buf = 0; + cp = strchr(buf0, '\n'); + if(cp != NULL) { + *cp = 0; + break; + } + } + close(fd[0]); + return 0; +} + + + static void traphandler(int sig, siginfo_t *si, void *UC) { ucontext_t *uc = UC; + char buf[200]; #if ENABLE_EXECINFO static void *frames[MAXFRAMES]; int nframes = backtrace(frames, MAXFRAMES); @@ -122,6 +190,11 @@ traphandler(int sig, siginfo_t *si, void *UC) continue; } + if(self[0] && !add2lineresolve(self, frames[i], buf, sizeof(buf))) { + tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p", buf, frames[i]); + continue; + } + if(dli.dli_fname != NULL && dli.dli_fbase != NULL) { tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p", dli.dli_fname, @@ -153,6 +226,7 @@ extern const char *htsversion_full; void trap_init(const char *ver) { + int r; uint8_t digest[20]; struct sigaction sa, old; char path[256]; @@ -160,6 +234,11 @@ trap_init(const char *ver) SHA_CTX binsum; int fd; + r = readlink("/proc/self/exe", self, sizeof(self) - 1); + if(r == -1) + self[0] = 0; + else + self[r] = 0; if((fd = open("/proc/self/exe", O_RDONLY)) != -1) { struct stat st;