1#if defined(__aarch64__) && 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 x30 in the off-stack spill area.
12        stp     xzr, x30, [sp, #-16]!
13        bl      COMMON_INTERCEPTOR_SPILL_AREA
14        ldp     xzr, x30, [sp], 16
15        str     x30, [x0]
16
17        // Call real vfork. This may return twice. User code that runs between the first and the second return
18        // may clobber the stack frame of the interceptor; that's why it does not have a frame.
19        adrp    x0, _ZN14__interception10real_vforkE
20        ldr     x0, [x0, :lo12:_ZN14__interception10real_vforkE]
21        blr     x0
22
23        stp     x0, xzr, [sp, #-16]!
24        cmp     x0, #0
25        b.eq   .L_exit
26
27        // x0 != 0 => parent process. Clear stack shadow.
28        add    x0, sp, #16
29        bl     COMMON_INTERCEPTOR_HANDLE_VFORK
30
31.L_exit:
32        // Restore x30.
33        bl     COMMON_INTERCEPTOR_SPILL_AREA
34        ldr    x30, [x0]
35        ldp    x0, xzr, [sp], 16
36
37        ret
38ASM_SIZE(vfork)
39
40.weak vfork
41.set vfork, ASM_WRAPPER_NAME(vfork)
42
43#endif
44