authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-07-21 22:31:59+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-07-21 22:38:14+02:00
logecd459b8647a1b7cade31f0286694e14101f80f4
tree46c47af6afb0e7c568d0ce52050c02d097542064
parent08cddaf11c7bac5fba2e696ed6b99d1f7b730543
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

start: Avoid going through the argc_argv_ptr global variable.

This is problematic for PIE. There's nothing but luck preventing the accesses to this global variable from requiring relocations. I've observed this being an issue on MIPS and PowerPC personally, but others may be affected. Besides, we're really just passing the initial stack pointer value to posixCallMainAndExit(), so... just do that.

1 files changed, 14 insertions(+), 15 deletions(-)

lib/std/start.zig+14-15
......@@ -9,8 +9,6 @@ const elf = std.elf;
99const native_arch = builtin.cpu.arch;
1010const native_os = builtin.os.tag;
1111
12var argc_argv_ptr: [*]usize = undefined;
13
1412const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
1513
1614// The self-hosted compiler is not fully capable of handling all of this start.zig file.
......@@ -277,41 +275,42 @@ fn _start() callconv(.Naked) noreturn {
277275 asm volatile (switch (native_arch) {
278276 .x86_64 =>
279277 \\ xorl %%ebp, %%ebp
280 \\ movq %%rsp, %[argc_argv_ptr]
278 \\ movq %%rsp, %%rdi
281279 \\ andq $-16, %%rsp
282280 \\ callq %[posixCallMainAndExit:P]
283281 ,
284282 .x86 =>
285283 \\ xorl %%ebp, %%ebp
286 \\ movl %%esp, %[argc_argv_ptr]
284 \\ movl %%esp, %%eax
287285 \\ andl $-16, %%esp
286 \\ subl $12, %%esp
287 \\ pushl %%eax
288288 \\ calll %[posixCallMainAndExit:P]
289289 ,
290290 .aarch64, .aarch64_be =>
291291 \\ mov fp, #0
292292 \\ mov lr, #0
293293 \\ mov x0, sp
294 \\ str x0, %[argc_argv_ptr]
295294 \\ b %[posixCallMainAndExit]
296295 ,
297296 .arm, .armeb, .thumb, .thumbeb =>
298297 \\ mov fp, #0
299298 \\ mov lr, #0
300 \\ str sp, %[argc_argv_ptr]
299 \\ mov a1, sp
301300 \\ and sp, #-16
302301 \\ b %[posixCallMainAndExit]
303302 ,
304303 .riscv64 =>
305304 \\ li s0, 0
306305 \\ li ra, 0
307 \\ sd sp, %[argc_argv_ptr]
306 \\ mv a0, sp
308307 \\ andi sp, sp, -16
309308 \\ tail %[posixCallMainAndExit]@plt
310309 ,
311310 .mips, .mipsel =>
312311 // The lr is already zeroed on entry, as specified by the ABI.
313312 \\ addiu $fp, $zero, 0
314 \\ sw $sp, %[argc_argv_ptr]
313 \\ move $a0, $sp
315314 \\ .set push
316315 \\ .set noat
317316 \\ addiu $1, $zero, -16
......@@ -322,7 +321,7 @@ fn _start() callconv(.Naked) noreturn {
322321 .mips64, .mips64el =>
323322 // The lr is already zeroed on entry, as specified by the ABI.
324323 \\ addiu $fp, $zero, 0
325 \\ sd $sp, %[argc_argv_ptr]
324 \\ move $a0, $sp
326325 \\ .set push
327326 \\ .set noat
328327 \\ daddiu $1, $zero, -16
......@@ -332,7 +331,7 @@ fn _start() callconv(.Naked) noreturn {
332331 ,
333332 .powerpc, .powerpcle =>
334333 // Setup the initial stack frame and clear the back chain pointer.
335 \\ stw 1, %[argc_argv_ptr]
334 \\ mr 3, 1
336335 \\ li 0, 0
337336 \\ stwu 1, -16(1)
338337 \\ stw 0, 0(1)
......@@ -342,7 +341,7 @@ fn _start() callconv(.Naked) noreturn {
342341 .powerpc64, .powerpc64le =>
343342 // Setup the initial stack frame and clear the back chain pointer.
344343 // TODO: Support powerpc64 (big endian) on ELFv2.
345 \\ std 1, %[argc_argv_ptr]
344 \\ mr 3, 1
346345 \\ li 0, 0
347346 \\ stdu 0, -32(1)
348347 \\ mtlr 0
......@@ -352,12 +351,12 @@ fn _start() callconv(.Naked) noreturn {
352351 // argc is stored after a register window (16 registers) plus stack bias
353352 \\ mov %%g0, %%i6
354353 \\ add %%o6, 2175, %%l0
355 \\ ba %[posixCallMainAndExit]
356 \\ stx %%l0, %[argc_argv_ptr]
354 \\ mov %%l0, %%o0
355 \\ ba,a %[posixCallMainAndExit]
357356 ,
358357 else => @compileError("unsupported arch"),
359358 }
360 : [argc_argv_ptr] "=m" (argc_argv_ptr),
359 :
361360 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),
362361 );
363362}
......@@ -385,7 +384,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
385384 std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result)));
386385}
387386
388fn posixCallMainAndExit() callconv(.C) noreturn {
387fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.C) noreturn {
389388 const argc = argc_argv_ptr[0];
390389 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
391390