@@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn {
272
272
: [tos ] "={rax}" (- > * std .os .plan9 .Tos ),
273
273
);
274
274
}
275
+
276
+ // Note that we maintain a very low level of trust with regards to ABI guarantees at this point.
277
+ // We will redundantly align the stack, clear the link register, etc. While e.g. the Linux
278
+ // kernel is usually good about upholding the ABI guarantees, the same cannot be said of dynamic
279
+ // linkers; musl's ldso, for example, opts to not align the stack when invoking the dynamic
280
+ // linker explicitly.
275
281
asm volatile (switch (native_arch ) {
276
282
.x86_64 = >
277
283
\\ xorl %%ebp, %%ebp
@@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn {
291
297
\\ mov fp, #0
292
298
\\ mov lr, #0
293
299
\\ mov x0, sp
300
+ \\ and sp, x0, #-16
294
301
\\ b %[posixCallMainAndExit]
295
302
,
296
303
.arm , .armeb , .thumb , .thumbeb = >
@@ -322,38 +329,31 @@ fn _start() callconv(.Naked) noreturn {
322
329
\\ jsr (%%pc, %%a0)
323
330
,
324
331
.mips , .mipsel = >
325
- // The lr is already zeroed on entry, as specified by the ABI.
326
- \\ addiu $fp , $zero, 0
332
+ \\ move $fp, $0
333
+ \\ move $ra , $0
327
334
\\ move $a0, $sp
328
- \\ .set push
329
- \\ .set noat
330
- \\ addiu $1, $zero, -16
331
- \\ and $sp, $sp, $1
332
- \\ .set pop
335
+ \\ and $sp, -8
333
336
\\ j %[posixCallMainAndExit]
334
337
,
335
338
.mips64 , .mips64el = >
336
- // The lr is already zeroed on entry, as specified by the ABI.
337
- \\ addiu $fp , $zero, 0
339
+ \\ move $fp, $0
340
+ \\ move $ra , $0
338
341
\\ move $a0, $sp
339
- \\ .set push
340
- \\ .set noat
341
- \\ daddiu $1, $zero, -16
342
- \\ and $sp, $sp, $1
343
- \\ .set pop
342
+ \\ and $sp, -16
344
343
\\ j %[posixCallMainAndExit]
345
344
,
346
345
.powerpc , .powerpcle = >
347
- // Setup the initial stack frame and clear the back chain pointer.
346
+ // Set up the initial stack frame, and clear the back chain pointer.
348
347
\\ mr 3, 1
348
+ \\ clrrwi 1, 1, 4
349
349
\\ li 0, 0
350
350
\\ stwu 1, -16(1)
351
351
\\ stw 0, 0(1)
352
352
\\ mtlr 0
353
353
\\ b %[posixCallMainAndExit]
354
354
,
355
355
.powerpc64 , .powerpc64le = >
356
- // Setup the initial stack frame and clear the back chain pointer.
356
+ // Set up the ToC and initial stack frame, and clear the back chain pointer.
357
357
\\ addis 2, 12, .TOC. - %[_start]@ha
358
358
\\ addi 2, 2, .TOC. - %[_start]@l
359
359
\\ mr 3, 1
@@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn {
365
365
,
366
366
.s390x = >
367
367
// Set up the stack frame (register save area and cleared back-chain slot).
368
- // Note: Stack pointer is guaranteed by ABI to be 8-byte aligned as required.
369
- \\ lgr %r2, %r15
370
- \\ aghi %r15, -160
371
- \\ lghi %r0, 0
372
- \\ stg %r0, 0(%r15)
368
+ \\ lgr %%r2, %%r15
369
+ \\ lghi %%r0, -16
370
+ \\ ngr %%r15, %%r0
371
+ \\ aghi %%r15, -160
372
+ \\ lghi %%r0, 0
373
+ \\ stg %%r0, 0(%%r15)
373
374
\\ jg %[posixCallMainAndExit]
374
375
,
375
376
.sparc64 = >
376
- // argc is stored after a register window (16 registers) plus stack bias
377
- \\ mov %%g0, %%i6
378
- \\ add %%o6, 2175, %%l0
379
- \\ mov %%l0, %%o0
377
+ // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
378
+ // (2047 bytes).
379
+ \\ mov %%g0, %%fp
380
+ \\ add %%sp, 2175, %%o0
381
+ \\ add %%sp, 2047, %%sp
382
+ \\ and %%sp, -16, %%sp
383
+ \\ sub %%sp, 2047, %%sp
380
384
\\ ba,a %[posixCallMainAndExit]
381
385
,
382
386
else = > @compileError ("unsupported arch" ),
0 commit comments