authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-12 07:29:14-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-16 22:48:18+02:00
logb23404af3d3141037f83257379743c9cdb0de473
tree95f1675b826838265ea8ab72167eb449720e569c
parentb64ce08c993f0871b2f9be7df561da69d9a9037e

DynLib: fix elf loading

The comment was just bogus given that these are private (COW) mappings. This code will need extra logic for handling multiple load segments overlapping the same page, but the deleted logic was not even close. Closes #30966

5 files changed, 28 insertions(+), 30 deletions(-)

lib/std/dynamic_library.zig+8-21
...@@ -302,27 +302,14 @@ pub const ElfDynLib = struct {...@@ -302,27 +302,14 @@ pub const ElfDynLib = struct {
302 const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);302 const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);
303 const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));303 const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));
304 const prot = elfToProt(ph.p_flags);304 const prot = elfToProt(ph.p_flags);
305 if ((ph.p_flags & elf.PF_W) == 0) {305 _ = try posix.mmap(
306 // If it does not need write access, it can be mapped from the fd.306 ptr,
307 _ = try posix.mmap(307 extended_memsz,
308 ptr,308 prot,
309 extended_memsz,309 .{ .TYPE = .PRIVATE, .FIXED = true },
310 prot,310 file.handle,
311 .{ .TYPE = .PRIVATE, .FIXED = true },311 ph.p_offset - extra_bytes,
312 file.handle,312 );
313 ph.p_offset - extra_bytes,
314 );
315 } else {
316 const sect_mem = try posix.mmap(
317 ptr,
318 extended_memsz,
319 prot,
320 .{ .TYPE = .PRIVATE, .FIXED = true, .ANONYMOUS = true },
321 -1,
322 0,
323 );
324 @memcpy(sect_mem[0..ph.p_filesz], file_bytes[0..ph.p_filesz]);
325 }
326 },313 },
327 else => {},314 else => {},
328 }315 }
test/standalone/load_dynamic_library/add.zig deleted-3
...@@ -1,3 +0,0 @@
1export fn add(a: i32, b: i32) i32 {
2 return a + b;
3}
test/standalone/load_dynamic_library/build.zig+6-2
...@@ -11,12 +11,16 @@ pub fn build(b: *std.Build) void {...@@ -11,12 +11,16 @@ pub fn build(b: *std.Build) void {
11 if (builtin.os.tag == .wasi) return;11 if (builtin.os.tag == .wasi) return;
12 if (builtin.os.tag == .windows) return;12 if (builtin.os.tag == .windows) return;
1313
14 // ld and lld do not agree on the format of the .hash section
15 // Tracked by https://codeberg.org/ziglang/zig/issues/35746
16 if (builtin.cpu.arch == .s390x and builtin.os.tag == .linux) return;
17
14 const lib = b.addLibrary(.{18 const lib = b.addLibrary(.{
15 .linkage = .dynamic,19 .linkage = .dynamic,
16 .name = "add",20 .name = "lib",
17 .version = .{ .major = 1, .minor = 0, .patch = 0 },21 .version = .{ .major = 1, .minor = 0, .patch = 0 },
18 .root_module = b.createModule(.{22 .root_module = b.createModule(.{
19 .root_source_file = b.path("add.zig"),23 .root_source_file = b.path("lib.zig"),
20 .optimize = optimize,24 .optimize = optimize,
21 .target = target,25 .target = target,
22 }),26 }),
test/standalone/load_dynamic_library/lib.zig created+8
...@@ -0,0 +1,8 @@
1export fn addInts(a: i32, b: i32) i32 {
2 return a + b;
3}
4
5var forty_two: i32 = 42;
6export fn fortyTwo() i32 {
7 return forty_two;
8}
test/standalone/load_dynamic_library/main.zig+6-4
...@@ -8,9 +8,11 @@ pub fn main(init: std.process.Init) !void {...@@ -8,9 +8,11 @@ pub fn main(init: std.process.Init) !void {
8 var lib = try std.DynLib.open(dynlib_name);8 var lib = try std.DynLib.open(dynlib_name);
9 defer lib.close();9 defer lib.close();
1010
11 const Add = *const fn (i32, i32) callconv(.c) i32;11 const AddInts = *const fn (i32, i32) callconv(.c) i32;
12 const addFn = lib.lookup(Add, "add") orelse return error.SymbolNotFound;12 const addInts = lib.lookup(AddInts, "addInts").?;
13 std.debug.assert(addInts(12, 34) == 46);
1314
14 const result = addFn(12, 34);15 const FortyTwo = *const fn () callconv(.c) i32;
15 std.debug.assert(result == 46);16 const fortyTwo = lib.lookup(FortyTwo, "fortyTwo").?;
17 std.debug.assert(fortyTwo() == 42);
16}18}