Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting stack trace on Android NDK

First of all: this question has already been asked a couple times, and some answers are useful, but none provide a working solution. I started by trying the code from this answer. Surprisingly, it does its thing, but there's a huge problem: the only way of calling this code I can think of is SIGSEGV handler, and it has its own stack - hence I can't get the actual stack of my crashed app just like that.

Then, I tried incorporating this answer. It's slightly better - it yields the first item of the stack (the method in which crash occurred). But that's in - no actual backtrace. So as soon as the crash occurs inside a 3rd-party library (or standard library), this information is meaningless.

How can I further improve the code and finally get the stack trace for my poor crashed app?

P. S. Tested on Android 4.0.3 and Android 5.0, so far the behavior is the same. I want to support at least 5.0 and the recent previous versions like 4.3-4.4.

like image 559
Violet Giraffe Avatar asked Apr 09 '15 14:04

Violet Giraffe


1 Answers

Did you try the coffeecatch library?

It is a JNI signal catcher that allows to turn SIGSEGV(+) signals into the java exceptions with mixed jni/java backtrace. It works up to API-19, but I had no chance to test it on API>19 yet. It provides program addresses which could be passed to addr2line in order to get the final references to a sources.

Code template:

#include "coffeejni.h"
#include "coffeecatch.h"

void   MyClass::foo(JNIEnv *env, int arg1, int arg2) {
    ....
    int  rc;
    COFFEE_TRY_JNI(env, rc = crashInside(arg1, arg2));
    ....
}

Example of the trace:

F/myapp   (24535): "DESIGN ERROR": thread=t1
F/myapp   (24535): java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282]
F/myapp   (24535):  at com.example.NativeSupport.nsc(Native Method)
F/myapp   (24535):  at com.example.NativeSupport.nsc_quiet(NativeSupport.java:328)
F/myapp   (24535):  at com.example.NativeSupport.loop(NativeSupport.java:287)
F/myapp   (24535):  at com.example.NativeSupport.access$2(NativeSupport.java:274)
F/myapp   (24535):  at com.example.NativeSupport$2.run(NativeSupport.java:124)
F/myapp   (24535):  at java.lang.Thread.run(Thread.java:856)
F/myapp   (24535): Caused by: java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282]
F/myapp   (24535):  at system.lib.libc_so.0x18282(Native Method)
F/myapp   (24535):  at system.lib.libc_so.0xdc04(abort:0x4:0)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0xf147(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x12d1b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x1347b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13969(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13ab3(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x17a9b(Native Method)
F/myapp   (24535):  at system.lib.libdvm_so.0x1f4b0(dvmPlatformInvoke:0x70:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x4dfa5(dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*):0x164:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x28920(Native Method)
F/myapp   (24535):  at system.lib.libdvm_so.0x2d0b0(dvmInterpret(Thread*, Method const*, JValue*):0xb4:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x5f599(dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list):0x110:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x5f5c3(dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...):0x14:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x549eb(Native Method)
F/myapp   (24535):  at system.lib.libc_so.0x12dd0(__thread_entry:0x30:0)
F/myapp   (24535):  at system.lib.libc_so.0x12534(pthread_create:0xac:0)

Native (jni) part of the stack trace was:

F/myapp   (24535):  at data.data.example.lib.libexample_so.0xf147(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x12d1b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x1347b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13969(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13ab3(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x17a9b(Native Method)

And finally get a humanoid-readable backtrace:

cd android-ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin
./arm-linux-androideabi-addr2line -e /home/joe/myproj/obj/local/armeabi-v7a/libexample.so 0xf147 0x12d1b 0x1347b 0x13969 0x13ab3 0x17a9b
like image 110
Fvwm Avatar answered Oct 11 '22 07:10

Fvwm