strace bug for clone()
Michael Holzheu
HOLZHEU at de.ibm.com
Thu Feb 26 06:44:33 UTC 2004
Hi all,
The clone() system call is not handled correctly in strace for s390(x)
under Linux.
The following testprogram under linux 2.6 fails:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
char stack[10000];
int childfn(void* arg)
{
printf("CHILD\n");
return 0;
}
int main(void)
{
pid_t child;
int status,rc;
child = clone(&childfn,stack+sizeof(stack)
,CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD ,NULL);
rc = waitpid(child,&status,0);
printf("parent rc: %i\n",rc);
return 0;
}
>>> strace -f ./test
....
clone(Process 15636 attached
child_stack=0x403fec,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0) =
15636
[pid 15635] --- SIGCHLD (Child exited) @ 0 (0) ---
[pid 15635] wait4(15636, Process 15635 suspended
<strace hangs here>
The problem is that on s390 the paramters of clone() are ordered in a
different way than on all other platforms. When tracing the clone() system
call the argument 0 (the flags argument which is argument 1 on s390) is
or'd with CLONE_PTRACE and is written back. Because on s390 the arguments
are swapped, we overwrite the old clone flags here.
Here is a fix for the problem:
--- util.c.orig 2004-02-25 16:26:10.268979783 +0100
+++ util.c 2004-02-26 15:01:25.048979783 +0100
@@ -1230,14 +1230,8 @@
#else
# if defined S390 || defined S390X
-/* Note: this is only true for the `clone' system call, which handles
- arguments specially. We could as well say that its first two arguments
- are swapped relative to other architectures, but that would just be
- another #ifdef in the calls. */
-# define arg0_offset PT_GPR3
-# define arg1_offset PT_ORIGGPR2
-# define restore_arg0(tcp, state, val) ((void) (state), 0)
-# define restore_arg1(tcp, state, val) ((void) (state), 0)
+# define arg0_offset PT_ORIGGPR2
+# define arg1_offset PT_GPR3
# elif defined (ALPHA) || defined (MIPS)
# define arg0_offset REG_A0
# define arg1_offset (REG_A0+1)
@@ -1317,6 +1311,21 @@
case SYS_fork:
#endif
#if defined SYS_fork || defined SYS_vfork
+#if defined(S390) || defined(S390X)
+/* Note: On s390(x) the `clone' system call arguments are arranged
differnt
+ then on other architectures
+*/
+ if (arg_setup (tcp, &state) < 0
+ || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
+ || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
+ || change_syscall(tcp, SYS_clone) < 0
+ || set_arg1 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
+ || set_arg0 (tcp, &state, 0) < 0
+ || arg_finish_change (tcp, &state) < 0)
+ return -1;
+ tcp->u_arg[0] = 0;
+ tcp->u_arg[1] = CLONE_PTRACE|SIGCHLD;
+#else
if (arg_setup (tcp, &state) < 0
|| get_arg0 (tcp, &state, &tcp->inst[0]) < 0
|| get_arg1 (tcp, &state, &tcp->inst[1]) < 0
@@ -1327,6 +1336,7 @@
return -1;
tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
tcp->u_arg[1] = 0;
+#endif
tcp->flags |= TCB_BPTSET;
return 0;
#endif
@@ -1335,11 +1345,19 @@
#ifdef SYS_clone2
case SYS_clone2:
#endif
+#if defined(S390) || defined(S390X)
+ if ((tcp->u_arg[1] & CLONE_PTRACE) == 0
+ && (arg_setup (tcp, &state) < 0
+ || set_arg1 (tcp, &state, tcp->u_arg[1] | CLONE_PTRACE) <
0
+ || arg_finish_change (tcp, &state) < 0))
+ return -1;
+#else
if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
&& (arg_setup (tcp, &state) < 0
|| set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) <
0
|| arg_finish_change (tcp, &state) < 0))
return -1;
+#endif
tcp->flags |= TCB_BPTSET;
tcp->inst[0] = tcp->u_arg[0];
tcp->inst[1] = tcp->u_arg[1];
(See attached file: strace-4.5.1-clone.diff)
Best Regards
Michael
------------------------------------------------------------------------
Linux for E-Server Development
Phone: +49-7031-16-2360, Bld 71032-03-U09
Email: holzheu at de.ibm.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: strace-4.5.1-clone.diff
Type: application/octet-stream
Size: 2372 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20040226/bb9cde89/attachment.obj>
More information about the Strace-devel
mailing list