How to Use Addr2Line in Android

How to use addr2line in Android

Let's say that logcat show you the following crash log (this is from one of my projects):

I/DEBUG   (   31): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 31): Build fingerprint: 'generic/sdk/generic:2.3/GRH55/79397:eng/test-keys'
I/DEBUG ( 31): pid: 378, tid: 386 >>> com.example.gltest <<<
I/DEBUG ( 31): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
I/DEBUG ( 31): r0 001dbdc0 r1 00000001 r2 00000000 r3 00000000
I/DEBUG ( 31): r4 00000000 r5 40a40000 r6 4051a480 r7 42ddbee8
I/DEBUG ( 31): r8 43661b24 r9 42ddbed0 10 42ddbebc fp 41e462d8
I/DEBUG ( 31): ip 00000001 sp 436619d0 lr 83a12f5d pc 8383deb4 cpsr 20000010
I/DEBUG ( 31): #00 pc 0003deb4 /data/data/com.example.gltest/lib/libnativemaprender.so
I/DEBUG ( 31): #01 pc 00039b76 /data/data/com.example.gltest/lib/libnativemaprender.so
I/DEBUG ( 31): #02 pc 00017d34 /system/lib/libdvm.so

Look at the last 3 lines; this is your callstack. 'pc' is the program counter, and the pc for stack frame #00 gives you the address where the crash occurred. This is the number to pass to addr2line.

I'm using NDK r5, so the executable I'm using is located at $NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin; make sure that is in your $PATH. The command to use looks like

arm-linux-androideabi-addr2line -C -f -e obj/local/armeabi/libXXX.so <address>

Or, for the case above:

arm-linux-androideabi-addr2line -C -f -e obj/local/armeabi/libnativemaprender.so 0003deb4

Which gives you the location of the crash.

Note:

  • The -C flag is to demangle C++ code
  • Use the .so file under
    obj/local/armeabi, since this is the
    non-stripped version

Also, when using NDK r5 with a 2.3 AVD, it is actually possible to debug multithreaded code.

How do I use addr2line for Android?

Use ndk-stack instead. Save your native log crash in a file, says log.txt and then use

$NDK_HOME/ndk-stack -sym $PROJECT_HOME/obj/local/armeabi -dump log.txt

of course, your native library has to be compiled with the debug symbols.

From the doc:

'ndk-stack' is a simple tool that allows you to filter stack traces as
they appear in the output of 'adb logcat' and replace any address inside a
shared library with the corresponding "source-file : line-number" values.

Addr2line 64bit tool

Found the required utility for 64 bits.
The 32-bit utility was located here

C: \ Program Files \ Unity \ Hub \ Editor \ 2019.2.19f1 \ Editor \ Data \ PlaybackEngines \ AndroidPlayer \ NDK \ toolchains \ arm-linux-androideabi-4.9 \ prebuilt \ windows-x86_64 \ bin \ arm-linux-androideabi- addr2line.exe

And 64 bits are here

C: \ Program Files \ Unity \ Hub \ Editor \ 2019.2.19f1 \ Editor \ Data \ PlaybackEngines \ AndroidPlayer \ NDK \ toolchains \ aarch64-linux-android-4.9 \ prebuilt \ windows-x86_64 \ bin \ aarch64-linux-android- addr2line.exe

And it's called a little differently - aarch64-linux-android-addr2line. Despite the fact that the name of the utility does not contain the word arm, it successfully decrypts stacktraces from under arm64-v8 and normally perceives characters for arm64-v8

The rest of the commands are the same, i.e.

./aarch64-linux-android-addr2line -f -C -e "C: \ Program Files \ Unity \ Hub \ Editor \ 2019.2.19f1 \ Editor \ Data \ PlaybackEngines \ AndroidPlayer \ NDK \ toolchains \ arm-linux-androideabi- 4.9 \ prebuilt \ windows-x86_64 \ bin \ arm64-v8a \ libunity.sym.so "00000000001f6f34

Returns normal stack trace for memory address 00000000001f6f34

arm-eabi-addr2line don't show line number

Do you have debugging symbols in your .so? You should also disable optimization (-O0) and inline functions (-fno-inline)

frida - How to translate native backtrace to use with addr2line tool

Below steps (e.g. libc.so)

  1. Get library base address:

0xac0ad000 <- Module.findBaseAddress("libc.so")


  1. Get backtrace

Thread.backtrace(thz.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n
");

Sample output:

0xac151ed7 libc.so!fopen64+0x2e

3.Substract baseAddr to get PC value

#pc 0x000a4ed7 <- 0xac151ed7 - 0xac0ad000


  1. Addr2line with PC value

$ addr2line -f -C -i -e
symbols/apex/com.android.runtime/lib/bionic/libc.so 0x000a4ed7

open(char const*, int pass_object_size1, unsigned short)

bionic/libc/include/bits/fortify/fcntl.h:74 fopen

bionic/libc/stdio/stdio.cpp:256

How to get Crash Point in Java code

You can't get the stack trace for code written in the Java programming language out of a native stack trace in the Dalvik VM, for the simple reason that Dalvik uses different pieces of memory for the native and managed stacks. (I believe it's possible to get it from Art crashes, because Art uses a shared stack, but can't say for certain.)

The fault address suggests a null pointer dereference, and the call through jniGetFDFromFileDescriptor() indicates file activity. You can see the source code for that method here. I would guess it's calling GetIntField on a null object, which would match with your suspicions.

Enabling CheckJNI may help -- if the JNI checker spots a problem, it will usually dump the current thread's stack trace to the log file before killing the VM.

How do I get android NDK detail crash reports?

Instead of the Run tab, look at the Logcat. Don't set the filter to your app only. There is a good chance that you will see a stack trace, like

I/DEBUG   (   31): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 31): Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'
I/DEBUG ( 31): pid: 351, tid: 351 >>> /data/local/ndk-tests/crasher <<<
I/DEBUG ( 31): signal 11 (SIGSEGV), fault addr 0d9f00d8
I/DEBUG ( 31): r0 0000af88 r1 0000a008 r2 baadf00d r3 0d9f00d8
I/DEBUG ( 31): r4 00000004 r5 0000a008 r6 0000af88 r7 00013c44
I/DEBUG ( 31): r8 00000000 r9 00000000 10 00000000 fp 00000000
I/DEBUG ( 31): ip 0000959c sp be956cc8 lr 00008403 pc 0000841e cpsr 60000030
I/DEBUG ( 31): #00 pc 0000841e /data/local/ndk-tests/crasher
I/DEBUG ( 31): #01 pc 000083fe /data/local/ndk-tests/crasher
I/DEBUG ( 31): #02 pc 000083f6 /data/local/ndk-tests/crasher
I/DEBUG ( 31): #03 pc 000191ac /system/lib/libc.so
I/DEBUG ( 31): #04 pc 000083ea /data/local/ndk-tests/crasher
I/DEBUG ( 31): #05 pc 00008458 /data/local/ndk-tests/crasher
I/DEBUG ( 31): #06 pc 0000d362 /system/lib/libc.so
I/DEBUG ( 31):

Android NDK includes a command ndk-stack that can help match the addresses with actual source files of your code, which is based on the addr2line utility in NDK toolchain.

Further instructions for understanding the stack trace: https://developer.android.com/studio/debug/stacktraces

From comments:

You may find the 'unstripped' libraries under app/build/intermediates/transforms/mergeJniLibs

How can I add a '.so' library in my android project

after making your native c code and header file browse to the root directory of your project and run ndk-build command.That will generate the .so file and then place it inside your project/libs folder



Related Topics



Leave a reply



Submit