Commit 74a3ae4927

Alex Rønne Petersen <alex@alexrp.com>
2025-05-18 02:01:37
start: Don't artificially limit some posixCallMainAndExit() logic to Linux.
This code applies to ~any POSIX OS where we don't link libc. For example, it'll be useful for FreeBSD and NetBSD. As part of this, move std.os.linux.pie to std.pie since there's really nothing Linux-specific about what that file is doing.
1 parent 8e72a25
Changed files (4)
lib/std/os/linux.zig
@@ -115,7 +115,6 @@ pub const user_desc = arch_bits.user_desc;
 pub const getcontext = arch_bits.getcontext;
 
 pub const tls = @import("linux/tls.zig");
-pub const pie = @import("linux/pie.zig");
 pub const BPF = @import("linux/bpf.zig");
 pub const IOCTL = @import("linux/ioctl.zig");
 pub const SECCOMP = @import("linux/seccomp.zig");
lib/std/os/linux/pie.zig → lib/std/pie.zig
File renamed without changes
lib/std/start.zig
@@ -325,7 +325,7 @@ fn _start() callconv(.naked) noreturn {
             ,
             .csky =>
             // The CSKY ABI assumes that `gb` is set to the address of the GOT in order for
-            // position-independent code to work. We depend on this in `std.os.linux.pie` to locate
+            // position-independent code to work. We depend on this in `std.pie` to locate
             // `_DYNAMIC` as well.
             // r8 = FP
             \\ grs t0, 1f
@@ -514,33 +514,33 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
     while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
     const envp = @as([*][*:0]u8, @ptrCast(envp_optional))[0..envp_count];
 
-    if (native_os == .linux) {
-        // Find the beginning of the auxiliary vector
-        const auxv: [*]elf.Auxv = @ptrCast(@alignCast(envp.ptr + envp_count + 1));
-
-        var at_hwcap: usize = 0;
-        const phdrs = init: {
-            var i: usize = 0;
-            var at_phdr: usize = 0;
-            var at_phnum: usize = 0;
-            while (auxv[i].a_type != elf.AT_NULL) : (i += 1) {
-                switch (auxv[i].a_type) {
-                    elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
-                    elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
-                    elf.AT_HWCAP => at_hwcap = auxv[i].a_un.a_val,
-                    else => continue,
-                }
+    // Find the beginning of the auxiliary vector
+    const auxv: [*]elf.Auxv = @ptrCast(@alignCast(envp.ptr + envp_count + 1));
+
+    var at_hwcap: usize = 0;
+    const phdrs = init: {
+        var i: usize = 0;
+        var at_phdr: usize = 0;
+        var at_phnum: usize = 0;
+        while (auxv[i].a_type != elf.AT_NULL) : (i += 1) {
+            switch (auxv[i].a_type) {
+                elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
+                elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
+                elf.AT_HWCAP => at_hwcap = auxv[i].a_un.a_val,
+                else => continue,
             }
-            break :init @as([*]elf.Phdr, @ptrFromInt(at_phdr))[0..at_phnum];
-        };
-
-        // Apply the initial relocations as early as possible in the startup process. We cannot
-        // make calls yet on some architectures (e.g. MIPS) *because* they haven't been applied yet,
-        // so this must be fully inlined.
-        if (builtin.position_independent_executable) {
-            @call(.always_inline, std.os.linux.pie.relocate, .{phdrs});
         }
+        break :init @as([*]elf.Phdr, @ptrFromInt(at_phdr))[0..at_phnum];
+    };
+
+    // Apply the initial relocations as early as possible in the startup process. We cannot
+    // make calls yet on some architectures (e.g. MIPS) *because* they haven't been applied yet,
+    // so this must be fully inlined.
+    if (builtin.position_independent_executable) {
+        @call(.always_inline, std.pie.relocate, .{phdrs});
+    }
 
+    if (native_os == .linux) {
         // This must be done after PIE relocations have been applied or we may crash
         // while trying to access the global variable (happens on MIPS at least).
         std.os.linux.elf_aux_maybe = auxv;
@@ -567,20 +567,20 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
         // Here we look for the stack size in our program headers and use setrlimit
         // to ask for more stack space.
         expandStackSize(phdrs);
+    }
 
-        const opt_init_array_start = @extern([*]*const fn () callconv(.c) void, .{
-            .name = "__init_array_start",
-            .linkage = .weak,
-        });
-        const opt_init_array_end = @extern([*]*const fn () callconv(.c) void, .{
-            .name = "__init_array_end",
-            .linkage = .weak,
-        });
-        if (opt_init_array_start) |init_array_start| {
-            const init_array_end = opt_init_array_end.?;
-            const slice = init_array_start[0 .. init_array_end - init_array_start];
-            for (slice) |func| func();
-        }
+    const opt_init_array_start = @extern([*]*const fn () callconv(.c) void, .{
+        .name = "__init_array_start",
+        .linkage = .weak,
+    });
+    const opt_init_array_end = @extern([*]*const fn () callconv(.c) void, .{
+        .name = "__init_array_end",
+        .linkage = .weak,
+    });
+    if (opt_init_array_start) |init_array_start| {
+        const init_array_end = opt_init_array_end.?;
+        const slice = init_array_start[0 .. init_array_end - init_array_start];
+        for (slice) |func| func();
     }
 
     std.posix.exit(callMainWithArgs(argc, argv, envp));
lib/std/std.zig
@@ -79,6 +79,7 @@ pub const net = @import("net.zig");
 pub const os = @import("os.zig");
 pub const once = @import("once.zig").once;
 pub const pdb = @import("pdb.zig");
+pub const pie = @import("pie.zig");
 pub const posix = @import("posix.zig");
 pub const process = @import("process.zig");
 pub const sort = @import("sort.zig");