You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The published libldk_node.so has no .note.gnu.build-id. Google Play matches an uploaded native debug symbol file to the crashing library by ELF build-id, so Play cannot symbolicate a single ldk-node frame — every production report arrives as raw program counters and has to be symbolicated by hand.
Linking release artifacts with -Wl,--build-id=sha1 would make Play Vitals reports readable directly.
Split out of #94, where the missing build-id was what forced manual symbolication of a production SIGABRT.
Evidence
Checked with llvm-readelf -n against com.synonym:ldk-node-android:0.7.0-rc.52, both the .so packaged in the AAR and the .so in the native-debug-symbols classifier artifact:
library
NT_GNU_BUILD_ID
libldk_node.so (packaged and symbols)
absent
libbitkitcore.so (packaged and symbols)
absent
libvss_rust_client_ffi.so
absent
libjnidispatch.so (JNA, third party)
present
The contrast with JNA is visible in the production reports themselves: debuggerd prints (BuildId: …) next to a frame only when the ELF carries the note. In Bitkit's Play crash and ANR reports, the only frames that ever show a BuildId are the libjnidispatch ones.
Impact
native-debug-symbols-<versionCode>.zip is inert for ldk-node no matter how correctly it is built and uploaded to Play Console. The downstream Android app already sets debugSymbolLevel = "FULL", merges the upstream symbol artifacts, and uploads the archive per release — none of it helps.
The only names Play resolves for this library come from the exported .dynsym. That yields the occasional UniFFI entry point (e.g. uniffi_ldk_node_fn_method_node_list_balances+68 in [Bug]: Node.listBalances ANR in receive flow bitkit-android#1036) and nothing else; all internal Rust/tokio frames stay as bare addresses.
Every production crash therefore needs the manual route: fetch the native-debug-symbols artifact for the exact dependency version, confirm the unstripped .so matches the packaged one by .text vaddr/size, work out which library a PC belongs to from .text ranges, then run llvm-symbolizer. That was required to root-cause SIGABRT: owned tokio Runtime dropped from its own worker thread during chain sync teardown #94 and is not something Play triage can do at scale.
Suggested fix
Add the build-id note when linking the Android release artifacts, e.g. via RUSTFLAGS / .cargo/config.toml for the Android targets:
(same for armv7-linux-androideabi, x86_64-linux-android)
Requirements for it to actually work end to end:
The note must survive stripping — the packaged .so and the native-debug-symbols.so must carry the same build-id, otherwise Play still cannot pair them.
Worth asserting in CI: fail the release job if llvm-readelf -n reports no NT_GNU_BUILD_ID for any published ABI, or if the packaged and symbol libraries disagree.
The same gap exists in synonymdev/bitkit-core and synonymdev/vss-rust-client-ffi; happy to open matching issues there.
Environment
ldk-node-android0.7.0-rc.52 (verified; nothing suggests later tags differ)
ABIs: arm64-v8a, armeabi-v7a, x86_64
Consumer: Bitkit Android 2.4.0 (mainnet to.bitkit), Play Console native symbol upload
Summary
The published
libldk_node.sohas no.note.gnu.build-id. Google Play matches an uploaded native debug symbol file to the crashing library by ELF build-id, so Play cannot symbolicate a single ldk-node frame — every production report arrives as raw program counters and has to be symbolicated by hand.Linking release artifacts with
-Wl,--build-id=sha1would make Play Vitals reports readable directly.Split out of #94, where the missing build-id was what forced manual symbolication of a production
SIGABRT.Evidence
Checked with
llvm-readelf -nagainstcom.synonym:ldk-node-android:0.7.0-rc.52, both the.sopackaged in the AAR and the.soin thenative-debug-symbolsclassifier artifact:NT_GNU_BUILD_IDlibldk_node.so(packaged and symbols)libbitkitcore.so(packaged and symbols)libvss_rust_client_ffi.solibjnidispatch.so(JNA, third party)The contrast with JNA is visible in the production reports themselves:
debuggerdprints(BuildId: …)next to a frame only when the ELF carries the note. In Bitkit's Play crash and ANR reports, the only frames that ever show aBuildIdare thelibjnidispatchones.Impact
native-debug-symbols-<versionCode>.zipis inert for ldk-node no matter how correctly it is built and uploaded to Play Console. The downstream Android app already setsdebugSymbolLevel = "FULL", merges the upstream symbol artifacts, and uploads the archive per release — none of it helps..dynsym. That yields the occasional UniFFI entry point (e.g.uniffi_ldk_node_fn_method_node_list_balances+68in [Bug]: Node.listBalances ANR in receive flow bitkit-android#1036) and nothing else; all internal Rust/tokio frames stay as bare addresses.native-debug-symbolsartifact for the exact dependency version, confirm the unstripped.somatches the packaged one by.textvaddr/size, work out which library a PC belongs to from.textranges, then runllvm-symbolizer. That was required to root-cause SIGABRT: owned tokio Runtime dropped from its own worker thread during chain sync teardown #94 and is not something Play triage can do at scale.Suggested fix
Add the build-id note when linking the Android release artifacts, e.g. via
RUSTFLAGS/.cargo/config.tomlfor the Android targets:(same for
armv7-linux-androideabi,x86_64-linux-android)Requirements for it to actually work end to end:
.soand thenative-debug-symbols.somust carry the same build-id, otherwise Play still cannot pair them.llvm-readelf -nreports noNT_GNU_BUILD_IDfor any published ABI, or if the packaged and symbol libraries disagree.The same gap exists in
synonymdev/bitkit-coreandsynonymdev/vss-rust-client-ffi; happy to open matching issues there.Environment
ldk-node-android0.7.0-rc.52(verified; nothing suggests later tags differ)arm64-v8a,armeabi-v7a,x86_64to.bitkit), Play Console native symbol upload