2

Environment

First I will give a quick summary of my environment

Device: Samsung Galaxy M20 (m20lte)
SoC: Exynos 7904 (with Mali-G71 GPU)
OS: Android 10 (Stock ROM with root using Magisk)
Kernel: 4.4.177
SELinux is disabled (set to permissive mode)
Vulkan API version: 1.1.108

Chroot environment: Debian 11 (arm64) running on Linux Deploy, with full root access. Directories like /dev, /proc, /data, /system, /sdcard are mounted into the chroot.

Vulkan availability

I know this device support Vulkan API (Vulkan loader avaliable at /system/lib64/libvulkan.so).

Normal Android apps can load and use Vulkan APIs without any problems. For example:

  • Vulkan Caps Viewer can display Vulkan information on this device
  • GeekBench 5, Compute section has an option to compute with GPU using Vulkan API, and it works well

Problem

I cannot load libvulkan.so from /system/lib64/libvulkan.so by running program in the chroot.

For example, I created a simple c source (named dlopen.c):

#include <stdio.h>
#include <dlfcn.h>

int main() {
        void *handle = dlopen("libvulkan.so", RTLD_LAZY);
        if (!handle) {
                printf("Cannot load libvulkan.so\n");
        } else {
                printf("Loaded libvulkan.so\n");
        }

        return 0;
}

Compile it using gcc: gcc dlopen.c -ldl -o dlopentest
Setup the environment variable LD_LIBRARY_PATH=/system/lib64/ or symlink /system/lib64/libvulkan.so to (folder in chroot) /lib/aarch64-linux-gnu/libvulkan.so and /lib/aarch64-linux-gnu/libvulkan.so.1
Finally run it using ./dlopentest, the program always print Cannot load libvulkan.so

Using strace, but nothing weird found (log link)

I'm not sure about /lib/aarch64-linux-gnu/libc.so, since instead of being a symlink to libc.so.6 or a real .so file, it's some kind of ld script. But replacing it with a symlink to libc.so.6 makes no change.

vulkaninfo also reports an error:

ERROR at /build/vulkan-tools-3Ouhix/vulkan-tools-1.2.162.0+dfsg1/vulkaninfo/vulkaninfo.h:628: Failed to initialize: Vulkan loader is not installed, not found, or failed to load.

strace result is pretty much the same as my dlopentest, so I won't include it here.

EDIT 1:

(actually I don't know what section to put this, so I put it here)

Running file on /system/lib64/libvulkan.so:

/system/lib64/libvulkan.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[md5/uuid]=e749d3c10d92fcef9b84402783d311f8, stripped

It's dynamically linked, so I run ldd on it and notice the following line:

/system/lib64/libvulkan.so: /lib/aarch64-linux-gnu/libc.so: version `LIBC' not found (required by /system/lib64/libvulkan.so)
/system/lib64/libvulkan.so: /lib/aarch64-linux-gnu/libdl.so: version `LIBC' not found (required by /system/lib64/libvulkan.so)

And other lines from .so libraries in /system/lib64 claimed the same thing.

So I check the /system/lib64/libc.so, and found that it's a symbolic link to /apex/com.android.runtime/lib64/bionic/libc.so.

So I mounted /apex/com.android.runtime to chroot.

After doing so, ldd found no more problem (log link)

But, when I run the program:

root@localhost:~# ./dlopentest
Trace/breakpoint trap

Running strace (log link)

Using gdb, I found that it was a trap signal from /system/lib64/ld-android.so

Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000007fb7fef000 in rtld_db_dlactivity () from /system/lib64/ld-android.so

When I check that file:

root@localhost:~# file /system/lib64/ld-android.so
/system/lib64/ld-android.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[md5/uuid]=62f4de8cdef6f71d65c403ac59427c51, stripped
root@localhost:~# ldd /system/lib64/ld-android.so
        statically linked

Question

  • Why it does not work (why I cannot load libvulkan.so properly)?
  • How to fix it?

Real purpose

I know this section might not related to the question, but I still want to include it, to avoid possible XY problem.

I want to run War Thunder (a game, and it supports x86_64 Linux). I run it on box64 and it runs until report cannot initialize Vulkan. FYI, Vulkan is the only supported render backend for the game on Linux, so I can't use OpenGL or something.

The game require the real libc (not Android one), so I can't run it on proot, and distro-proof on Termux is too complicated compared to Linux Deploy.

Finally, thank you for reading this I just want to run War Thunder :)

2
  • Ok, I think this crash because /lib/aarch64-linux-gnu/libc.so.6 is loaded, then another libc /system/lib64/libc.so is loaded. I don't think libc can be loaded with multiple instances
    – raspiduino
    Commented Feb 24, 2023 at 1:40
  • Possible solution: 1) (unlikely) If we can call vulkan api from vulkan kernel driver without using Android libs, then write a simple vulkan loader than redirect the calls. 2) Write a "Vulkan server" that create an IPC (pipeline), read Vulkan commands from that pipeline, then calls to Android's libvulkan.so, then compile it using Android NDK. Then write a "client" libvulkan.so that communicate through the IPC to redirect the calls from program. Compile it using gcc in chroot.
    – raspiduino
    Commented Feb 24, 2023 at 11:27

0

Browse other questions tagged or ask your own question.