• Willy Tarreau's avatar
    tools/nolibc: restore mips branch ordering in the _start block · 184177c3
    Willy Tarreau authored
    Depending on the compiler used and the optimization options, the sbrk()
    test was crashing, both on real hardware (mips-24kc) and in qemu. One
    such example is kernel.org toolchain in version 11.3 optimizing at -Os.
    
    Inspecting the sys_brk() call shows the following code:
    
      0040047c <sys_brk>:
        40047c:       24020fcd        li      v0,4045
        400480:       27bdffe0        addiu   sp,sp,-32
        400484:       0000000c        syscall
        400488:       27bd0020        addiu   sp,sp,32
        40048c:       10e00001        beqz    a3,400494 <sys_brk+0x18>
        400490:       00021023        negu    v0,v0
        400494:       03e00008        jr      ra
    
    It is obviously wrong, the "negu" instruction is placed in beqz's
    delayed slot, and worse, there's no nop nor instruction after the
    return, so the next function's first instruction (addiu sip,sip,-32)
    will also be executed as part of the delayed slot that follows the
    return.
    
    This is caused by the ".set noreorder" directive in the _start block,
    that applies to the whole program. The compiler emits code without the
    delayed slots and relies on the compiler to swap instructions when this
    option is not set. Removing the option would require to change the
    startup code in a way that wouldn't make it look like the resulting
    code, which would not be easy to debug. Instead let's just save the
    default ordering before changing it, and restore it at the end of the
    _start block. Now the code is correct:
    
      0040047c <sys_brk>:
        40047c:       24020fcd        li      v0,4045
        400480:       27bdffe0        addiu   sp,sp,-32
        400484:       0000000c        syscall
        400488:       10e00002        beqz    a3,400494 <sys_brk+0x18>
        40048c:       27bd0020        addiu   sp,sp,32
        400490:       00021023        negu    v0,v0
        400494:       03e00008        jr      ra
        400498:       00000000        nop
    
    Fixes: 66b6f755 ("rcutorture: Import a copy of nolibc") #5.0
    Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
    Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
    184177c3
arch-mips.h 10.8 KB