1351282Sdim#if defined(__arm__) && defined(__linux__) 2351282Sdim 3351282Sdim#include "sanitizer_common/sanitizer_asm.h" 4351282Sdim 5351282SdimASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA) 6351282Sdim 7351282Sdim.comm _ZN14__interception10real_vforkE,4,4 8351282Sdim.globl ASM_WRAPPER_NAME(vfork) 9351282SdimASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork)) 10351282SdimASM_WRAPPER_NAME(vfork): 11351282Sdim // Save LR in the off-stack spill area. 12351282Sdim push {r4, lr} 13351282Sdim bl COMMON_INTERCEPTOR_SPILL_AREA 14351282Sdim pop {r4, lr} 15351282Sdim str lr, [r0] 16351282Sdim 17351282Sdim // Call real vfork. This may return twice. User code that runs between the first and the second return 18351282Sdim // may clobber the stack frame of the interceptor; that's why it does not have a frame. 19351282Sdim ldr r0, .LCPI0_0 20351282Sdim.LPC0_0: 21351282Sdim ldr r0, [pc, r0] 22351282Sdim mov lr, pc 23351282Sdim bx r0 24351282Sdim 25351282Sdim push {r0, r4} 26351282Sdim cmp r0, #0 27351282Sdim beq .L_exit 28351282Sdim 29351282Sdim // r0 != 0 => parent process. Clear stack shadow. 30351282Sdim add r0, sp, #8 31351282Sdim bl COMMON_INTERCEPTOR_HANDLE_VFORK 32351282Sdim 33351282Sdim.L_exit: 34351282Sdim // Restore LR. 35351282Sdim bl COMMON_INTERCEPTOR_SPILL_AREA 36351282Sdim ldr lr, [r0] 37351282Sdim pop {r0, r4} 38351282Sdim 39351282Sdim mov pc, lr 40351282Sdim 41351282Sdim.LCPI0_0: 42351282Sdim .long _ZN14__interception10real_vforkE - (.LPC0_0+8) 43351282Sdim 44351282SdimASM_SIZE(vfork) 45351282Sdim 46351282Sdim.weak vfork 47351282Sdim.set vfork, ASM_WRAPPER_NAME(vfork) 48351282Sdim 49351282Sdim#endif 50