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;...@@ -9,8 +9,6 @@ const elf = std.elf;
9const native_arch = builtin.cpu.arch;9const native_arch = builtin.cpu.arch;
10const native_os = builtin.os.tag;10const native_os = builtin.os.tag;
1111
12var argc_argv_ptr: [*]usize = undefined;
13
14const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";12const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
1513
16// The self-hosted compiler is not fully capable of handling all of this start.zig file.14// 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 {...@@ -277,41 +275,42 @@ fn _start() callconv(.Naked) noreturn {
277 asm volatile (switch (native_arch) {275 asm volatile (switch (native_arch) {
278 .x86_64 =>276 .x86_64 =>
279 \\ xorl %%ebp, %%ebp277 \\ xorl %%ebp, %%ebp
280 \\ movq %%rsp, %[argc_argv_ptr]278 \\ movq %%rsp, %%rdi
281 \\ andq $-16, %%rsp279 \\ andq $-16, %%rsp
282 \\ callq %[posixCallMainAndExit:P]280 \\ callq %[posixCallMainAndExit:P]
283 ,281 ,
284 .x86 =>282 .x86 =>
285 \\ xorl %%ebp, %%ebp283 \\ xorl %%ebp, %%ebp
286 \\ movl %%esp, %[argc_argv_ptr]284 \\ movl %%esp, %%eax
287 \\ andl $-16, %%esp285 \\ andl $-16, %%esp
286 \\ subl $12, %%esp
287 \\ pushl %%eax
288 \\ calll %[posixCallMainAndExit:P]288 \\ calll %[posixCallMainAndExit:P]
289 ,289 ,
290 .aarch64, .aarch64_be =>290 .aarch64, .aarch64_be =>
291 \\ mov fp, #0291 \\ mov fp, #0
292 \\ mov lr, #0292 \\ mov lr, #0
293 \\ mov x0, sp293 \\ mov x0, sp
294 \\ str x0, %[argc_argv_ptr]
295 \\ b %[posixCallMainAndExit]294 \\ b %[posixCallMainAndExit]
296 ,295 ,
297 .arm, .armeb, .thumb, .thumbeb =>296 .arm, .armeb, .thumb, .thumbeb =>
298 \\ mov fp, #0297 \\ mov fp, #0
299 \\ mov lr, #0298 \\ mov lr, #0
300 \\ str sp, %[argc_argv_ptr]299 \\ mov a1, sp
301 \\ and sp, #-16300 \\ and sp, #-16
302 \\ b %[posixCallMainAndExit]301 \\ b %[posixCallMainAndExit]
303 ,302 ,
304 .riscv64 =>303 .riscv64 =>
305 \\ li s0, 0304 \\ li s0, 0
306 \\ li ra, 0305 \\ li ra, 0
307 \\ sd sp, %[argc_argv_ptr]306 \\ mv a0, sp
308 \\ andi sp, sp, -16307 \\ andi sp, sp, -16
309 \\ tail %[posixCallMainAndExit]@plt308 \\ tail %[posixCallMainAndExit]@plt
310 ,309 ,
311 .mips, .mipsel =>310 .mips, .mipsel =>
312 // The lr is already zeroed on entry, as specified by the ABI.311 // The lr is already zeroed on entry, as specified by the ABI.
313 \\ addiu $fp, $zero, 0312 \\ addiu $fp, $zero, 0
314 \\ sw $sp, %[argc_argv_ptr]313 \\ move $a0, $sp
315 \\ .set push314 \\ .set push
316 \\ .set noat315 \\ .set noat
317 \\ addiu $1, $zero, -16316 \\ addiu $1, $zero, -16
...@@ -322,7 +321,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -322,7 +321,7 @@ fn _start() callconv(.Naked) noreturn {
322 .mips64, .mips64el =>321 .mips64, .mips64el =>
323 // The lr is already zeroed on entry, as specified by the ABI.322 // The lr is already zeroed on entry, as specified by the ABI.
324 \\ addiu $fp, $zero, 0323 \\ addiu $fp, $zero, 0
325 \\ sd $sp, %[argc_argv_ptr]324 \\ move $a0, $sp
326 \\ .set push325 \\ .set push
327 \\ .set noat326 \\ .set noat
328 \\ daddiu $1, $zero, -16327 \\ daddiu $1, $zero, -16
...@@ -332,7 +331,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -332,7 +331,7 @@ fn _start() callconv(.Naked) noreturn {
332 ,331 ,
333 .powerpc, .powerpcle =>332 .powerpc, .powerpcle =>
334 // Setup the initial stack frame and clear the back chain pointer.333 // Setup the initial stack frame and clear the back chain pointer.
335 \\ stw 1, %[argc_argv_ptr]334 \\ mr 3, 1
336 \\ li 0, 0335 \\ li 0, 0
337 \\ stwu 1, -16(1)336 \\ stwu 1, -16(1)
338 \\ stw 0, 0(1)337 \\ stw 0, 0(1)
...@@ -342,7 +341,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -342,7 +341,7 @@ fn _start() callconv(.Naked) noreturn {
342 .powerpc64, .powerpc64le =>341 .powerpc64, .powerpc64le =>
343 // Setup the initial stack frame and clear the back chain pointer.342 // Setup the initial stack frame and clear the back chain pointer.
344 // TODO: Support powerpc64 (big endian) on ELFv2.343 // TODO: Support powerpc64 (big endian) on ELFv2.
345 \\ std 1, %[argc_argv_ptr]344 \\ mr 3, 1
346 \\ li 0, 0345 \\ li 0, 0
347 \\ stdu 0, -32(1)346 \\ stdu 0, -32(1)
348 \\ mtlr 0347 \\ mtlr 0
...@@ -352,12 +351,12 @@ fn _start() callconv(.Naked) noreturn {...@@ -352,12 +351,12 @@ fn _start() callconv(.Naked) noreturn {
352 // argc is stored after a register window (16 registers) plus stack bias351 // argc is stored after a register window (16 registers) plus stack bias
353 \\ mov %%g0, %%i6352 \\ mov %%g0, %%i6
354 \\ add %%o6, 2175, %%l0353 \\ add %%o6, 2175, %%l0
355 \\ ba %[posixCallMainAndExit]354 \\ mov %%l0, %%o0
356 \\ stx %%l0, %[argc_argv_ptr]355 \\ ba,a %[posixCallMainAndExit]
357 ,356 ,
358 else => @compileError("unsupported arch"),357 else => @compileError("unsupported arch"),
359 }358 }
360 : [argc_argv_ptr] "=m" (argc_argv_ptr),359 :
361 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),360 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),
362 );361 );
363}362}
...@@ -385,7 +384,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {...@@ -385,7 +384,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
385 std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result)));384 std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result)));
386}385}
387386
388fn posixCallMainAndExit() callconv(.C) noreturn {387fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.C) noreturn {
389 const argc = argc_argv_ptr[0];388 const argc = argc_argv_ptr[0];
390 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));389 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
391390