Skip to content

Commit ecd459b

Browse files
committed
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 parent 08cddaf commit ecd459b

File tree

1 file changed

+14
-15
lines changed

1 file changed

+14
-15
lines changed

lib/std/start.zig

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ const elf = std.elf;
99
const native_arch = builtin.cpu.arch;
1010
const native_os = builtin.os.tag;
1111

12-
var argc_argv_ptr: [*]usize = undefined;
13-
1412
const 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

388-
fn posixCallMainAndExit() callconv(.C) noreturn {
387+
fn 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

0 commit comments

Comments
 (0)