Skip to content

Startup crash in 11.4.1 on x86_64 (Android 9 / Chromebook ARC++): UnsatisfiedLinkError "unknown reloc type 16" — TLS DTPMOD64 still present (related to #445) #458

Description

@daentech

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions