ndk-stack

A ferramenta ndk-stack permite simbolizar stack traces de adb logcat ou um Tombstone em /data/tombstones/. Ela substitui qualquer endereço dentro de uma biblioteca compartilhada pelo <source-file>:<line-number> correspondente do seu código-fonte, facilitando a depuração.

Por exemplo, ela converte algo como:

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):

em uma saída mais legível:

********** Crash dump: **********
Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'
pid: 351, tid: 351  >>> /data/local/ndk-tests/crasher <<<
signal 11 (SIGSEGV), fault addr 0d9f00d8
Stack frame #00  pc 0000841e  /data/local/ndk-tests/crasher : Routine zoo in /tmp/foo/crasher/jni/zoo.c:13
Stack frame #01  pc 000083fe  /data/local/ndk-tests/crasher : Routine bar in /tmp/foo/crasher/jni/bar.c:5
Stack frame #02  pc 000083f6  /data/local/ndk-tests/crasher : Routine my_comparison in /tmp/foo/crasher/jni/foo.c:9
Stack frame #03  pc 000191ac  /system/lib/libc.so
Stack frame #04  pc 000083ea  /data/local/ndk-tests/crasher : Routine foo in /tmp/foo/crasher/jni/foo.c:14
Stack frame #05  pc 00008458  /data/local/ndk-tests/crasher : Routine main in /tmp/foo/crasher/jni/main.c:19
Stack frame #06  pc 0000d362  /system/lib/libc.so

Uso

Para usar ndk-stack, primeiro você precisa de um diretório que contenha versões sem remoção de conteúdo das bibliotecas compartilhadas do seu app. Se você usa ndk-build, essas bibliotecas compartilhadas sem remoção de conteúdo podem ser encontradas em $PROJECT_PATH/obj/local/<abi>, em que <abi> é a ABI do seu dispositivo.

Para um build do Plug-in do Android para Gradle (AGP), as bibliotecas sem remoção de conteúdo estarão em <project-path>/build/intermediates/cxx/<build-type>/<hash>/obj/<abi>, em que <project-path> é o diretório do projeto do AGP que contém o módulo que você está tentando simbolizar (por padrão, é app), <build-type> é o nome do tipo de build do CMake ou do ndk-build (como RelWithDebInfo, Release, Debug etc.). <hash> é arbitrário, e <abi> é a ABI do dispositivo.

Há duas formas de usar a ferramenta. Você pode inserir texto do logcat como entrada direta no programa. Por exemplo:

adb logcat | $NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi-v7a

Você também pode usar a opção -dump para especificar o logcat como um arquivo de entrada. Por exemplo:

adb logcat > /tmp/foo.txt
$NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi-v7a -dump foo.txt

Quando a análise da saída do logcat for iniciada, a ferramenta buscará uma linha de asteriscos inicial. Exemplo:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

Observação: ao copiar/colar traces, não se esqueça dessa linha. Caso contrário, ndk-stack não funcionará corretamente.

Mais informações

O Google Play usa ndk-stack para simbolizar stack traces para apps nativos no Google Play Console. Para saber como ativar esse recurso em seu app em um ambiente de produção, veja como incluir um arquivo de símbolos de depuração nativo para o app no Google Play Console.