From 960d13887d7e1e4d14ae68d72163d639590673b5 Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 15 Dec 2019 15:21:27 +0100 Subject: Add helpers to find the correct executable path for libbacktrace Signed-off-by: Haru --- src/common/nullpo.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/nullpo.c b/src/common/nullpo.c index d28d7ee4b..11741745c 100644 --- a/src/common/nullpo.c +++ b/src/common/nullpo.c @@ -23,14 +23,28 @@ #include "nullpo.h" #include "common/showmsg.h" +#include "common/strlib.h" #include #include #include #include -#ifdef HAVE_LIBBACKTRACE +#if defined(HAVE_LIBBACKTRACE) #include "libbacktrace/backtrace.h" #include "libbacktrace/backtrace-supported.h" +# if defined(WIN32) +# include +# elif defined(__sun) +# include +# elif defined(__linux) || defined(__linux__) +# include +# include +# elif defined(__APPLE__) && defined(__MACH__) +# include +# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) +# include +# include +# endif #elif defined(HAVE_EXECINFO) #include #endif // HAVE_LIBBACKTRACE @@ -40,6 +54,8 @@ static struct nullpo_interface nullpo_s; struct nullpo_interface *nullpo; #ifdef HAVE_LIBBACKTRACE +static char executable_path[PATH_MAX]; + static void nullpo_error_callback(void *data, const char *msg, int errnum) { ShowError("Error: %s (%d)", msg, errnum); @@ -61,6 +77,50 @@ static void nullpo_backtrace_print(struct backtrace_state *state) backtrace_full(state, 0, nullpo_print_callback, nullpo_error_callback, state); } +static bool nullpo_backtrace_get_executable_path(char *buf, size_t length) +{ +#if defined(WIN32) + char *exe_path = NULL; + if (_get_pgmptr(&exe_path) != 0) + return false; + safestrncpy(buf, exe_path, length); + return true; +#elif defined(__sun) + if (length < MAX_PATH) + return false; + if (realpath(getexecname(), buf) == NULL) + return false; + buf[length - 1] = '\0'; + return true; +#elif defined(__linux) || defined(__linux__) + ssize_t len = readlink("/proc/self/exe", buf, length); + if (len <= 0 || len == length) + return false; + buf[len] = '\0'; + return true; +#elif defined(__APPLE__) && defined(__MACH__) + uint32_t len = (uint32_t)length; + if (_NSGetExecutablePath(buf, &len) != 0) + return false; // buffer too small (!) + // resolve symlinks, ., .. if possible + char *canonical_path = realpath(buf, NULL); + if (canonical_path != NULL) { + safestrncpy(buf, canonical_path, length); + free(canonical_path); + } + return true; +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + if (sysctl(mib, 4, buf, &length, NULL, 0) != 0) + return false; + return true; +#endif + return false; +} #endif // HAVE_LIBBACKTRACE /** @@ -99,7 +159,10 @@ static void assert_report(const char *file, int line, const char *func, const ch static void nullpo_init(void) { #ifdef HAVE_LIBBACKTRACE - nullpo->backtrace_state = backtrace_create_state("hercules", BACKTRACE_SUPPORTS_THREADS, nullpo_error_callback, NULL); + if (!nullpo_backtrace_get_executable_path(executable_path, sizeof executable_path)) { + safestrncpy(executable_path, "hercules", sizeof executable_path); + } + nullpo->backtrace_state = backtrace_create_state(executable_path, BACKTRACE_SUPPORTS_THREADS, nullpo_error_callback, NULL); #endif } -- cgit v1.2.3-60-g2f50