@@ -289,17 +289,42 @@ fn _start() callconv(.Naked) noreturn {
289
289
,
290
290
.mips , .mipsel = >
291
291
\\ move $fp, $0
292
+ \\ bal 1f
293
+ \\ .gpword .
294
+ \\ .gpword %[posixCallMainAndExit]
295
+ \\ 1:
296
+ \\ lw $gp, 0($ra)
297
+ \\ subu $gp, $ra, $gp
298
+ \\ lw $25, 4($ra)
299
+ \\ addu $25, $25, $gp
292
300
\\ move $ra, $0
293
301
\\ move $a0, $sp
294
302
\\ and $sp, -8
295
- \\ j %[posixCallMainAndExit]
303
+ \\ subu $sp, $sp, 16
304
+ \\ jalr $25
296
305
,
297
306
.mips64 , .mips64el = >
298
307
\\ move $fp, $0
308
+ // This is needed because early MIPS versions don't support misaligned loads. Without
309
+ // this directive, the hidden `nop` inserted to fill the delay slot after `bal` would
310
+ // cause the two doublewords to be aligned to 4 bytes instead of 8.
311
+ \\ .balign 8
312
+ \\ bal 1f
313
+ \\ .gpdword .
314
+ \\ .gpdword %[posixCallMainAndExit]
315
+ \\ 1:
316
+ // The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64.
317
+ // We need to set it up in order for dynamically-linked / position-independent code to
318
+ // work.
319
+ \\ ld $gp, 0($ra)
320
+ \\ dsubu $gp, $ra, $gp
321
+ \\ ld $25, 8($ra)
322
+ \\ daddu $25, $25, $gp
299
323
\\ move $ra, $0
300
324
\\ move $a0, $sp
301
325
\\ and $sp, -16
302
- \\ j %[posixCallMainAndExit]
326
+ \\ dsubu $sp, $sp, 16
327
+ \\ jalr $25
303
328
,
304
329
.powerpc , .powerpcle = >
305
330
// Set up the initial stack frame, and clear the back chain pointer.
@@ -389,7 +414,6 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.C) noreturn {
389
414
if (native_os == .linux ) {
390
415
// Find the beginning of the auxiliary vector
391
416
const auxv : [* ]elf.Auxv = @ptrCast (@alignCast (envp .ptr + envp_count + 1 ));
392
- std .os .linux .elf_aux_maybe = auxv ;
393
417
394
418
var at_hwcap : usize = 0 ;
395
419
const phdrs = init : {
@@ -407,12 +431,17 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.C) noreturn {
407
431
break :init @as ([* ]elf .Phdr , @ptrFromInt (at_phdr ))[0.. at_phnum ];
408
432
};
409
433
410
- // Apply the initial relocations as early as possible in the startup
411
- // process.
434
+ // Apply the initial relocations as early as possible in the startup process. We cannot
435
+ // make calls yet on some architectures (e.g. MIPS) *because* they haven't been applied yet,
436
+ // so this must be fully inlined.
412
437
if (builtin .position_independent_executable ) {
413
- std .os .linux .pie .relocate ( phdrs );
438
+ @call ( .always_inline , std .os .linux .pie .relocate , .{ phdrs } );
414
439
}
415
440
441
+ // This must be done after PIE relocations have been applied or we may crash
442
+ // while trying to access the global variable (happens on MIPS at least).
443
+ std .os .linux .elf_aux_maybe = auxv ;
444
+
416
445
if (! builtin .single_threaded ) {
417
446
// ARMv6 targets (and earlier) have no support for TLS in hardware.
418
447
// FIXME: Elide the check for targets >= ARMv7 when the target feature API
0 commit comments