[v2] arm: add RESET_PID in the clone impl

Submitted by Wangyufen on Sept. 5, 2014, 7:19 a.m.

Details

Message ID 540963F9.8020204@huawei.com
State New
Headers show

Commit Message

Wangyufen Sept. 5, 2014, 7:19 a.m.
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(-)

-- 1.7.1

Comments

Waldemar Brodkorb Sept. 11, 2014, 9:37 a.m.
Hi Wang,

I have tested your patch for arm/armhf and NPTL. Works fine.
The getpid tests didn't fail anymore.

But when I am trying to compile linuxthreads instead of NPTL I get:
/adk/uclibc-arm-static/toolchain_qemu-arm_uclibc_arm_eabi/usr/bin/arm-openadk-linux-uclibceabi-gcc
-c libc/sysdeps/linux/arm/syscall-eabi.S -o
libc/sysdeps/linux/arm/syscall-eabi.os -Wall -Wstrict-prototypes
-Wstrict-aliasing -funsigned-char -fno-builtin -fno-asm -msoft-float
-mlittle-endian -fno-stack-protector -nostdinc -I./include
-I./include -include libc-symbols.h -I./libc/sysdeps/linux/arm
-I./libc/sysdeps/linux -I./ldso/ldso/arm -I./ldso/include -I. -Os
-funit-at-a-time -fmerge-all-constants -fstrict-aliasing
-fno-tree-loop-optimize -fno-tree-dominator-opts
-fno-strength-reduce -march=armv7-a -mtune=cortex-a9
-mfloat-abi=soft -fwrapv -fno-ident -fhonour-copts -Os -pipe -g3
-fomit-frame-pointer -fno-unwind-tables
-fno-asynchronous-unwind-tables -marm
-I./libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm
-I./libpthread/linuxthreads/sysdeps/arm
-I./libpthread/linuxthreads/sysdeps/unix/sysv/linux
-I./libpthread/linuxthreads/sysdeps/pthread
-I./libpthread/linuxthreads -I./libpthread
-I./libc/sysdeps/linux/common -isystem
/adk/uclibc-arm-static/toolchain_qemu-arm_uclibc_arm_eabi/usr/lib/gcc/arm-openadk-linux-uclibceabi/4.8.3/include-fixed
-isystem
/adk/uclibc-arm-static/toolchain_qemu-arm_uclibc_arm_eabi/usr/lib/gcc/arm-openadk-linux-uclibceabi/4.8.3/include
-I/adk/uclibc-arm-static/target_qemu-arm_uclibc_arm_eabi/usr/include/
-DNDEBUG -fPIC -MT libc/sysdeps/linux/arm/syscall-eabi.os -MD -MP
-MF libc/sysdeps/linux/arm/.syscall-eabi.os.dep -D__ASSEMBLER__
-Wa,--noexecstack
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h: Assembler
messages:
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:35: Error: bad
instruction `extern __inline
__attribute__((__always_inline__))__attribute__((__gnu_inline__,__artificial__))long
int'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:36: Error: bad
instruction `testandset (int*spinlock)'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:37: Error: junk
at end of line, first unrecognized character is `{'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:38: Error: bad
instruction `register unsigned int movcc pc,lr'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:40: Error: bad
instruction `__asm__ __volatile__("swp %0, %1, [%2]"'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:41: Error: junk
at end of line, first unrecognized character is `:'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:41: Error:
garbage following instruction -- `b __syscall_error(PLT))'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:42: Error: junk
at end of line, first unrecognized character is `:'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:44: Error: bad
instruction `return movcc pc,lr'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:45: Error: junk
at end of line, first unrecognized character is `}'
./libpthread/linuxthreads/sysdeps/arm/pt-machine.h:51: Error: bad
instruction `register char*stack_pointer __asm__("sp")'
Makerules:366: recipe for target 'libc/sysdeps/linux/arm/clone.os'
failed

Any idea how to fix the bug without breaking linuxthreads?

best regards
 Waldemar

Patch hide | download patch | download mbox

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__)