zig
zig copied to clipboard
std.DynLib: Lookup points to zero'ed bytes when libc is not linked.
Zig Version
0.14.0-dev.1166+bb7050106
Steps to Reproduce and Observed Behavior
Using the above archive, run the following commands:
$ tar xvf repro.tar.gz
zig-dynlib-lookup-bug/
zig-dynlib-lookup-bug/.gitignore
zig-dynlib-lookup-bug/LICENSE
zig-dynlib-lookup-bug/README.md
zig-dynlib-lookup-bug/build.zig
zig-dynlib-lookup-bug/lib.zig
zig-dynlib-lookup-bug/main.zig
zig-dynlib-lookup-bug/workaround.diff
$ cd zig-dynlib-lookup-bug
$ zig build
$ ./zig-out/bin/repro zig-out/lib/librepro.so
Segmentation fault at address 0x0
???:?:?: 0x0 in ??? (???)
fish: Job 1, './zig-out/bin/repro zig-out/lib…' terminated by signal SIGABRT (Abort)
Expected Behavior
$ ./zig-out/bin/repro zig-out/lib/librepro.so
Hello, world!
Linking libc works around the issue.
Environment:
$ cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.20.2
PRETTY_NAME="Alpine Linux v3.20"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
$ uname -a
Linux gcoakes 6.6.45-0-lts #1-Alpine SMP PREEMPT_DYNAMIC 2024-08-13 08:10:32 x86_64 GNU/Linux
Related to #20980
This is caused by missing relocation logic in the zig implementation of ElfDynLib. Linking wtih libc causes dlopen to be used instead, which makes it work. Though this case is probably more complicated, because std is involved
Somewhat reduced repro steps updated for 0.15.0-dev.552+bc2f7c754
mkdir repro
cd repro
zig init
root.zig
const std = @import("std");
pub export fn foo() callconv(.c) void {
std.debug.print("aa", .{});
}
main.zig
const std = @import("std");
pub fn main() !void {
var lib = try std.DynLib.open("zig-out/lib/librepro.so");
const foo = lib.lookup(*const fn () callconv(.c) void, "foo") orelse return error.LookupFailed;
foo();
}
build.zig diff
51c51
< .linkage = .static,
---
> .linkage = .dynamic,
zig build run