ANDROID NDK

Make C/C++ stack trace more understandable on Firebase Crashlytics and PlayStore

How to upload native debug symbols to make fix of C/C++ bug easier and get 100% crash free user

Torcheux Frédéric

--

Upload native debug symbol on Firebase and Play Store to get more understandable native stack trace.

The same way Firebase Crashlytics and Play Store need a mapping file to decode Java / Kotlin crash stack traces, they also need a specific mapping file to decode native crash stack traces.

To generate this file, an application needs to access unstripped versions of native libraries .so and the stripped ones.

An unstripped .sofile contains native debug symbols. It means it keeps for each instruction the information of the line in the source code, the variable and function names.

By default, a published library, in a aar file (by using the maven or maven-publish plugin) embeds the stripped .so. There are no debug symbols so we can’t get understandable native stack traces in case of a crash.

Publish a library with unstripped .so files

For Android Gradle plugin 7.0 and above

In the library’s build.gradle, use keepDebugSymbols to select which .so embed in its unstripped version.

Here, all .so are unstripped:

For Android Gradle plugin 4.2 and under

In the library build.gradle, use doNotStrip to select which .so embed in its unstripped version.

Here, all .so are unstripped:

⚠️ Because an unstripped .so contains all debug symbols, it's far bigger than the stripped one.

You could be afraid that your .aabsize will increase drastically.

Don’t worry, users won’t see the difference because, during the release of your application, the release task will do the transformation unstripped -> stripped.

Upload debug symbol to the Play store

To upload native debug symbols on the Play Store, you must ship them in the released .aab.

This information will be in the .aab at the following path: BUNDLE_METADATA/com.android.tools.build.debugsymbols/{ABI}/{your_native_lib.so.dbg}

In the application’s build.gradle, add the following configuration:

debugSymbolLevel can take two values:

  • FULL: you will get function names, files, and line numbers in the Play Console's symbolicated stack traces.
  • SYMBOL_TABLE : you will get function names in the Play Console's symbolicated stack traces.

Use this second value if your debug symbol file is more than 300Mo because the Play Store fixes a file size limitation. Otherwise, we should use FULL to get the most information.

Upload debug symbol on Firebase Crashlytics

In the application’s build.gradle, if Firebase Crashlytics is already setup, you just have to add this dependency:

dependencies {
implementation 'com.google.firebase:firebase-crashlytics-ndk:{VERSION}'
}

You also have some configuration to do:

  • Enable native symbol upload feature for your release buildType.
  • Define the path of your stripped and unstripped native libraries.

These files are localized in specific directories:

  • stripped: $buildDir/intermediates/stripped_native_libs/{BUILD_VARIANT}/out/lib
  • unstripped: $buildDir/intermediates/merged_native_libs/{BUILD_VARIANT}/out/lib

⚠️ Check that the files don’t have the same size to be sure the stripped versions are generated. Unstripped versions should be bigger than the stripped ones.

If your application doesn’t have product flavors, the configuration you add inbuild.gradle will look like this:

Now you can build a release .aab of your application.

After the build, call uploadCrashlyticsSymbolFile{BUILD_VARIANT} to upload native debug symbols on the platform.

If your app doesn’t have product flavors, the task is uploadCrashlyticsSymbolFileRelease.

Conclusion

If you followed all the intructions, now you know:

  • How to publish a library with unstripped .so files.
  • How to publish native debug symbols on the Play Store.
  • How to publish native debug symbols on Firebase crashlytics.

Future native crash reports will be more explicit and it will be easier to fix them and get 100% crash free user !

Links

--

--

Torcheux Frédéric

I’m a French Android developer at MWM. I humbly try to contribute to the developer community from which I learnt everything.