summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2019-12-15 15:21:27 +0100
committerAndrei Karas <akaras@inbox.ru>2020-03-30 06:35:10 +0300
commit960d13887d7e1e4d14ae68d72163d639590673b5 (patch)
treefd70243851d9798172464e13c4f89d5b2c4f2a9b /src/common
parent19526df51126694542c518c6589e7979eedc61e2 (diff)
downloadhercules-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.c67
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
}