Bug report
librive-android.so for the x86_64 ABI in app.rive:rive-android:11.4.1 still contains a general-dynamic TLS relocation (R_X86_64_DTPMOD64, relocation type 16) and imports __tls_get_addr. Android's bionic dynamic linker does not support dynamic-TLS relocations in a dlopen()-ed shared library before API 29, so Rive.init() → System.loadLibrary aborts at startup on x86_64 devices running Android ≤ 9.
This appears to be the x86_64 counterpart of #445 (armeabi-v7a, "unknown reloc type 17"), which was reported fixed in 11.4.1 by adapting the libhydrogen TLS fix — but the x86_64 build of 11.4.1 still carries the TLS relocation. This is consistent with the post-close report on #445 that crashes persist on Android 9.
Versions
Affected devices
- ABI: x86_64
- Android 9 (API 28)
- Reproduced on x86_64 Chromebooks (Android-on-ChromeOS / ARC++): Intel Apollo Lake / Braswell-class boards (e.g.
coral). ARM phones are unaffected — they load the arm64-v8a build.
Crash
java.lang.UnsatisfiedLinkError: dlopen failed: unknown reloc type 16 @ 0x... (11982)
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1669)
at app.rive.runtime.kotlin.core.Rive$NativeLoader.loadWithSystemLoader(Rive.kt)
at app.rive.runtime.kotlin.core.Rive$NativeLoader.loadLibrary(Rive.kt:11)
at app.rive.runtime.kotlin.core.Rive.init(Rive.kt:31)
Evidence
The readelf/objdump TLS check (the one requested in #445), run against lib/x86_64/librive-android.so extracted from the 11.4.1 artifact:
# relocation-type histogram
11982 R_X86_64_RELATIVE
6757 R_X86_64_64
2077 R_X86_64_JUMP_SLOT
535 R_X86_64_GLOB_DAT
1 R_X86_64_DTPMOD64 <-- relocation type 16 == "unknown reloc type 16"
# general-dynamic TLS marker (undefined import)
*UND* __tls_get_addr
# TLS program header present
TLS ... memsz 0x40 flags r--
R_X86_64_DTPMOD64 is relocation type 16 on x86_64 — exactly the "unknown reloc type 16" in the crash. The single DTPMOD64 plus the __tls_get_addr import indicate one thread_local compiled with the general/local-dynamic TLS model.
Why x86_64 specifically
arm64-v8a uses R_AARCH64_TLSDESC (TLS-descriptor model), which modern bionic supports, so phones load fine. The x86_64 (and likely x86) build emits general-dynamic TLS (DTPMOD64 + __tls_get_addr), which bionic's linker rejects on API < 29.
Suggested fix
Same family as the libhydrogen fix in #445, but the x86/x86_64 builds appear to have been missed. Build the affected native libraries with emulated TLS (-femulated-tls) or force the initial-exec model (-ftls-model=initial-exec), so the thread_local no longer emits general-dynamic relocations / __tls_get_addr and instead resolves via __emutls_get_address (supported on all API levels). This matches the NDK guidance for supporting API < 29 with thread_local.
Happy to re-run the TLS check on a fixed build.
Bug report
librive-android.sofor the x86_64 ABI inapp.rive:rive-android:11.4.1still contains a general-dynamic TLS relocation (R_X86_64_DTPMOD64, relocation type 16) and imports__tls_get_addr. Android's bionic dynamic linker does not support dynamic-TLS relocations in adlopen()-ed shared library before API 29, soRive.init()→System.loadLibraryaborts at startup on x86_64 devices running Android ≤ 9.This appears to be the x86_64 counterpart of #445 (armeabi-v7a, "unknown reloc type 17"), which was reported fixed in 11.4.1 by adapting the
libhydrogenTLS fix — but the x86_64 build of 11.4.1 still carries the TLS relocation. This is consistent with the post-close report on #445 that crashes persist on Android 9.Versions
app.rive:rive-android: 11.4.1 (pulled via[email protected])libhydrogenwas added (per Android startup crash in 11.3.1 on armeabi-v7a / older devices: UnsatisfiedLinkError "unknown reloc type 17" #445)Affected devices
coral). ARM phones are unaffected — they load thearm64-v8abuild.Crash
Evidence
The
readelf/objdumpTLS check (the one requested in #445), run againstlib/x86_64/librive-android.soextracted from the 11.4.1 artifact:R_X86_64_DTPMOD64is relocation type 16 on x86_64 — exactly the "unknown reloc type 16" in the crash. The singleDTPMOD64plus the__tls_get_addrimport indicate onethread_localcompiled with the general/local-dynamic TLS model.Why x86_64 specifically
arm64-v8ausesR_AARCH64_TLSDESC(TLS-descriptor model), which modern bionic supports, so phones load fine. The x86_64 (and likely x86) build emits general-dynamic TLS (DTPMOD64+__tls_get_addr), which bionic's linker rejects on API < 29.Suggested fix
Same family as the
libhydrogenfix in #445, but the x86/x86_64 builds appear to have been missed. Build the affected native libraries with emulated TLS (-femulated-tls) or force the initial-exec model (-ftls-model=initial-exec), so thethread_localno longer emits general-dynamic relocations /__tls_get_addrand instead resolves via__emutls_get_address(supported on all API levels). This matches the NDK guidance for supporting API < 29 withthread_local.Happy to re-run the TLS check on a fixed build.