aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gn/BUILD.gn10
-rw-r--r--tools/ok.cpp67
2 files changed, 66 insertions, 11 deletions
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 7be1617d23..b2013c571b 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -387,7 +387,10 @@ config("debug_symbols") {
# It's annoying to wait for full debug symbols to push over
# to Android devices. -gline-tables-only is a lot slimmer.
if (is_android) {
- cflags = [ "-gline-tables-only" ]
+ cflags = [
+ "-gline-tables-only",
+ "-funwind-tables", # Helps make in-process backtraces fuller.
+ ]
} else if (is_win) {
cflags = [ "/Zi" ]
ldflags = [ "/DEBUG" ]
@@ -434,7 +437,10 @@ config("release") {
config("executable") {
if (is_android) {
- ldflags = [ "-pie" ]
+ ldflags = [
+ "-pie",
+ "-rdynamic",
+ ]
} else if (is_mac) {
ldflags = [ "-Wl,-rpath,@loader_path/." ]
} else if (is_linux) {
diff --git a/tools/ok.cpp b/tools/ok.cpp
index ca99f33a16..eb33439248 100644
--- a/tools/ok.cpp
+++ b/tools/ok.cpp
@@ -24,11 +24,63 @@
static thread_local const char* tls_currently_running = "";
-#if __has_include(<execinfo.h>) && __has_include(<fcntl.h>) && __has_include(<signal.h>)
+#if __has_include(<execinfo.h>)
#include <execinfo.h>
+
+ #define CAN_BACKTRACE
+ static void backtrace(int fd) {
+ void* stack[128];
+ int frames = backtrace(stack, sizeof(stack)/sizeof(*stack));
+ backtrace_symbols_fd(stack, frames, fd);
+ }
+
+#elif __has_include(<dlfcn.h>) && __has_include(<unwind.h>)
+ #include <cxxabi.h>
+ #include <dlfcn.h>
+ #include <unwind.h>
+
+ #define CAN_BACKTRACE
+ static void backtrace(int fd) {
+ FILE* file = fdopen(fd, "a");
+ _Unwind_Backtrace([](_Unwind_Context* ctx, void* arg) {
+ auto file = (FILE*)arg;
+ if (auto ip = (void*)_Unwind_GetIP(ctx)) {
+ const char* name = "[unknown]";
+ void* addr = nullptr;
+ Dl_info info;
+ if (dladdr(ip, &info) && info.dli_sname && info.dli_saddr) {
+ name = info.dli_sname;
+ addr = info.dli_saddr;
+ }
+
+ int ok;
+ char* demangled = abi::__cxa_demangle(name, nullptr,0, &ok);
+ if (ok == 0 && demangled) {
+ name = demangled;
+ }
+
+ fprintf(file, "\t%p %s+%zu\n", ip, name, (size_t)ip - (size_t)addr);
+ free(demangled);
+ }
+ return _URC_NO_REASON;
+ }, file);
+ fflush(file);
+ }
+#endif
+
+#if defined(CAN_BACKTRACE) && __has_include(<fcntl.h>) && __has_include(<signal.h>)
#include <fcntl.h>
#include <signal.h>
+ #if defined(__ANDROID_API__) && __ANDROID_API__ < 24
+ // TODO: do all locking manually with fcntl() so we can lock on older Android NDK APIs?
+ static void lock_fd(int) {}
+ static void unlock_fd(int) {}
+ #else
+ static void lock_fd(int fd) { lockf(fd, F_LOCK, 0); }
+ static void unlock_fd(int fd) { lockf(fd, F_ULOCK, 0); }
+ #endif
+
static int log_fd = 2/*stderr*/;
static void log(const char* msg) {
@@ -39,7 +91,7 @@ static thread_local const char* tls_currently_running = "";
static void (*original_handlers[32])(int);
for (int sig : std::vector<int>{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV }) {
original_handlers[sig] = signal(sig, [](int sig) {
- lockf(log_fd, F_LOCK, 0);
+ lock_fd(log_fd);
log("\ncaught signal ");
switch (sig) {
#define CASE(s) case s: log(#s); break
@@ -53,11 +105,8 @@ static thread_local const char* tls_currently_running = "";
log(" while running '");
log(tls_currently_running);
log("'\n");
-
- void* stack[128];
- int frames = backtrace(stack, sizeof(stack)/sizeof(*stack));
- backtrace_symbols_fd(stack, frames, log_fd);
- lockf(log_fd, F_ULOCK, 0);
+ backtrace(log_fd);
+ unlock_fd(log_fd);
signal(sig, original_handlers[sig]);
raise(sig);
@@ -77,13 +126,13 @@ static thread_local const char* tls_currently_running = "";
}
void ok_log(const char* msg) {
- lockf(log_fd, F_LOCK, 0);
+ lock_fd(log_fd);
log("[");
log(tls_currently_running);
log("]\t");
log(msg);
log("\n");
- lockf(log_fd, F_ULOCK, 0);
+ unlock_fd(log_fd);
}
#else