Search code examples
androidandroid-ndkopencldlopenunsatisfiedlinkerror

Linking shared library libGLES_mali.so causes dlopen failed: library "[email protected]" not found in Android >= 7.0


Since Android 7.0 it's not possible anymore to link against a non-ndk shared library (see NDK Apps Linking to Platform Libraries).

One possible workaround consists in including the library in the apk (See Update your app).

The library that you are trying to link against may depend on other non-ndk libraries. In that case you should include those libraries too.

In my case I've been developing an application which makes use of OpenCL. On ARM devices the library with the correct symbols is libGLES_mali.so. The application works fine on devices with Android < 7.0 but it crashes on devices with Android >= 7.0. The error that I can read in logcat is:

java.lang.UnsatisfiedLinkError: dlopen failed: library "[email protected]" not found

Using the command

readelf -d libGLES_mali.so | grep NEEDED

I can read the name of the libraries libGLES_mali.so depend on and predictably [email protected] is among them:

0x0000000000000001 (NEEDED)             Shared library: [[email protected]]
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnativewindow.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++.so]
 0x0000000000000001 (NEEDED)             Shared library: [libutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]

I've tried including the aforementioned library in the apk but I get the same error. The weird thing is that the library is part of the VNDK-SP (see SP-HAL) and as such it is my understanding that private libraries may depend on it freely.

Any suggestion?

EDIT 31/01/2019: Tested devices running on Android >= 7.0 were all Huawei. Could it possibly be a vendor related problem?


Solution

  • Alex Cohn comment was right. In order to solve the problem I did the following:

    1) Renamed [email protected] in libfoo.so

    2) Added libfoo.so in CMakeLists.txt like this:

    add_library( foo
             SHARED
             IMPORTED )
    set_target_properties( foo
             PROPERTIES IMPORTED_LOCATION
             ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfoo.so )
    

    3) Target-linked MyLibrary, which contains the OpenCL calls, against libfoo.so (and, of course, libGLES_mali.so)

    target_link_libraries (MyLibrary GLES_mali foo)
    

    4) Loaded libfoo.so as soon as possible. To do so I created a static method in my MainActivity which I call as soon as the application enters onCreate().

    private static void loadLibrary() {
        System.loadLibrary("foo");
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        loadLibrary();
        ...
    }  
    

    At this point the application crashes complaining that it couldn't find some libraries. Using the readelf command:

    ./readelf -d /Users/rodolforocco/AndroidProjects/OvermindClient/app/libs/arm64-v8a/android-27/libfoo.so | grep NEEDED
    

    I was able to see that these were indeed the libraries that libfoo.so depended on. These libraries also depended on other libraries that could not be located. I copied them all from the folder /system/lib64/ in my device to the folder ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/, where libfoo.so was.

    5) Finally, as before, I loaded MyLibrary when I needed it.

    The application doesn't crash anymore and works as intended. Thanks a lot!