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 {
302302 const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);
303303 const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));
304304 const prot = elfToProt(ph.p_flags);
305 if ((ph.p_flags & elf.PF_W) == 0) {
306 // If it does not need write access, it can be mapped from the fd.
307 _ = try posix.mmap(
308 ptr,
309 extended_memsz,
310 prot,
311 .{ .TYPE = .PRIVATE, .FIXED = true },
312 file.handle,
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 }
305 _ = try posix.mmap(
306 ptr,
307 extended_memsz,
308 prot,
309 .{ .TYPE = .PRIVATE, .FIXED = true },
310 file.handle,
311 ph.p_offset - extra_bytes,
312 );
326313 },
327314 else => {},
328315 }
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 {
1111 if (builtin.os.tag == .wasi) return;
1212 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
1418 const lib = b.addLibrary(.{
1519 .linkage = .dynamic,
16 .name = "add",
20 .name = "lib",
1721 .version = .{ .major = 1, .minor = 0, .patch = 0 },
1822 .root_module = b.createModule(.{
19 .root_source_file = b.path("add.zig"),
23 .root_source_file = b.path("lib.zig"),
2024 .optimize = optimize,
2125 .target = target,
2226 }),
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 {
88 var lib = try std.DynLib.open(dynlib_name);
99 defer lib.close();
1010
11 const Add = *const fn (i32, i32) callconv(.c) i32;
12 const addFn = lib.lookup(Add, "add") orelse return error.SymbolNotFound;
11 const AddInts = *const fn (i32, i32) callconv(.c) i32;
12 const addInts = lib.lookup(AddInts, "addInts").?;
13 std.debug.assert(addInts(12, 34) == 46);
1314
14 const result = addFn(12, 34);
15 std.debug.assert(result == 46);
15 const FortyTwo = *const fn () callconv(.c) i32;
16 const fortyTwo = lib.lookup(FortyTwo, "fortyTwo").?;
17 std.debug.assert(fortyTwo() == 42);
1618}