From da6b2e2fd79c9aac12127b2c2f512e9555fdd06d Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 23 Apr 2014 14:57:32 -0700 Subject: [PATCH] Improve liblog's fatal logging. This makes LOG_ALWAYS_FATAL and LOG_ALWAYS_FATAL_IF as good as regular assert(3). Change-Id: I0666684d30cae7baf23c64b33d35c1e43f81acf0 --- debuggerd/crasher.c | 49 +++++++++++++++++++++++----------------- include/android/log.h | 6 ++--- liblog/logd_write.c | 8 ++++++- liblog/logd_write_kern.c | 8 ++++++- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c index 5a2bc3c73..9946faa59 100644 --- a/debuggerd/crasher.c +++ b/debuggerd/crasher.c @@ -1,20 +1,17 @@ - -//#include - -#include +#include +#include +#include +#include +#include #include #include #include -#include -#include - -#include #include -#include #include +#include +#include -#include - +#include #include extern const char* __progname; @@ -23,8 +20,8 @@ void crash1(void); void crashnostack(void); static int do_action(const char* arg); -static void maybeabort() { - if(time(0) != 42) { +static void maybe_abort() { + if (time(0) != 42) { abort(); } } @@ -119,20 +116,28 @@ static int do_action(const char* arg) if (!strncmp(arg, "thread-", strlen("thread-"))) { return do_action_on_thread(arg + strlen("thread-")); - } else if (!strcmp(arg,"smash-stack")) { + } else if (!strcmp(arg, "smash-stack")) { return smash_stack(42); - } else if (!strcmp(arg,"stack-overflow")) { + } else if (!strcmp(arg, "stack-overflow")) { overflow_stack(NULL); - } else if (!strcmp(arg,"nostack")) { + } else if (!strcmp(arg, "nostack")) { crashnostack(); - } else if (!strcmp(arg,"ctest")) { + } else if (!strcmp(arg, "ctest")) { return ctest(); - } else if (!strcmp(arg,"exit")) { + } else if (!strcmp(arg, "exit")) { exit(1); - } else if (!strcmp(arg,"crash")) { + } else if (!strcmp(arg, "crash")) { return crash(42); - } else if (!strcmp(arg,"abort")) { - maybeabort(); + } else if (!strcmp(arg, "abort")) { + maybe_abort(); + } else if (!strcmp(arg, "assert")) { + __assert("some_file.c", 123, "false"); + } else if (!strcmp(arg, "assert2")) { + __assert2("some_file.c", 123, "some_function", "false"); + } else if (!strcmp(arg, "LOG_ALWAYS_FATAL")) { + LOG_ALWAYS_FATAL("hello %s", "world"); + } else if (!strcmp(arg, "LOG_ALWAYS_FATAL_IF")) { + LOG_ALWAYS_FATAL_IF(true, "hello %s", "world"); } else if (!strcmp(arg, "heap-usage")) { abuse_heap(); } @@ -148,6 +153,8 @@ static int do_action(const char* arg) fprintf(stderr, " exit call exit(1)\n"); fprintf(stderr, " crash cause a SIGSEGV\n"); fprintf(stderr, " abort call abort()\n"); + fprintf(stderr, " assert call assert() without a function\n"); + fprintf(stderr, " assert2 call assert() with a function\n"); fprintf(stderr, "prefix any of the above with 'thread-' to not run\n"); fprintf(stderr, "on the process' main thread.\n"); return EXIT_SUCCESS; diff --git a/include/android/log.h b/include/android/log.h index 0ea4c298b..f5b1900ae 100644 --- a/include/android/log.h +++ b/include/android/log.h @@ -110,11 +110,11 @@ int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap); /* - * Log an assertion failure and SIGTRAP the process to have a chance - * to inspect it, if a debugger is attached. This uses the FATAL priority. + * Log an assertion failure and abort the process to have a chance + * to inspect it if a debugger is attached. This uses the FATAL priority. */ void __android_log_assert(const char *cond, const char *tag, - const char *fmt, ...) + const char *fmt, ...) #if defined(__GNUC__) __attribute__ ((noreturn)) __attribute__ ((format(printf, 3, 4))) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 94722d3a4..48531d571 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -407,9 +407,15 @@ void __android_log_assert(const char *cond, const char *tag, strcpy(buf, "Unspecified assertion failed"); } +#if __BIONIC__ + // Ensure debuggerd gets to see what went wrong by keeping the C library in the loop. + extern __noreturn void __android_fatal(const char* tag, const char* format, ...) __printflike(2, 3); + __android_fatal(tag ? tag : "", "%s", buf); +#else __android_log_write(ANDROID_LOG_FATAL, tag, buf); - __builtin_trap(); /* trap so we have a chance to debug the situation */ +#endif + /* NOTREACHED */ } int __android_log_bwrite(int32_t tag, const void *payload, size_t len) diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c index c29c28f2d..8c707adfb 100644 --- a/liblog/logd_write_kern.c +++ b/liblog/logd_write_kern.c @@ -272,9 +272,15 @@ void __android_log_assert(const char *cond, const char *tag, strcpy(buf, "Unspecified assertion failed"); } +#if __BIONIC__ + // Ensure debuggerd gets to see what went wrong by keeping the C library in the loop. + extern __noreturn void __android_fatal(const char* tag, const char* format, ...) __printflike(2, 3); + __android_fatal(tag ? tag : "", "%s", buf); +#else __android_log_write(ANDROID_LOG_FATAL, tag, buf); - __builtin_trap(); /* trap so we have a chance to debug the situation */ +#endif + /* NOTREACHED */ } int __android_log_bwrite(int32_t tag, const void *payload, size_t len)