1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include <errno.h>
#include "syscalls.h"
#include "arm-features.h"
@
@ Some slightly tricky stuff here... edit with care :-)
@
#ifdef __ARM_EABI__
#define CLONE_VM 0x00000100
#define CLONE_THREAD 0x00010000
@ ; don't do this yet
@#define RESET_PID
FUNC_START_WEAK clone
FUNC_START __clone
@ ; start with a sanity check
cmp r0, #0
cmpne r1, #0
mvneq r0, #-EINVAL
beq __unified_syscall @ handle as if error was returned by the syscall
@ ; insert args into stack
str r3, [r1, #-4]!
str r0, [r1, #-4]!
@ ; do the system call
@ ; get the flags
mov r0, r2
#ifdef RESET_PID
mov ip, r2
#endif
@ ; child sp is already in r1
stmfd sp!, {r4, r7}
@stmdb sp!, {r4, r7}
ldr r2, [sp, #8]
ldr r3, [sp, #12]
ldr r4, [sp, #16]
ldr r7, =__NR_clone
swi 0
cmp r0, #0
beq 1f
ldmfd sp!, {r4, r7}
blt __unified_syscall @ (return code < 0): handle as an error
RET
1:
#ifdef RESET_PID
tst ip, #CLONE_THREAD
bne 3f
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
mov r1, r0
tst ip, #CLONE_VM
movne r0, #-1
ldr r7, =__NR_getpid
swi 0
str r0, [r1, #PID_OFFSET] @ ; not defined yet ??
str r0, [r1, #TID_OFFSET] @ ; not defined yet ??
3:
#endif
@ ; pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
mov lr, pc
ldr pc, [sp], #8
@ ; and we're done, passing return value through r0
b _exit @ branch to _exit (PIC safe)
FUNC_END __clone
FUNC_END clone
#else
FUNC_START_WEAK clone
FUNC_START __clone
movs r12, r0 @ check function pointer
cmpne r1, #0 @ if function check for stack pointer
moveq r0, #-EINVAL @ if one is not available set errno value
beq __unified_syscall @ handle as if error was returned by the syscall
stmdb r1!, { r3, r12 } @ store function param (r3) and function ptr (r12)
@ into what will become the childs stack.
mov r0, r2 @ move flags argument to r0
swi __NR_clone @ call the syscall
movs r0, r0 @ set condition codes
blt __unified_syscall @ (return code < 0): handle as an error
movne pc, lr @ (return code > 0): return to parent
mov fp, #0 @ clear the frame pointer
adr lr, 1f @ setup return address
ldmia sp!, { r0, pc } @ load function param and jump to thread function
1: b _exit @ branch to _exit (PIC safe)
FUNC_END __clone
FUNC_END clone
#endif
|