DynLib fails to open libGL.so
DynLib fails to open and parse libGL.so un linux (Ubuntu 20.04 x64) due to error.ElfHashTableNotFound. std.elf.readAllHeaders seems to parse the header okay, maybe ElfDynLib should use that.
Modern libraries on Linux use DT_GNU_HASH and not DT_HASH, and apparently aren't even inserting the old hash table in the binary anymore. It seems DynLib doesn't handle that yet.
you can link libc, then it will use libc provided dlopen() instead of custom zig impl
EDIT: it seems to work with arm-features.h patch to zig. feel free to use that repo as example.
FYI I was trying to cross-compile for 32bit raspi (where musl is the only libc which works ATM) but unfortunately, dlopen() doesn't seem to work - I get File not found error and I don't know why (the file exists, it's in ldconfig -v, etc.).
Here's repo https://github.com/cztomsik/glfw-loader if anyone wants have a look at how to do something similar - I think it should be mostly correct and maybe it's just some misconfiguration, I might try to figure it out later but now I don't want to waste any more time.
Zig version: Master (0.11.0-dev.12+ebf9ffd34) Project test: https://github.com/kassane/zig-pkcs11 (wip)
I encounter something similar in the lib below. But there was a difference that in the CI (GH actions) another error code occurred.
My host: (softhsm2 - not installed)
Test [1/2] test.Detecting libSoftHSM 2... [default] (err):
Error: Library not found!
Code: error.FileNotFound
GH actions: - (softhsm2 - installed on ubuntu)
1/2 test.Detecting libSoftHSM 2... [default] (err):
Error: Library not found!
Code: error.ElfHashTableNotFound
Modern libraries on Linux use DT_GNU_HASH and not DT_HASH, and apparently aren't even inserting the old hash table in the binary anymore. It seems DynLib doesn't handle that yet.
So this justifies the fact of only recognizing shared library compiled with zig itself.
I think adding DT_GNU_HASH-support will only reveal further problems, since glibc apparently doesn't work without initialization (and most Linux .so-libraries depend on glibc). I investigated this by compiling my own .so-library with gcc, and passing a linker option to force DT_HASH output (-Wl,--hash-style=sysv) so I could load it with zig's ELF loader, but then any libc call inside my .so-library crashes the program:
Segmentation fault at address 0x0
???:?:?: 0x0 in ??? (???)
???:?:?: 0x7f972cfac81d in ??? (???)
/path/to/my/src/host.zig:13:22: 0x20df05 in main (host)
c_function_inside_so_library_that_calls_glibc_stuff();
...
I don't think glibc supports being initialized dynamically? (Ostensibly you need to re-enter your program via __libc_start_main, but it's not even a symbol I can lookup?)
DT_GNU_HASH support is still useful if you want to load shared objects built with gcc and -nostdlib (because it defaults to --hash-style=gnu, used to be --hash-style=both), or if you have a "A loads B loads C" thing going where A and C depend on glibc, but B doesn't and instead uses zig's ELF loader.
Also, in case it matters to somebody; I've dug into the ziglang-code and learned that zig does heap allocations using mmap-syscalls (and neverbrk) so you shouldn't have problems in the opposite case where a glibc-based host loads a static/nolibc shared object built with zig.
I'm experiencing the same problem here with using std.DynLib and Flutter Engine's embedded engine shared library. Sounds like I'll have to link libc and use dlopen/dlsym for this to work correctly.
I've hacked together some DT_GNU_HASH support. https://github.com/ziglang/zig/commit/c2a4e20efa72330aed0346b60be150a26cfb6430