From ac1d7381e43f33fce772f856f492c5d445f39b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 18 May 2025 02:01:37 +0200 Subject: [PATCH] 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. --- lib/std/os/linux.zig | 1 - lib/std/{os/linux => }/pie.zig | 0 lib/std/start.zig | 76 +++++++++++++++++----------------- lib/std/std.zig | 1 + 4 files changed, 39 insertions(+), 39 deletions(-) rename lib/std/{os/linux => }/pie.zig (100%) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 142c8d4e4a32..e5b2696f8098 100644 --- a/lib/std/os/linux.zig +++ b/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"); diff --git a/lib/std/os/linux/pie.zig b/lib/std/pie.zig similarity index 100% rename from lib/std/os/linux/pie.zig rename to lib/std/pie.zig diff --git a/lib/std/start.zig b/lib/std/start.zig index 6495db1c51a6..477e24bb557c 100644 --- a/lib/std/start.zig +++ b/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)); diff --git a/lib/std/std.zig b/lib/std/std.zig index 94851657a680..5f13b931d1d1 100644 --- a/lib/std/std.zig +++ b/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");