Crash: UnsatisfiedLinkError loading OnionMasq JNI at app startup
On the device: Xiaomi Redmi 5, using Android 7.1 (SDK 25) the following crash happened:
Exception java.lang.UnsatisfiedLinkError:
at java.lang.Runtime.loadLibrary0 (Runtime.java:989)
at java.lang.System.loadLibrary (System.java:1562)
at org.torproject.onionmasq.OnionMasqJni.<clinit> (OnionMasqJni.java:202)
at org.torproject.onionmasq.OnionMasqJni.init
at org.torproject.onionmasq.OnionMasq.<init> (OnionMasq.java:92)
at org.torproject.onionmasq.OnionMasq.init (OnionMasq.java:82)
at org.torproject.vpn.TorApplication.onCreate (TorApplication.kt:15)
at android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1025)
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:5506)
at android.app.ActivityThread.-wrap2 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1593)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:163)
at android.app.ActivityThread.main (ActivityThread.java:6238)
at java.lang.reflect.Method.invoke
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:794)
This indicates the expected native .so for oniomasq could not be found or loaded for the device’s ABI.
A Xiaomi Redmi 5 on Android 7.1 (SDK 25) seems to typically run a 32-bit ARM userspace (armeabi-v7a). We do not provide that architecture for onionmasq, so this would be why we got this.
We do build onionmasq for armeabi-v7a
, and when I download and unpack the apk, I do find ./lib/armeabi-v7a/libonionmasq_mobile.so
in there and:
$ file ./lib/armeabi-v7a/libonionmasq_mobile.so
./lib/armeabi-v7a/libonionmasq_mobile.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, for Android 21, built by NDK r25c (9519653), stripped
I looked at the objdump -p
output of the libonionmasq_mobile.so
and the libgojni.so
for v7a, and the NEEDED
shows only system libs (liblog
, libdl
, libm
, libc
, and also libandroid
for libgojni), which suggests there isn't a missing runtime.
I think if you could run a 32-bit arm emulator of the apk, and capture the logcat, it might be possible to find a missing symbol error when the dlopen happens. Probably there is some symbol/API mismatch and we could see that symbol error in a logcat output from an emulator.... but I'm not that savvy with android, this is just coming from my knowledge of dynamically loaded shared libraries from C.