1#if defined(__arm__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
6
7.comm _ZN14__interception10real_vforkE,4,4
8.globl ASM_WRAPPER_NAME(vfork)
9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
10ASM_WRAPPER_NAME(vfork):
11        // Save LR in the off-stack spill area.
12        push    {r4, lr}
13        bl      COMMON_INTERCEPTOR_SPILL_AREA
14        pop     {r4, lr}
15        str     lr, [r0]
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        ldr     r0, .LCPI0_0
20.LPC0_0:
21        ldr     r0, [pc, r0]
22        mov     lr, pc
23        bx      r0
24
25        push    {r0, r4}
26        cmp     r0, #0
27        beq     .L_exit
28
29        // r0 != 0 => parent process. Clear stack shadow.
30        add     r0, sp, #8
31        bl      COMMON_INTERCEPTOR_HANDLE_VFORK
32
33.L_exit:
34        // Restore LR.
35        bl      COMMON_INTERCEPTOR_SPILL_AREA
36        ldr     lr, [r0]
37        pop     {r0, r4}
38
39        mov     pc, lr
40
41.LCPI0_0:
42        .long   _ZN14__interception10real_vforkE - (.LPC0_0+8)
43
44ASM_SIZE(vfork)
45
46ASM_INTERCEPTOR_TRAMPOLINE(vfork)
47ASM_TRAMPOLINE_ALIAS(vfork, vfork)
48
49#endif
50