From 7a0b649aeace5c1e1efe4a1d7b1ae6e3a87e0d44 Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Thu, 23 Dec 1999 15:08:17 +0000 Subject: [PATCH] Begin work on supporting clone --- ChangeLog | 2 ++ defs.h | 3 ++ process.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++--- syscall.c | 7 ++-- util.c | 5 +-- 5 files changed, 111 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 959068c6..e7b1c871 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ Thu Dec 23 15:01:37 CET 1999 Wichert Akkerman * Merge patch from ftp://oss.software.ibm.com/linux390/ to add support for Linux on the IBM S/390 architecture + * process.c: add internal_clone(), currently only shows the options + * syscall.c: use internal_clone to handle SYS_clone Mon Dec 20 00:27:50 CET 1999 Wichert Akkerman diff --git a/defs.h b/defs.h index d65fc152..cae320a1 100644 --- a/defs.h +++ b/defs.h @@ -336,6 +336,9 @@ extern void call_summary P((FILE *)); extern void fake_execve P((struct tcb *, char *, char *[], char *[])); extern void printtv32 P((struct tcb*, long)); +#ifdef LINUX +extern int internal_clone P((struct tcb *)); +#endif extern int internal_fork P((struct tcb *)); extern int internal_exec P((struct tcb *)); extern int internal_wait P((struct tcb *)); diff --git a/process.c b/process.c index ea78824a..ae7b8e4a 100644 --- a/process.c +++ b/process.c @@ -78,7 +78,7 @@ #define WCOREDUMP(status) ((status) & 0200) #endif -/* WTA: this has `&& !defined(LINUXSPARC)', this seems unneeded though? */ +/* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */ #if defined(HAVE_PRCTL) static struct xlat prctl_options[] = { #ifdef PR_MAXPROCS @@ -316,6 +316,35 @@ struct tcb *tcp; #else /* !SVR4 */ +#ifdef LINUX + +/* defines copied from linux/sched.h since we can't include that + * ourselves (it conflicts with *lots* of libc includes) + */ +#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_FS 0x00000200 /* set if fs info shared between processes */ +#define CLONE_FILES 0x00000400 /* set if open files shared between processes */ +#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ +#define CLONE_PID 0x00001000 /* set if pid shared */ +#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ +#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ + +static struct xlat clone_flags[] = { + { CLONE_VM, "CLONE_VM" }, + { CLONE_FS, "CLONE_FS" }, + { CLONE_FILES, "CLONE_FILES" }, + { CLONE_SIGHAND, "CLONE_SIGHAND" }, + { CLONE_PID, "CLONE_PID" }, + { CLONE_PTRACE, "CLONE_PTRACE" }, + { CLONE_VFORK, "CLONE_VFORK" }, + { CLONE_PARENT, "CLONE_PARENT" }, + { 0, NULL }, +}; + +#endif + int sys_fork(tcp) struct tcb *tcp; @@ -325,6 +354,66 @@ struct tcb *tcp; return 0; } +#ifdef SYS_clone +int +internal_clone(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + tprintf("fn=%#lx, child_stack=%#lx, flags=", + tcp->u_arg[0], tcp->u_arg[1]); + if (printflags(clone_flags, tcp->u_arg[2]) == 0) + tprintf("0"); + tprintf(", args=%#lx", tcp->u_arg[3]); + + /* For now we don't follow clone yet.. we're just preparing the code */ + dont_follow = 1; + + if (!followfork || dont_follow) + return 0; + if (nprocs == MAX_PROCS) { + tcp->flags &= ~TCB_FOLLOWFORK; + fprintf(stderr, "sys_fork: tcb table full\n"); + return 0; + } + tcp->flags |= TCB_FOLLOWFORK; + + /* XXX + /* We will take the simple approach and add CLONE_PTRACE to the clone + * options. This only works on Linux 2.2.x and later. This means that + * we break all programs using clone on older kernels.. + * We should try to fallback to the bpt-trick if this fails, but right + * now we don't. + */ + + /* TODO: actually change the flags */ + } else { + if (!(tcp->flags & TCB_FOLLOWFORK)) + return 0; + + if (syserror(tcp)) + return 0; + + pid = tcp->u_rval; + if ((tcpchild = alloctcb(pid)) == NULL) { + fprintf(stderr, " [tcb table full]\n"); + kill(pid, SIGKILL); /* XXX */ + return 0; + } + + /* For fork we need to re-attach, but thanks to CLONE_PTRACE we're + * already attached. + */ + tcphild->flags |= TCB_ATTACHED; + newoutf(tcpfhild); + tcp->nchildren++; + if (!qflag) + fprintf(stderr, "Process %d attached\n", pid); + } + return 0; +} +#endif + int internal_fork(tcp) struct tcb *tcp; @@ -349,9 +438,17 @@ struct tcb *tcp; #endif #ifdef SYS_clone /* clone can do many things, not all of which we know how to handle. - Don't do it for now. */ - if (tcp->scno == SYS_clone) + Don't do much for now. */ + if (tcp->scno == SYS_clone) { + if (entering(tcp)) { + tprintf("fn=%#lx, child_stack=%#lx, flags=", + tcp->u_arg[0], tcp->u_arg[1]); + if (printflags(clone_flags, tcp->u_arg[2]) == 0) + tprintf("0"); + tprintf(", args=%#lx", tcp->u_arg[3]); + } dont_follow = 1; + } #endif if (entering(tcp)) { if (!followfork || dont_follow) @@ -364,7 +461,7 @@ struct tcb *tcp; tcp->flags |= TCB_FOLLOWFORK; if (setbpt(tcp) < 0) return 0; - } + } else { int bpt = tcp->flags & TCB_BPTSET; diff --git a/syscall.c b/syscall.c index 2b23471d..19739a87 100644 --- a/syscall.c +++ b/syscall.c @@ -531,12 +531,13 @@ struct tcb *tcp; #ifdef SYS_vfork case SYS_vfork: #endif + internal_fork(tcp); + break; #ifdef SYS_clone case SYS_clone: -#endif - internal_fork(tcp); + internal_clone(tcp); break; - +#endif #ifdef SYS_execv case SYS_execv: #endif diff --git a/util.c b/util.c index 5c38e66b..2d55f8ed 100644 --- a/util.c +++ b/util.c @@ -871,7 +871,6 @@ struct tcb *tcp; #ifdef LINUX long pc; - #if defined(I386) if (upeek(tcp->pid, 4*EIP, &pc) < 0) return -1; @@ -897,9 +896,7 @@ struct tcb *tcp; pc = regs.r_pc; #elif defined(S390) if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0) - return -1; - -#else +#endif return pc; #endif /* LINUX */ -- 2.40.0