summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
}