diff options
author | Haru <haru@dotalux.com> | 2019-12-15 15:21:27 +0100 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2020-03-30 06:35:10 +0300 |
commit | 960d13887d7e1e4d14ae68d72163d639590673b5 (patch) | |
tree | fd70243851d9798172464e13c4f89d5b2c4f2a9b /src/common | |
parent | 19526df51126694542c518c6589e7979eedc61e2 (diff) | |
download | hercules-960d13887d7e1e4d14ae68d72163d639590673b5.tar.gz hercules-960d13887d7e1e4d14ae68d72163d639590673b5.tar.bz2 hercules-960d13887d7e1e4d14ae68d72163d639590673b5.tar.xz hercules-960d13887d7e1e4d14ae68d72163d639590673b5.zip |
Add helpers to find the correct executable path for libbacktrace
Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/nullpo.c | 67 |
1 files changed, 65 insertions, 2 deletions
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 <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> -#ifdef HAVE_LIBBACKTRACE +#if defined(HAVE_LIBBACKTRACE) #include "libbacktrace/backtrace.h" #include "libbacktrace/backtrace-supported.h" +# if defined(WIN32) +# include <windows.h> +# elif defined(__sun) +# include <limits.h> +# elif defined(__linux) || defined(__linux__) +# include <unistd.h> +# include <limits.h> +# elif defined(__APPLE__) && defined(__MACH__) +# include <mach-o/dyld.h> +# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) +# include <sys/types.h> +# include <sys/sysctl.h> +# endif #elif defined(HAVE_EXECINFO) #include <execinfo.h> #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 } |