blob: 5b6ea6fe6c7adeb290184f6c3adb4a7b350c2474 [file] [log] [blame]
#if (defined(__riscv) && (__riscv_xlen == 64)) && defined(__linux__)
#include "sanitizer_common/sanitizer_asm.h"
ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
.comm _ZN14__interception10real_vforkE,8,8
.globl ASM_WRAPPER_NAME(vfork)
ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
ASM_WRAPPER_NAME(vfork):
// Save ra in the off-stack spill area.
// allocate space on stack
addi sp, sp, -16
// store ra value
sd ra, 8(sp)
call COMMON_INTERCEPTOR_SPILL_AREA
// restore previous values from stack
ld ra, 8(sp)
// adjust stack
addi sp, sp, 16
// store ra by x10
sd ra, 0(x10)
// Call real vfork. This may return twice. User code that runs between the first and the second return
// may clobber the stack frame of the interceptor; that's why it does not have a frame.
la x10, _ZN14__interception10real_vforkE
ld x10, 0(x10)
jalr x10
// adjust stack
addi sp, sp, -16
// store x10 by adjusted stack
sd x10, 8(sp)
// jump to exit label if x10 is 0
beqz x10, .L_exit
// x0 != 0 => parent process. Clear stack shadow.
// put old sp to x10
addi x10, sp, 16
call COMMON_INTERCEPTOR_HANDLE_VFORK
.L_exit:
// Restore ra
call COMMON_INTERCEPTOR_SPILL_AREA
ld ra, 0(x10)
// load value by stack
ld x10, 8(sp)
// adjust stack
addi sp, sp, 16
ret
ASM_SIZE(vfork)
ASM_INTERCEPTOR_TRAMPOLINE(vfork)
ASM_TRAMPOLINE_ALIAS(vfork, vfork)
#endif