diff options
-rw-r--r-- | gn/BUILD.gn | 10 | ||||
-rw-r--r-- | tools/ok.cpp | 67 |
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 |