【问题标题】:Android Firebase Crashlytics NDK backtraces are missing framesAndroid Firebase Crashlytics NDK 回溯缺少帧
【发布时间】:2020-09-13 11:03:24
【问题描述】:

当我使用 Fabric Crashlytics 时,问题就出现了,现在使用 Firebase Crashlytics 最新版本时它仍然存在。一切都是基于official NDK docs 实现的,并且每次构建后都会正确上传符号(cSYM)文件。我设法产生了一个故意的崩溃来比较墓碑和报告的本机崩溃回溯,结果如下:

报告的 Firebase 控制台崩溃:

崩溃保存的墓碑文件:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'samsung/klteduosxx/klte:5.0/LRX21T/G900FDXXU1BOJ1:user/release-keys'
Revision: '14'
ABI: 'arm'
pid: 652, tid: 1160, name: AsyncTask #5  >>> com.mnhaami.pasaj <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'stack corruption detected'
    r0 00000000  r1 00000488  r2 00000006  r3 00000000
    r4 656f3db8  r5 00000006  r6 00000016  r7 0000010c
    r8 656f3878  r9 00000000  sl 134eaf00  fp 13f14800
    ip 00000488  sp 656f37f8  lr b6eeefd5  pc b6f11b74  cpsr 600d0010
    d0  ffffffffffffffff  d1  ffffffffffffffff
    d2  ff816306ff836406  d3  ff795f04ff7e6206
    d4  ffff000000000000  d5  0000000000000003
    d6  ffff000000000000  d7  ffffffffffffffff
    d8  0000000000000000  d9  0000000000000000
    d10 0000000000000000  d11 0000000000000000
    d12 0000000000000000  d13 0000000000000000
    d14 0000000000000000  d15 0000000000000000
    d16 0000000000000000  d17 6e6f697470757272
    d18 ff916d0aff997208  d19 ff825f0aff896708
    d20 ff715613ff785a11  d21 ff6b520fff6b520f
    d22 ff6f5309ff6e530e  d23 ff775b07ff735609
    d24 0000000000000000  d25 0000000000000000
    d26 0002000100010001  d27 0002000200020002
    d28 0080008000800080  d29 0080008000800080
    d30 0800080008000800  d31 0800080008000800
    scr 2800001b

backtrace:
    #00 pc 00036b74  /system/lib/libc.so (tgkill+12)
    #01 pc 00013fd1  /system/lib/libc.so (pthread_kill+52)
    #02 pc 00014bef  /system/lib/libc.so (raise+10)
    #03 pc 00011531  /system/lib/libc.so (__libc_android_abort+36)
    #04 pc 0000fcbc  /system/lib/libc.so (abort+4)
    #05 pc 00012701  /system/lib/libc.so (__libc_fatal+16)
    #06 pc 000368fb  /system/lib/libc.so (__stack_chk_fail+6)

stack:
         656f37b8  00000001  
         656f37bc  00430000  
         656f37c0  00550000  
         656f37c4  00000000  
         656f37c8  00430000  
         656f37cc  b4e18218  
         656f37d0  00000000  
         656f37d4  2f94ff4a  /dev/ashmem/dalvik-main space (deleted)
         656f37d8  9866fb50  
         656f37dc  2f94ff4a  /dev/ashmem/dalvik-main space (deleted)
         656f37e0  656f3db8  [stack:1160]
         656f37e4  00000006  
         656f37e8  00000016  
         656f37ec  00000488  
         656f37f0  00000000  
         656f37f4  b6eeefcd  /system/lib/libc.so (pthread_kill+48)
    #00  656f37f8  656f3db0  [stack:1160]
         ........  ........
    #01  656f37f8  656f3db0  [stack:1160]
         656f37fc  00000006  
         656f3800  00000000  
         656f3804  656f3820  [stack:1160]
         656f3808  656f3898  [stack:1160]
         656f380c  b6eefbf3  /system/lib/libc.so (raise+14)
    #02  656f3810  656f381c  [stack:1160]
         656f3814  b6eec535  /system/lib/libc.so (__libc_android_abort+40)
    #03  656f3818  000000a8  
         656f381c  ffffffdf  
         656f3820  00000000  
         656f3824  8c93ac00  
         656f3828  ae907e40  
         656f382c  2f94ff4a  /dev/ashmem/dalvik-main space (deleted)
         656f3830  93bcd2fc  
         656f3834  b4bc0435  /system/lib/libart.so (art::CheckJNI::GetIntArrayRegion(_JNIEnv*, _jintArray*, int, int, int*))
         656f3838  b6f44e04  
         656f383c  b6eeacc0  /system/lib/libc.so (__bionic_clone)
    #04  656f3840  00000000  
         656f3844  b6eed705  /system/lib/libc.so (__fortify_chk_fail)
    #05  656f3848  b6f359a5  /system/lib/libc.so
         656f384c  656f385c  [stack:1160]
         656f3850  8f38e000  
         656f3854  b6f118ff  /system/lib/libc.so (__stack_chk_fail+10)
         656f3858  b6f359a5  /system/lib/libc.so
         656f385c  2f94ff4a  /dev/ashmem/dalvik-main space (deleted)
         656f3860  8f38e000  
         656f3864  00000000  

我的 gradle 配置如下:

项目build.gradle:

buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url "https://jitpack.io" }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:3.6.3"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
        classpath "com.google.gms:google-services:4.3.3"  // Google Services plugin
        classpath "com.google.firebase:perf-plugin:1.3.1"  // Performance Monitoring plugin
        classpath "com.google.firebase:firebase-crashlytics-gradle:2.1.1"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven {
            url 'https://jitpack.io'
        }
        flatDir {
            dirs 'libs'
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

应用模块build.gradle:

repositories {
    maven { url 'http://dl.bintray.com/piasy/maven' }
    mavenCentral()
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.firebase-perf'
android {
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }

    ....

    buildTypes {
        debug {
            ndk {
                abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
            }
            FirebasePerformance {
                instrumentationEnabled false
            }
        }
        release {
            minifyEnabled true
            useProguard = true
            proguardFile getDefaultProguardFile('proguard-android.txt')
            proguardFile 'proguard-rules.pro'

            ndk {
                abiFilters "armeabi-v7a", "arm64-v8a", "x86_64"
            }

            /* Add the firebaseCrashlytics extension (by default,
            * it's disabled to improve build speeds) and set
            * nativeSymbolUploadEnabled to true. */
            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

// Upload Crashlytics NDK symbols
tasks.whenTaskAdded { task -> if (task.name.startsWith('assemble') && task.name.endsWith("Release")) task.finalizedBy "uploadCrashlyticsSymbolFile" + task.name.substring('assemble'.length()) }

dependencies {
    implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')

    implementation platform('com.google.firebase:firebase-bom:25.2.1')
    implementation "com.google.firebase:firebase-crashlytics-ndk:17.0.0"
    implementation 'com.google.firebase:firebase-iid'
    implementation 'com.google.firebase:firebase-messaging'
    implementation 'com.google.firebase:firebase-appindexing'
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-perf'

    ...
}
apply plugin: 'com.google.gms.google-services'

Firebase 控制台报告了很多崩溃,就像我捕获的那样。其中没有一个具有适当的可用回溯。

感谢任何提示,本机报告目前在没有框架的情况下是无用的。

编辑:

我已经解决了基于Kevin's answer 的已剥离和未剥离的本机库目录,如下所示:

android {
    ...
    buildTypes {
        ...
        release {
            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
                applicationVariants.all { variant ->
                    firebaseCrashlytics {
                        strippedNativeLibsDir "build/intermediates/stripped_native_libs/${variant.name}/out/lib"
                        unstrippedNativeLibsDir "build/intermediates/ndkBuild/${variant.name}/obj/local"
                    }
                }
            }
        }
    }
}

并设法产生了一个崩溃,该崩溃具有一个通过我自己的本机库的调用堆栈,但问题仍然存在:

编辑 2:

按照 Kevin 的建议,我使用此命令调试符号文件上传问题(我使用 find /I 而不是 grep,因为我在 Windows 上):

gradlew app:assembleRelease --console=plain --debug | find /I "[com.google.firebase.crashlytics]"

结果证明使用implementation 'com.google.firebase:firebase-iid'implementation platform('com.google.firebase:firebase-bom:25.2.1') 是让我无法赎回的原因:) 因为显然Firebase 已经在com.google.firebase:firebase-messaging 本身内部使用了实例ID 依赖项。长话短说,仅使用此配置帮助我正确上传了我的符号:

android {
    ...
    buildTypes {
        ...
        release {
            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
            }
        }
    }
}

// Upload Crashlytics NDK symbols
tasks.whenTaskAdded { task -> if (task.name.startsWith('assemble') && task.name.endsWith("Release")) task.finalizedBy "uploadCrashlyticsSymbolFile" + task.name.substring('assemble'.length()) }

dependencies {
    ...
    implementation platform('com.google.firebase:firebase-bom:25.2.1')
    implementation 'com.google.firebase:firebase-iid:20.1.5'
    implementation 'com.google.firebase:firebase-messaging'
    ...
}

至少在我自己的本地库中获取调用堆栈:

【问题讨论】:

  • 您好,我已经上传了符号文件,但我仍然看到缺少的堆栈帧。我还有什么需要做的吗?
  • @FarazAhmed 正如 Kevin 在上一段中提到的那样,崩溃调用堆栈必须通过您自己的本机库才能让控制台显示帧。如果您确定上传符号并且仍然看到丢失的帧,则意味着崩溃调用堆栈没有通过您的本机代码,因为您仍然可以在我的最后一个控制台中看到 libc.so(Missing) 帧(Android 本机代码)图片也是。
  • 感谢您的回复。我知道 .so 文件是非调试文件,因此没有为它们生成符号文件。

标签: android firebase android-ndk crashlytics firebase-console


【解决方案1】:

Firebaser 在这里-

您粘贴屏幕截图的崩溃报告似乎只出现在系统库中。我们可以在 Crashlytics 崩溃报告(和墓碑)中看到,所有的堆栈帧都与“libc.so”相关联——这是一个 Android 系统运行时库,任何像 Crashlytics 这样的库都无法符号化。

这是因为 Crashlytics 只能符号化来自您为其上传符号的库的崩溃或堆栈帧。由于 libc.so 是您和 Crashlytics 都没有其符号的系统库,因此这是预期的行为。 Crashlytics 仍会显示帧,即使它不能进行符号化,它仍会报告尽可能多的信息。

如果您能够提交包含调用堆栈的测试崩溃报告,该调用堆栈会遍历您尝试为其上传符号的本机库,并且您仍然在各处看到“(Missing)”,那将出乎意料。如果是这种情况,我建议您确保在您链接的文档中关注these instructions,如果您仍有问题,请联系Firebase support

【讨论】:

  • 感谢您的关注和澄清,我已经根据您发送的说明和我得到的结果更新了我的答案。我想知道顺便说一句,我是否也有任何解决方案可以上传系统本机库符号,正如您提到的“Crashlytics 只能表示来自您已为其上传符号的库的崩溃或堆栈帧”,并且因为 AOSP 有一套我想每个 Android 版本上每个 CPU 架构的固定原生资源?
  • 根据您的编辑,您似乎仍然遇到问题,要么将库的符号文件上传到 Crashlytics,要么 Crashlytics 遇到问题,表明上传的符号文件会导致这些崩溃。我会检查以确保您在 strippedNativeLibsDir 和 unStrippedNativeLibsDir 指定的位置是正确的。否则,您可以使用以下命令检查调试日志以查看 Crashlytics 符号生成 + 上传的状态:./gradlew app:assembleDebug --console=plain --debug | grep "[com.google.firebase.crashlytics]"
  • 是的,不幸的是,系统符号点没有解决方案,因为正如您所说,AOSP 有自己的一组本地库,Crashlytics 无法看到这些库。只有设备上的符号,如 Play 商店本身。
  • 感谢您的帮助,命令行提示帮助我查明了核心问题,并如您所说,让它在我自己的本机库上运行。尽管如果插件报告符号上传结果本身以及过程中是否存在罪魁祸首或说例如短暂的互联网连接丢失,这将是一个很大的帮助,但开发人员会意识到失败的结果并尝试重试该过程(带有重试链接或某事),对于成功上传也是如此。由于 Fabric 插件之前在日志文件中报告了该过程。
  • 好点!我同意更强大的日志记录,这样您就可以自行解决并找出问题所在,这在这里会非常有帮助,而且我自己也在推动这一点。这是团队正在考虑的反馈。
猜你喜欢
  • 2019-07-28
  • 2018-11-14
  • 2020-11-29
  • 1970-01-01
  • 2011-12-28
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多