1#if (defined(__riscv) && (__riscv_xlen == 64)) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
6
7.comm _ZN14__interception10real_vforkE,8,8
8.globl ASM_WRAPPER_NAME(vfork)
9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
10ASM_WRAPPER_NAME(vfork):
11 // Save ra in the off-stack spill area.
12 // allocate space on stack
13 addi sp, sp, -16
14 // store ra value
15 sd ra, 8(sp)
16 call COMMON_INTERCEPTOR_SPILL_AREA
17 // restore previous values from stack
18 ld ra, 8(sp)
19 // adjust stack
20 addi sp, sp, 16
21 // store ra by x10
22 sd ra, 0(x10)
23
24 // Call real vfork. This may return twice. User code that runs between the first and the second return
25 // may clobber the stack frame of the interceptor; that's why it does not have a frame.
26 la x10, _ZN14__interception10real_vforkE
27 ld x10, 0(x10)
28 jalr x10
29
30 // adjust stack
31 addi sp, sp, -16
32 // store x10 by adjusted stack
33 sd x10, 8(sp)
34 // jump to exit label if x10 is 0
35 beqz x10, .L_exit
36
37 // x0 != 0 => parent process. Clear stack shadow.
38 // put old sp to x10
39 addi x10, sp, 16
40 call COMMON_INTERCEPTOR_HANDLE_VFORK
41
42.L_exit:
43 // Restore ra
44 call COMMON_INTERCEPTOR_SPILL_AREA
45 ld ra, 0(x10)
46 // load value by stack
47 ld x10, 8(sp)
48 // adjust stack
49 addi sp, sp, 16
50 ret
51ASM_SIZE(vfork)
52
53ASM_INTERCEPTOR_TRAMPOLINE(vfork)
54ASM_TRAMPOLINE_ALIAS(vfork, vfork)
55
56#endif
57