Skip to content

Commit

Permalink
tools/nolibc: restore mips branch ordering in the _start block
Browse files Browse the repository at this point in the history
[ Upstream commit 184177c ]

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: 66b6f75 ("rcutorture: Import a copy of nolibc") #5.0
Signed-off-by: Willy Tarreau <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
wtarreau authored and gregkh committed Jan 18, 2023
1 parent bd0431a commit 1e6ec75
Showing 1 changed file with 2 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tools/include/nolibc/arch-mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct sys_stat_struct {
asm(".section .text\n"
".weak __start\n"
".set nomips16\n"
".set push\n"
".set noreorder\n"
".option pic0\n"
".ent __start\n"
Expand All @@ -210,6 +211,7 @@ asm(".section .text\n"
"li $v0, 4001\n" // NR_exit == 4001
"syscall\n"
".end __start\n"
".set pop\n"
"");

#endif // _NOLIBC_ARCH_MIPS_H

0 comments on commit 1e6ec75

Please sign in to comment.