Summary
Native crashes on Android 15/16 are reported without a resolved stack trace when the Tombstone integration is active. Similar crashes on Android 10/11 (mechanism signalhandler) symbolicate correctly.
The affected setup is a game engine app where the native libraries are loaded directly from the APK (extractNativeLibs=false / uncompressed, zip-aligned .so entries).
Affected events have mechanism TombstoneMerged or Tombstone, and all frames of the app's native library show "symbolicator_status": "unknown_image".
Behavior
Frame from the signal handler (symbolication succeeds):
{
"package": "/data/app/<redacted>/base.apk",
"in_app": false,
"image_addr": "0x<image_addr>",
"instruction_addr": "0x<instruction_addr>"
}
with a matching debug image:
{
"code_id": "<redacted>",
"code_file": "/data/app/<redacted>/base.apk",
"debug_id": "<redacted>",
"arch": "arm64",
"image_addr": "0x<image_addr>",
"image_size": <redacted>,
"type": "elf",
"debug_status": "found"
}
Frame from the tombstone (symbolication fails):
{
"package": "/data/app/<redacted>/base.apk!libGame.so",
"in_app": false,
"data": {
"client_in_app": false,
"symbolicator_status": "unknown_image"
},
"instruction_addr": "0x<instruction_addr>"
}
There is no debug image for base.apk or for the app's native library in the event.
|
signalhandler |
TombstoneMerged |
frame package |
.../base.apk |
.../base.apk!libGame.so |
frame image_addr |
set |
missing |
| debug image for the app library |
present |
absent |
| symbolicator |
ok |
unknown_image |
Possible Cause
TombstoneParser.createDebugMeta does not create a module for APK-embedded ELFs
TombstoneParser.java#L317-L320 starts a module only when hasBuildId && mapping.offset == 0. The offset == 0 condition is a proxy for "the ELF header is at this position". That is correct for an extracted /lib/arm64/libfoo.so, but not for a library mapped out of the APK:
- the mapping name is the APK (
.../base.apk)
- the mapping offset is the zip entry offset of the library, so it is not
0
- the build id can still be present on that mapping
So the condition is never true and no debug image is created for the crashing library. The frames also do not set image_addr (only the package is set), so the symbolicator can match only by address range - and there is no image to match against.
System libraries are not affected because they are real files at offset 0. The test fixture in the SDK only contains extracted .../lib/arm64/*.so, so this case is not covered by tests.
Suggested fix
In TombstoneParser:
- accept a mapping with a non-zero offset and a build id as the start of a module (ELF at an offset inside a zip/APK), like sentry-native does
- write
code_file in a form the symbolicator accepts (sentry-native uses .../base.apk; the !-path may need normalization)
- set
image_addr on the frames, or make sure the image range covers the program counters
- add a test fixture with an APK-embedded library
Workaround
Disable the Tombstone integration, so native crashes use the signal handler only:
- sentry-java:
io.sentry.tombstone.enable=false in the AndroidManifest.xml, or options.setTombstoneEnabled(false)
- sentry-unreal: Project Settings -> Sentry -> General|Mobile -> Android crash capturing backend ->
NdkSignalHandler
Summary
Native crashes on Android 15/16 are reported without a resolved stack trace when the Tombstone integration is active. Similar crashes on Android 10/11 (mechanism
signalhandler) symbolicate correctly.The affected setup is a game engine app where the native libraries are loaded directly from the APK (
extractNativeLibs=false/ uncompressed, zip-aligned.soentries).Affected events have mechanism
TombstoneMergedorTombstone, and all frames of the app's native library show"symbolicator_status": "unknown_image".Behavior
Frame from the signal handler (symbolication succeeds):
{ "package": "/data/app/<redacted>/base.apk", "in_app": false, "image_addr": "0x<image_addr>", "instruction_addr": "0x<instruction_addr>" }with a matching debug image:
{ "code_id": "<redacted>", "code_file": "/data/app/<redacted>/base.apk", "debug_id": "<redacted>", "arch": "arm64", "image_addr": "0x<image_addr>", "image_size": <redacted>, "type": "elf", "debug_status": "found" }Frame from the tombstone (symbolication fails):
{ "package": "/data/app/<redacted>/base.apk!libGame.so", "in_app": false, "data": { "client_in_app": false, "symbolicator_status": "unknown_image" }, "instruction_addr": "0x<instruction_addr>" }There is no debug image for
base.apkor for the app's native library in the event.package.../base.apk.../base.apk!libGame.soimage_addrunknown_imagePossible Cause
TombstoneParser.createDebugMetadoes not create a module for APK-embedded ELFsTombstoneParser.java#L317-L320starts a module only whenhasBuildId && mapping.offset == 0. Theoffset == 0condition is a proxy for "the ELF header is at this position". That is correct for an extracted/lib/arm64/libfoo.so, but not for a library mapped out of the APK:.../base.apk)0So the condition is never true and no debug image is created for the crashing library. The frames also do not set
image_addr(only the package is set), so the symbolicator can match only by address range - and there is no image to match against.System libraries are not affected because they are real files at offset
0. The test fixture in the SDK only contains extracted.../lib/arm64/*.so, so this case is not covered by tests.Suggested fix
In
TombstoneParser:code_filein a form the symbolicator accepts (sentry-native uses.../base.apk; the!-path may need normalization)image_addron the frames, or make sure the image range covers the program countersWorkaround
Disable the Tombstone integration, so native crashes use the signal handler only:
io.sentry.tombstone.enable=falsein theAndroidManifest.xml, oroptions.setTombstoneEnabled(false)NdkSignalHandler