Android: dlopen fail due to has text relocations issue

For some reason, I found out some Apps I programmed several years ago, rebuilt them and put on my MI NOTE (Android 6.0) to run some tests.

Here is my cross compile environment:

  • NDK: former downloaded, r7c + r8b
  • SDK: newly downloaded, 24.4.1

But when I tried to run the App on my phone, I got an error like this:

02-15 14:42:58.540: I/OpenGLRenderer(3260): Initialized EGL, version 1.4
02-15 14:42:58.699: W/InputMethodManager(3260): Ignoring onBind: cur seq=164, given seq=163
02-15 14:43:06.718: I/Timeline(3260): Timeline: Activity_launch_request time:6144239
02-15 14:43:06.877: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libffmpeg.so: has text relocations
02-15 14:43:06.897: D/FFMpeg(3260): Couldn't load lib: ffmpeg - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libffmpeg.so: has text relocations
02-15 14:43:06.905: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libezgl.so: has text relocations
02-15 14:43:06.910: D/FFMpeg(3260): Couldn't load lib: ezgl - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libezgl.so: has text relocations
02-15 14:43:06.920: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libeasyonvif.so: has text relocations
02-15 14:43:06.927: D/FFMpeg(3260): Couldn't load lib: easyonvif - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libeasyonvif.so: has text relocations
02-15 14:43:06.927: W/System.err(3260): rg4.net.onvifplayer.RSException: Couldn't load native libs
02-15 14:43:06.927: W/System.err(3260):     at rg4.net.onvifplayer.libEasyRTSP.<init>(libEasyRTSP.java:40)
02-15 14:43:06.927: W/System.err(3260):     at rg4.net.onvifplayer.PlayerActivity.<init>(PlayerActivity.java:33)
02-15 14:43:06.927: W/System.err(3260):     at java.lang.Class.newInstance(Native Method)
02-15 14:43:06.927: W/System.err(3260):     at android.app.Instrumentation.newActivity(Instrumentation.java:1068)
02-15 14:43:06.927: W/System.err(3260):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2322)
02-15 14:43:06.927: W/System.err(3260):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
02-15 14:43:06.928: W/System.err(3260):     at android.app.ActivityThread.access$900(ActivityThread.java:153)
02-15 14:43:06.928: W/System.err(3260):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
02-15 14:43:06.928: W/System.err(3260):     at android.os.Handler.dispatchMessage(Handler.java:102)
02-15 14:43:06.928: W/System.err(3260):     at android.os.Looper.loop(Looper.java:148)
02-15 14:43:06.928: W/System.err(3260):     at android.app.ActivityThread.main(ActivityThread.java:5432)
02-15 14:43:06.928: W/System.err(3260):     at java.lang.reflect.Method.invoke(Native Method)
02-15 14:43:06.928: W/System.err(3260):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
02-15 14:43:06.928: W/System.err(3260):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
02-15 14:43:06.956: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libffmpeg.so: has text relocations
02-15 14:43:06.962: D/FFMpeg(3260): Couldn't load lib: ffmpeg - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libffmpeg.so: has text relocations
02-15 14:43:06.968: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libezgl.so: has text relocations
02-15 14:43:06.974: D/FFMpeg(3260): Couldn't load lib: ezgl - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libezgl.so: has text relocations
02-15 14:43:06.985: E/linker(3260): /data/app/rg4.net.onvifplayer-1/lib/arm/libeasyonvif.so: has text relocations
02-15 14:43:06.991: D/FFMpeg(3260): Couldn't load lib: easyonvif - dlopen failed: /data/app/rg4.net.onvifplayer-1/lib/arm/libeasyonvif.so: has text relocations
02-15 14:43:06.991: W/System.err(3260): rg4.net.onvifplayer.RSException: Couldn't load native libs
02-15 14:43:06.991: W/System.err(3260):     at rg4.net.onvifplayer.libEasyRTSP.<init>(libEasyRTSP.java:40)
02-15 14:43:06.991: W/System.err(3260):     at rg4.net.onvifplayer.PlayerActivity.onCreate(PlayerActivity.java:65)
02-15 14:43:06.992: W/System.err(3260):     at android.app.Activity.performCreate(Activity.java:6303)
02-15 14:43:06.992: W/System.err(3260):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
02-15 14:43:06.992: W/System.err(3260):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2374)
02-15 14:43:06.992: W/System.err(3260):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
02-15 14:43:06.992: W/System.err(3260):     at android.app.ActivityThread.access$900(ActivityThread.java:153)
02-15 14:43:06.992: W/System.err(3260):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
02-15 14:43:06.992: W/System.err(3260):     at android.os.Handler.dispatchMessage(Handler.java:102)
02-15 14:43:06.992: W/System.err(3260):     at android.os.Looper.loop(Looper.java:148)
02-15 14:43:06.992: W/System.err(3260):     at android.app.ActivityThread.main(ActivityThread.java:5432)
02-15 14:43:06.992: W/System.err(3260):     at java.lang.reflect.Method.invoke(Native Method)
02-15 14:43:06.992: W/System.err(3260):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
02-15 14:43:06.992: W/System.err(3260):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
02-15 14:43:06.994: E/art(3260): No implementation found for int rg4.net.onvifplayer.libEasyRTSP.NewInstance() (tried Java_rg4_net_onvifplayer_libEasyRTSP_NewInstance and Java_rg4_net_onvifplayer_libEasyRTSP_NewInstance__)

Solutions 1:

This issue could be solved by checking the targetSDKVersion in the manifest file.

Using “22” and not “23” as targetSDKVersion solved it. (See below)

<uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="22" />

I also checked the build.gradle files for compile version and targetSDKversion:

compileSdkVersion 22
    buildToolsVersion '22.0.1'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 22
    }

Solutions 2:

It was caused by the ffmpeg, and it could also be solved by patching the latest ffmpeg code

libavcodec\arm\fft_fixed_neon.S
libavcodec\arm\fft_neon.S
libavcodec\arm\fft_vfp.S
libavcodec\arm\mlpdsp_armv5te.S
libutil\arm\asm.S

I took the latest from https://github.com/FFmpeg/FFmpeg

You will also need HAVE_SECTION_DATA_REL_RO declared somewhere in your build for the macro in asm.S to use the dynamic relocations option.

Further informations:

Previous versions of Android would warn if asked to load a shared library with text relocations:

“libfoo.so has text relocations. This is wasting memory and prevents security hardening. Please fix.”.

Despite this, the OS will load the library anyway. Marshmallow rejects library if your app’s target SDK version is >= 23. System no longer logs this because it assumes that your app will log the dlopen(3) failure itself, and include the text from dlerror(3) which does explain the problem. Unfortunately, lots of apps seem to catch and hide the UnsatisfiedLinkError throw by System.loadLibrary in this case, often leaving no clue that the library failed to load until you try to invoke one of your native methods and the VM complains that it’s not present.

You can use the command-line scanelf tool to check for text relocations. You can find advice on the subject on the internet; for example https://wiki.gentoo.org/wiki/Hardened/Textrels_Guide is a useful guide.

And you can check if your shared lbirary has text relocations by doing this:

readelf -a path/to/yourlib.so | grep TEXTREL

If it has text relocations, it will show you something like this:

0x00000016 (TEXTREL)                    0x0

If this is the case, you may recompile your shared library with the latest NDK version available:

ndk-build -B -j 8

And if you check it again, the grep command will return nothing.