Android 符号表

介绍Android符号表的基础概念,以及如何找到符号表并上传。

一、什么是符号表

在Android平台上,符号表用于将混淆过的代码进行还原,其中Java代码的符号化文件是mapping文件,C/C++代码的符号化文件是SO文件。

1. mapping文件

mapping文件可用于对混淆后的Java Crash堆栈进行还原。

  • 原始堆栈

    java.lang.NullPointerException
    	at com.aliyun.emas.android.apm.CrashActivity$o.a(CrashActivity.java:1)
    	at com.aliyun.emas.android.apm.CrashActivity$f.onClick(CrashActivity.java:1)
    	at android.view.View.performClick(View.java:7751)
    	at android.view.View.performClickInternal(View.java:7724)
    	at android.view.View.access$3700(View.java:858)
    	at android.view.View$PerformClick.run(View.java:29336)
    	at android.os.Handler.handleCallback(Handler.java:938)
    	at android.os.Handler.dispatchMessage(Handler.java:99)
    	at android.os.Looper.loopOnce(Looper.java:211)
    	at android.os.Looper.loop(Looper.java:300)
    	at android.app.ActivityThread.main(ActivityThread.java:8285)
    	at java.lang.reflect.Method.invoke(Native Method)
    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1074)
  • 还原堆栈

    java.lang.NullPointerException
    	at com.aliyun.emas.android.apm.CrashActivity$JavaCrash.throwException(CrashActivity.java:281)
    	at com.aliyun.emas.android.apm.CrashActivity$1.onClick(CrashActivity.java:54)
    	at android.view.View.performClick(View.java:7778)
    	at android.view.View.performClickInternal(View.java:7755)
    	at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
    	at android.view.View$PerformClick.run(View.java:30769)
    	at android.os.Handler.handleCallback(Handler.java:1013)
    	at android.os.Handler.dispatchMessage(Handler.java:101)
    	at android.os.Looper.loopOnce(Looper.java:226)
    	at android.os.Looper.loop(Looper.java:328)
    	at android.app.ActivityThread.main(ActivityThread.java:9179)
    	at java.lang.reflect.Method.invoke(Native Method)
    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:594)
    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
    Back traces end.

2. SO符号表

SO符号表是用来存储源代码中符号信息的数据结构,符号表元素如下所示:

<起始地址> <结束地址> <函数> [<文件名:行号>]

SO符号表可用于对Native Crash堆栈进行还原。

  • 原始堆栈

    #00 pc 000000000000f224  /data/app/~~z7k3Yi_OI3CSgGIlRwLTAA==/com.aliyun.ha.test_8-kjF3YBAA72Ed6Q0gg9U7fQ==/lib/arm64/libnativecrash.so (_Z4testv+20)
    #01 pc 000000000000f200  /data/app/~~z7k3Yi_OI3CSgGIlRwLTAA==/com.aliyun.ha.test_8-kjF3YBAA72Ed6Q0gg9U7fQ==/lib/arm64/libnativecrash.so (Java_com_example_nativecrash_NativeLib_mockSigSegv+20)
    #02 pc 0000000000022244  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148)
    #03 pc 0000000000018964  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+548)
    #04 pc 00000000000845a8  /apex/com.android.art/lib64/libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+188)
    #05 pc 00000000001fd680  /apex/com.android.art/lib64/libart.so (_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_11ShadowFrameEtPNS_6JValueE+400)
    #06 pc 00000000001f84f4  /apex/com.android.art/lib64/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+804)
    #07 pc 0000000000595d50  /apex/com.android.art/lib64/libart.so (MterpInvokeVirtual+1168)
    #08 pc 0000000000003814  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_virtual+20)
  • 还原堆栈

    #00 pc 0xf224 libnativecrash.so (/Users/liubaowen/projects/temp/emas-android-appmonitor-demo/nativecrash/src/main/cpp/nativecrash.cpptest()
    #01 pc 0xf200 libnativecrash.so (/Users/liubaowen/projects/temp/emas-android-appmonitor-demo/nativecrash/src/main/cpp/nativecrash.cppJava_com_example_nativecrash_NativeLib_mockSigSegv+line:17)
    #02 pc 0x22244 libart.so (art_quick_generic_jni_trampoline+148)
    #03 pc 0x18964 libart.so (art_quick_invoke_stub+548)
    #04 pc 0x845a8 libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+188)
    #05 pc 0x1fd680 libart.so (_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_11ShadowFrameEtPNS_6JValueE+400)
    #06 pc 0x1f84f4 libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+804)
    #07 pc 0x595d50 libart.so (MterpInvokeVirtual+1168)
    #08 pc 0x3814 libart.so (mterp_op_invoke_virtual+20)

二、如何找到符号表

1. mapping文件位置

如果在:<project>/<app-module>/build.gradle中打开了混淆,则在编译完成后会生成mapping文件。

android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    ...
}

默认情况下,mapping文件位置在<project>/<app-module>/build/outputs/mapping/<build-type>/

image

2. SO符号表位置

Android平台中,Debug SO文件是指具有调试信息的SO文件,其中包含用户还原堆栈的符号信息。

  • CMake编译项目

    默认情况下,编译的SO文件在<project>/<sdk-module>/build/intermediates/cmake/<build-type>/obj/CPU架构/

    image

  • NDK编译项目

    默认情况下,编译的SO文件在<project>/<sdk-module>/build/intermediates/ndk/<build-type>/obj/CPU架构/

    image

三、如何上传符号表

详见 网页上传符号表

四、FAQ

详见 符号表 FAQ