1#if defined(__aarch64__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4#include "builtins/assembly.h"
5
6ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
7
8.comm _ZN14__interception10real_vforkE,8,8
9.globl ASM_WRAPPER_NAME(vfork)
10ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
11ASM_WRAPPER_NAME(vfork):
12        // Save x30 in the off-stack spill area.
13        hint    #25 // paciasp
14        stp     xzr, x30, [sp, #-16]!
15        bl      COMMON_INTERCEPTOR_SPILL_AREA
16        ldp     xzr, x30, [sp], 16
17        str     x30, [x0]
18
19        // Call real vfork. This may return twice. User code that runs between the first and the second return
20        // may clobber the stack frame of the interceptor; that's why it does not have a frame.
21        adrp    x0, _ZN14__interception10real_vforkE
22        ldr     x0, [x0, :lo12:_ZN14__interception10real_vforkE]
23        blr     x0
24
25        stp     x0, xzr, [sp, #-16]!
26        cmp     x0, #0
27        b.eq   .L_exit
28
29        // x0 != 0 => parent process. Clear stack shadow.
30        add    x0, sp, #16
31        bl     COMMON_INTERCEPTOR_HANDLE_VFORK
32
33.L_exit:
34        // Restore x30.
35        bl     COMMON_INTERCEPTOR_SPILL_AREA
36        ldr    x30, [x0]
37        ldp    x0, xzr, [sp], 16
38        hint   #29 // autiasp
39
40        ret
41ASM_SIZE(vfork)
42
43ASM_INTERCEPTOR_TRAMPOLINE(vfork)
44ASM_TRAMPOLINE_ALIAS(vfork, vfork)
45
46GNU_PROPERTY_BTI_PAC
47
48#endif
49