diff mbox

arm: add RESET_PID in the clone impl

Message ID 54095F67.5040904@huawei.com
State Superseded
Headers show

Commit Message

Wang Yufen Sept. 5, 2014, 6:59 a.m. UTC
From: Wang Yufen <wangyufen@huawei.com>

Called getpid() When creating a new process with clone(), getpid() returns 
the father_process's value. It should be child_process's value.
The reason is missing a RESET_PID in the arm clone impl.

Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 libc/sysdeps/linux/arm/clone.S  |   61 ++++++++++++++++++++++++++++++---------
 libc/sysdeps/linux/arm/sysdep.h |   36 +++++++++++++++++++++++
 2 files changed, 83 insertions(+), 14 deletions(-)
diff mbox

Patch

diff --git a/libc/sysdeps/linux/arm/clone.S b/libc/sysdeps/linux/arm/clone.S
index 03cd10e..29045ef 100644
--- a/libc/sysdeps/linux/arm/clone.S
+++ b/libc/sysdeps/linux/arm/clone.S
@@ -19,12 +19,17 @@ 
 /* clone() is even more special than fork() as it mucks with stacks
    and invokes a function in the right context after its all over.  */
 
+#include <sysdep.h>
 #define _ERRNO_H
 #include <features.h>
 #include <bits/errno.h>
 #include <sys/syscall.h>
 #include <bits/arm_asm.h>
 #include <bits/arm_bx.h>
+#include <sysdep-cancel.h>
+
+#define CLONE_VM      0x00000100
+#define CLONE_THREAD  0x00010000
 
 #if defined(__NR_clone)
 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
@@ -87,6 +92,8 @@  __error:
 .pool
 #else
 __clone:
+.fnstart
+.cantunwind
 	@ sanity check args
 	cmp	r0, #0
 	IT(te, ne)
@@ -95,32 +102,58 @@  __clone:
 	beq	__error
 
 	@ insert the args onto the new stack
-	sub	r1, r1, #8
-	str	r3, [r1, #4]
-	@ save the function pointer as the 0th element
-	str	r0, [r1]
+	str	r3, [r1, #-4]!
+	str	r0, [r1, #-4]!
 
 	@ do the system call
 	@ get flags
 	mov	r0, r2
+#ifdef RESET_PID
+	mov	ip, r2
+#endif
 	@ new sp is already in r1
-	@ load remaining arguments off the stack
-	stmfd	sp!, {r4}
-	ldr	r2, [sp, #4]
-	ldr	r3, [sp, #8]
-	ldr	r4, [sp, #12]
-	DO_CALL (clone)
-	movs	a1, a1
-	IT(t, ne)
-	ldmnefd	sp!, {r4}
+	push	{r4, r7}
+	cfi_adjust_cfa_offset (8)
+	cfi_rel_offset (r4, 0)
+	cfi_rel_offset (r7, 4)
+	ldr	r2, [sp, #8]
+	ldr	r3, [sp, #12]
+	ldr	r4, [sp, #16]
+	ldr	r7, =SYS_ify(clone)
+	swi	0x0
+	cfi_endproc
+	cmp	r0, #0
+	beq	1f
+	pop	{r4, r7}
 	blt	__error
-	IT(t, ne)
 #if defined(__USE_BX__)
 	bxne	lr
 #else
 	movne	pc, lr
 #endif
 
+	cfi_startproc
+.fnend
+PSEUDO_END (__clone)
+
+1:
+	.fnstart
+	.cantunwind
+#ifdef RESET_PID
+	tst	ip, #CLONE_THREAD
+	bne	3f
+	GET_TLS (lr)
+	mov	r1, r0
+	tst	ip, #CLONE_VM
+	ldr	r7, =SYS_ify(getpid)
+	ite	ne
+	movne	r0, #-1
+	swieq	0x0
+	NEGOFF_ADJ_BASE (r1, TID_OFFSET)
+	str	r0, NEGOFF_OFF1 (r1, TID_OFFSET)
+	str	r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET)
+3:
+#endif
 	@ pick the function arg and call address off the stack and execute
 	ldr	r0, [sp, #4]
 	mov	lr, pc
diff --git a/libc/sysdeps/linux/arm/sysdep.h b/libc/sysdeps/linux/arm/sysdep.h
index 64f4040..2d0a9cc 100644
--- a/libc/sysdeps/linux/arm/sysdep.h
+++ b/libc/sysdeps/linux/arm/sysdep.h
@@ -213,6 +213,42 @@  __local_syscall_error:						\
    sees the right arguments.
 
 */
+#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
+# define ARCH_HAS_HARD_TP
+#endif
+
+# ifdef __thumb2__
+#  define NEGOFF_ADJ_BASE(R, OFF)	add R, R, $OFF
+#  define NEGOFF_ADJ_BASE2(D, S, OFF)	add D, S, $OFF
+#  define NEGOFF_OFF1(R, OFF)		[R]
+#  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $((OFFA) - (OFFB))]
+# else
+#  define NEGOFF_ADJ_BASE(R, OFF)
+#  define NEGOFF_ADJ_BASE2(D, S, OFF)	mov D, S
+#  define NEGOFF_OFF1(R, OFF)		[R, $OFF]
+#  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $OFFA]
+# endif
+
+# ifdef ARCH_HAS_HARD_TP
+/* If the cpu has cp15 available, use it.  */
+#  define GET_TLS(TMP)		mrc p15, 0, r0, c13, c0, 3
+# else
+/* At this generic level we have no tricks to pull.  Call the ABI routine.  */
+#  define GET_TLS(TMP)					\
+	push	{ r1, r2, r3, lr };			\
+	cfi_remember_state;				\
+	cfi_adjust_cfa_offset (16);			\
+	cfi_rel_offset (r1, 0);				\
+	cfi_rel_offset (r2, 4);				\
+	cfi_rel_offset (r3, 8);				\
+	cfi_rel_offset (lr, 12);			\
+	bl	__aeabi_read_tp;			\
+	pop	{ r1, r2, r3, lr };			\
+	cfi_restore_state
+# endif /* ARCH_HAS_HARD_TP */
+
+
+
 
 #undef	DO_CALL
 #if defined(__ARM_EABI__)