Skip to content

zig cc: Cannot load shared library cross-compiled to arm-linux-gnueabihf #11471

@saierd

Description

@saierd

Zig Version

0.9.1

Steps to Reproduce

Compile the program in this gist: https://gist.github.com/saierd/3ee0a898ae7fa5b469e53536851cb39c

lib.cpp:

#include <iostream>

void test()
{
    std::cout << "lib" << std::endl;
}

main.cpp:

#include <iostream>

void test();

int main()
{
    std::cout << "main" << std::endl;
    test();
    return 0;
}

Build:

zig c++ -target arm-linux-gnueabihf -shared -o libtest.so lib.cpp
zig c++ -target arm-linux-gnueabihf main.cpp -l libtest.so

Expected Behavior

Program should run on an ARM device.

Actual Behavior

Without the dynamic library

If I remove the dynamic library from the test program (just a hello world) everything works fine. The program runs in QEMU as well as on the actual device, even though there are some strange things happening on the device:

  • ldd a.out outputs not a dynamic executable.
  • /lib/ld-linux-armhf.so.3 --verify a.out returns 1.

With the dynamic library

  • The program does run in QEMU.
  • The program does not run on the actual device and fails with the error message
    ./a.out: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
    
  • Output of ldd and ld --verify are the same as above for both a.out and libtest.so.

I tried to debug what happens with LD_DEBUG and strace and this is what I found out:

  • The search for the library does find libtest.so and tries to open it. strace shows that some parts of the file get read:
    open("./libtest.so", O_RDONLY|O_CLOEXEC) = 3
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\360E\2\0004\0\0\0"..., 512) = 512
    lseek(3, 497736, SEEK_SET)              = 497736
    read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1040) = 1040
    lseek(3, 493664, SEEK_SET)              = 493664
    read(3, "A\35\0\0\0aeabi\0\1\23\0\0\0\6\6\10\1\t\1\30\1\31\1\"\0D\1", 30) = 30
    close(3)                                = 0
    open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
    fstat64(3, {st_mode=S_IFREG|0644, st_size=11919, ...}) = 0
    mmap2(NULL, 11919, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6fab000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    
  • It seems like the file gets discarded for some reason, since after this the search continues with the system search paths.
  • If the file /etc/ld.so.nohwcap exists, this removes some of the paths that were searched previously and the access no longer fails:
    open("./libtest.so", O_RDONLY|O_CLOEXEC) = 3
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\360E\2\0004\0\0\0"..., 512) = 512
    lseek(3, 497736, SEEK_SET)              = 497736
    read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1040) = 1040
    lseek(3, 493664, SEEK_SET)              = 493664
    read(3, "A\35\0\0\0aeabi\0\1\23\0\0\0\6\6\10\1\t\1\30\1\31\1\"\0D\1", 30) = 30
    close(3)                                = 0
    open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
    fstat64(3, {st_mode=S_IFREG|0644, st_size=11919, ...}) = 0
    mmap2(NULL, 11919, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6fa8000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = 0
    
  • Other than that everything else is the same as when the file does not exist. After these lines, the search continues with the system search paths.

I know that this is probably difficult to debug without actual hardware. Do you have any idea for how I could investigate this further?

Metadata

Metadata

Assignees

No one assigned

    Labels

    arch-arm32-bit ArmbugObserved behavior contradicts documented or intended behavioros-linuxLinux

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions