#Call to 0x0 with the Zig 0.15.2 Linker when using OpenAL

1 messages · Page 1 of 1 (latest)

twin stirrup
#

I solved this already with Claude but just want to get it out there if anyone is ever interested in checking it out in the compiler.

The fix was just switching to lld+llvm.

I linked against openal in Zig(with its linker) with the linkSystemLibrary. When trying to call alcOpenDevice I hit a nasty segfault.
The stacktrace showed me that I was calling 0x0.

After switching the call was valid.

These are some diagnostic commands I ran:

$ # What does the actual binary think about alcOpenDevice?
objdump -d ./zig-out/bin/bwg | grep -A5 alcOpenDevice

# Is it even in the PLT?
objdump -d ./zig-out/bin/bwg | grep plt | grep -i openal

# Check the dynamic symbol table
readelf -Ws ./zig-out/bin/bwg | grep alcOpenDevice

# Check what the .so exports
readelf -Ws /lib64/libopenal.so.1 | grep alcOpenDevice
 113b0ba:    48 8b 15 07 ca 05 00     mov    0x5ca07(%rip),%rdx        # 1197ac8 <alcOpenDevice@Base>
 113b0c1:    bb 03 00 00 00           mov    $0x3,%ebx
 113b0c6:    e8 85 0c 00 00           call   113bd50 <Io.Writer.printValue__anon_22834>
 113b0cb:    66 89 c2                 mov    %ax,%dx
 113b0ce:    81 e2 ff ff 00 00        and    $0xffff,%edx
 113b0d4:    66 83 fa 00              cmp    $0x0,%dx
    34: 0000000000000000  3211 FUNC    GLOBAL PROTECTED  UND alcOpenDevice
  3551: 0000000001197ac8     8 OBJECT  LOCAL  DEFAULT   25 alcOpenDevice$got
  3615: 0000000000000000  3211 FUNC    GLOBAL PROTECTED  UND alcOpenDevice
   261: 000000000005c9d0  3211 FUNC    GLOBAL PROTECTED    5 alcOpenDevice

readelf -d ./zig-out/bin/bwg | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libSDL3.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libopenal.so.1]
#

What Claude said:

What happened: Zig has its own self-hosted linker (not LLD, not GNU ld) that it uses by default. It has a bug where when a shared library exports a symbol with PROTECTED visibility (which OpenAL does), Zig's linker misclassifies the symbol — it emits a LOCAL GOT data slot instead of a proper PLT function stub. The dynamic linker then never fills it in, leaving 0x0. GCC, Clang, and LLD all handle PROTECTED function symbols correctly.
#

If any contributor sees it thanks for working on Zig I love it