Automatically dump stack traces in dvmAbort on the host.
Before:
E(25569) VM aborting (dalvikvm)
After:
E( 9806) VM aborting (dalvikvm)
W( 9806) Obtained 7 stack frames. (dalvikvm)
W( 9806) #0 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/../lib/libdvm.so(dvmPrintNativeBackTrace+0x3f) [0xf7678f2f] (dalvikvm)
W( 9806) #1 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/../lib/libdvm.so(dvmAbort+0x52) [0xf7679072] (dalvikvm)
W( 9806) #2 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/../lib/libdvm.so(dvmStartup+0x67f) [0xf767a45f] (dalvikvm)
W( 9806) #3 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/../lib/libdvm.so(JNI_CreateJavaVM+0x1ee) [0xf768152e] (dalvikvm)
W( 9806) #4 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/dalvikvm() [0x8048ae3] (dalvikvm)
W( 9806) #5 /lib32/libc.so.6(__libc_start_main+0xe6) [0xf6ed5bd6] (dalvikvm)
W( 9806) #6 /usr/local/google/home/enh/dd4/out/host/linux-x86/bin/dalvikvm() [0x8048761] (dalvikvm)
This makes continuous build crashes more directly useful, and saves having to
switch to the device/break out gdb when doing simple debugging.
Bug: 4176271
Change-Id: I49b40fd56e6aa89d1ddc7c7f299314761456fc28
diff --git a/vm/Init.c b/vm/Init.c
index be63dab..ae4e175 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -1709,6 +1709,41 @@
return result;
}
+#ifdef __GLIBC__
+#include <execinfo.h>
+/*
+ * glibc-only stack dump function. Requires link with "--export-dynamic".
+ *
+ * TODO: move this into libs/cutils and make it work for all platforms.
+ */
+void dvmPrintNativeBackTrace(void)
+{
+ size_t MAX_STACK_FRAMES = 64;
+ void* stackFrames[MAX_STACK_FRAMES];
+ size_t frameCount = backtrace(stackFrames, MAX_STACK_FRAMES);
+
+ /*
+ * TODO: in practice, we may find that we should use backtrace_symbols_fd
+ * to avoid allocation, rather than use our own custom formatting.
+ */
+ char** strings = backtrace_symbols(stackFrames, frameCount);
+ if (strings == NULL) {
+ LOGE("backtrace_symbols failed: %s", strerror(errno));
+ return;
+ }
+
+ size_t i;
+ for (i = 0; i < frameCount; ++i) {
+ LOGW("#%d %s", i, strings[i]);
+ }
+ free(strings);
+}
+#else
+void dvmPrintNativeBackTrace(void) {
+ /* Hopefully, you're on an Android device and debuggerd will do this. */
+}
+#endif
+
/*
* Abort the VM. We get here on fatal errors. Try very hard not to use
* this; whenever possible, return an error to somebody responsible.
@@ -1724,6 +1759,12 @@
(*gDvm.abortHook)();
/*
+ * On the device, debuggerd will give us a stack trace.
+ * On the host, we have to help ourselves.
+ */
+ dvmPrintNativeBackTrace();
+
+ /*
* If we call abort(), all threads in the process receives a SIBABRT.
* debuggerd dumps the stack trace of the main thread, whether or not
* that was the thread that failed.
diff --git a/vm/Misc.h b/vm/Misc.h
index 4dc983e..c1c3d47 100644
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -256,6 +256,7 @@
* it undecorated.
*/
void dvmAbort(void);
+void dvmPrintNativeBackTrace(void);
#if (!HAVE_STRLCPY)
/* Implementation of strlcpy() for platforms that don't already have it. */
diff --git a/vm/Thread.c b/vm/Thread.c
index b347834..a003481 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -2346,36 +2346,6 @@
unlockThreadSuspendCount();
}
-
-#ifdef HAVE_GLIBC
-# define NUM_FRAMES 20
-# include <execinfo.h>
-/*
- * glibc-only stack dump function. Requires link with "--export-dynamic".
- *
- * TODO: move this into libs/cutils and make it work for all platforms.
- */
-static void printBackTrace(void)
-{
- void* array[NUM_FRAMES];
- size_t size;
- char** strings;
- size_t i;
-
- size = backtrace(array, NUM_FRAMES);
- strings = backtrace_symbols(array, size);
-
- LOGW("Obtained %zd stack frames.\n", size);
-
- for (i = 0; i < size; i++)
- LOGW("%s\n", strings[i]);
-
- free(strings);
-}
-#else
-static void printBackTrace(void) {}
-#endif
-
/*
* Dump the state of the current thread and that of another thread that
* we think is wedged.
@@ -2383,7 +2353,7 @@
static void dumpWedgedThread(Thread* thread)
{
dvmDumpThread(dvmThreadSelf(), false);
- printBackTrace();
+ dvmPrintNativeBackTrace();
// dumping a running thread is risky, but could be useful
dvmDumpThread(thread, true);