|
From: <sv...@va...> - 2005-07-02 11:28:01
|
Author: sewardj
Date: 2005-07-02 12:27:02 +0100 (Sat, 02 Jul 2005)
New Revision: 4082
Log:
Try to make (client) clone() work for ppc32-linux. I don't know if I
was successful for real uses of clone, but fork-disguised-as-clone
appears to work now.
Modified:
trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
trunk/coregrind/vki_unistd-ppc32-linux.h
Modified: trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2005-07-02 10:13:34 U=
TC (rev 4081)
+++ trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2005-07-02 11:27:02 U=
TC (rev 4082)
@@ -136,7 +136,7 @@
{
ThreadId tid =3D (ThreadId)tidW;
=20
- VG_(debugLog)(1, "syscalls-ppc32-linux",=20
+ VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"run_a_thread_NORETURN(tid=3D%lld): "
"ML_(thread_wrapper) called\n",
(ULong)tidW);
@@ -144,7 +144,7 @@
/* Run the thread all the way through. */
VgSchedReturnCode src =3D ML_(thread_wrapper)(tid); =20
=20
- VG_(debugLog)(1, "syscalls-ppc32-linux",=20
+ VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"run_a_thread_NORETURN(tid=3D%lld): "
"ML_(thread_wrapper) done\n",
(ULong)tidW);
@@ -154,7 +154,7 @@
=20
if (c =3D=3D 1) {
=20
- VG_(debugLog)(1, "syscalls-ppc32-linux",=20
+ VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"run_a_thread_NORETURN(tid=3D%lld): "
"last one standing\n",
(ULong)tidW);
@@ -164,7 +164,7 @@
VG_(shutdown_actions_NORETURN)(tid, src);
=20
} else {
- VG_(debugLog)(1, "syscalls-ppc32-linux",=20
+ VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"run_a_thread_NORETURN(tid=3D%lld): "
"not last one standing\n",
(ULong)tidW);
@@ -261,7 +261,7 @@
*/
void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
{
- VG_(debugLog)(1, "syscalls-ppc32-linux",=20
+ VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"entering VG_(main_thread_wrapper_NORETURN)\n");
=20
UWord* sp =3D allocstack(tid);
@@ -284,7 +284,6 @@
vg_assert(0);
}
=20
-#if 0
static Int start_thread_NORETURN ( void* arg )
{
ThreadState* tst =3D (ThreadState*)arg;
@@ -294,8 +293,8 @@
/*NOTREACHED*/
vg_assert(0);
}
-#endif
=20
+
/* ---------------------------------------------------------------------
clone() handling
------------------------------------------------------------------ */
@@ -400,8 +399,7 @@
#undef STRINGIFZ
=20
// forward declarations
-//.. static void setup_child ( ThreadArchState*, ThreadArchState*, Bool =
);
-//.. static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
+static void setup_child ( ThreadArchState*, ThreadArchState* );
=20
/*=20
When a client clones, we need to keep track of the new thread. This =
means:
@@ -413,167 +411,165 @@
but using the scheduler entrypoint for IP, and a separate stack
for SP.
*/
-//.. static SysRes do_clone ( ThreadId ptid,=20
-//.. UInt flags, Addr esp,=20
-//.. Int *parent_tidptr,=20
-//.. Int *child_tidptr,=20
-//.. vki_modify_ldt_t *tlsinfo)
-//.. {
-//.. static const Bool debug =3D False;
-//..=20
-//.. ThreadId ctid =3D VG_(alloc_ThreadState)();
-//.. ThreadState *ptst =3D VG_(get_ThreadState)(ptid);
-//.. ThreadState *ctst =3D VG_(get_ThreadState)(ctid);
-//.. UWord *stack;
-//.. Segment *seg;
-//.. Int ret;
-//.. vki_sigset_t blockall, savedmask;
-//..=20
-//.. VG_(sigfillset)(&blockall);
-//..=20
-//.. vg_assert(VG_(is_running_thread)(ptid));
-//.. vg_assert(VG_(is_valid_tid)(ctid));
-//..=20
-//.. stack =3D allocstack(ctid);
+static SysRes do_clone ( ThreadId ptid,=20
+ UInt flags, Addr sp,=20
+ Int *parent_tidptr,=20
+ Int *child_tidptr,=20
+ vki_modify_ldt_t *tlsinfo)
+{
+ static const Bool debug =3D False;
=20
+ ThreadId ctid =3D VG_(alloc_ThreadState)();
+ ThreadState* ptst =3D VG_(get_ThreadState)(ptid);
+ ThreadState* ctst =3D VG_(get_ThreadState)(ctid);
+ ULong word64;
+ UWord* stack;
+ Segment* seg;
+ SysRes res;
+ vki_sigset_t blockall, savedmask;
+
+ VG_(sigfillset)(&blockall);
+
+ vg_assert(VG_(is_running_thread)(ptid));
+ vg_assert(VG_(is_valid_tid)(ctid));
+
+ stack =3D allocstack(ctid);
+
//? /* make a stack frame */
//? stack -=3D 16;
//? *(UWord *)stack =3D 0;
=20
-//..=20
-//.. /* Copy register state
-//..=20
-//.. Both parent and child return to the same place, and the code
-//.. following the clone syscall works out which is which, so we
-//.. don't need to worry about it.
-//..=20
-//.. The parent gets the child's new tid returned from clone, but =
the
-//.. child gets 0.
-//..=20
-//.. If the clone call specifies a NULL esp for the new thread, th=
en
-//.. it actually gets a copy of the parent's esp.
-//.. */
-//.. VG_(setup_child)( &ctst->arch, &ptst->arch );
-//..=20
-//.. /* Make sys_clone appear to have returned Success(0) in the
-//.. child. */
-//.. ctst->arch.vex.guest_GPR3 =3D 0;
-//.. =20
-//.. //guest_CC_OP =3D 1
-//.. //guest_CC_DEP1 =3D 0x20000000
-//..=20
-//.. if (esp !=3D 0)
-//.. ctst->arch.vex.guest_ESP =3D esp;
-//..=20
-//.. ctst->os_state.parent =3D ptid;
-//.. ctst->os_state.clone_flags =3D flags;
-//.. ctst->os_state.parent_tidptr =3D parent_tidptr;
-//.. ctst->os_state.child_tidptr =3D child_tidptr;
-//..=20
-//.. /* inherit signal mask */
-//.. ctst->sig_mask =3D ptst->sig_mask;
-//.. ctst->tmp_sig_mask =3D ptst->sig_mask;
-//..=20
-//.. /* We don't really know where the client stack is, because its
-//.. allocated by the client. The best we can do is look at the
-//.. memory mappings and try to derive some useful information. W=
e
-//.. assume that esp starts near its highest possible value, and c=
an
-//.. only go down to the start of the mmaped segment. */
-//.. seg =3D VG_(find_segment)((Addr)esp);
-//.. if (seg) {
-//.. ctst->client_stack_highest_word =3D (Addr)PGROUNDUP(esp);
-//.. ctst->client_stack_szB =3D ctst->client_stack_highest_word -=
seg->addr;
-//..=20
-//.. if (debug)
-//.. VG_(printf)("tid %d: guessed client stack range %p-%p\n",
-//.. ctid, seg->addr, PGROUNDUP(esp));
-//.. } else {
-//.. VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%p=
) unmapped\n",
-//.. ctid, esp);
-//.. ctst->client_stack_szB =3D 0;
-//.. }
-//..=20
-//.. if (flags & VKI_CLONE_SETTLS) {
-//.. if (debug)
-//.. VG_(printf)("clone child has SETTLS: tls info at %p: idx=3D%d bas=
e=3D%p limit=3D%x; esp=3D%p fs=3D%x gs=3D%x\n",
-//.. tlsinfo, tlsinfo->entry_number, tlsinfo->base_addr, tlsinfo-=
>limit,
-//.. ptst->arch.vex.guest_ESP,
-//.. ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
-//.. ret =3D VG_(sys_set_thread_area)(ctid, tlsinfo);
-//..=20
-//.. if (ret !=3D 0)
-//.. goto out;
-//.. }
-//..=20
-//.. flags &=3D ~VKI_CLONE_SETTLS;
-//..=20
-//.. /* start the thread with everything blocked */
-//.. VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
-//..=20
-//.. /* Create the new thread */
-//.. ret =3D VG_(clone)(start_thread, stack, flags, &VG_(threads)[cti=
d],
-//.. child_tidptr, parent_tidptr, NULL);
-//..=20
-//.. VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-//..=20
-//.. out:
-//.. if (ret < 0) {
-//.. /* clone failed */
-//.. VG_(cleanup_thread)(&ctst->arch);
-//.. ctst->status =3D VgTs_Empty;
-//.. }
-//..=20
-//.. return ret;
-//.. }
=20
+ /* Copy register state
=20
+ Both parent and child return to the same place, and the code
+ following the clone syscall works out which is which, so we
+ don't need to worry about it.
+
+ The parent gets the child's new tid returned from clone, but the
+ child gets 0.
+
+ If the clone call specifies a NULL SP for the new thread, then
+ it actually gets a copy of the parent's SP.
+ */
+ setup_child( &ctst->arch, &ptst->arch );
+
+ /* Make sys_clone appear to have returned Success(0) in the
+ child. */
+ ctst->arch.vex.guest_GPR3 =3D 0;
+#warning "fixme: need to clear simulated CR0.SO"
+
+ if (sp !=3D 0)
+ ctst->arch.vex.guest_GPR1 =3D sp;
+
+ ctst->os_state.parent =3D ptid;
+
+ /* inherit signal mask */
+ ctst->sig_mask =3D ptst->sig_mask;
+ ctst->tmp_sig_mask =3D ptst->sig_mask;
+
+ /* We don't really know where the client stack is, because its
+ allocated by the client. The best we can do is look at the
+ memory mappings and try to derive some useful information. We
+ assume that esp starts near its highest possible value, and can
+ only go down to the start of the mmaped segment. */
+ seg =3D VG_(find_segment)(sp);
+ if (seg) {
+ ctst->client_stack_highest_word =3D (Addr)VG_PGROUNDUP(sp);
+ ctst->client_stack_szB =3D ctst->client_stack_highest_word - seg-=
>addr;
+
+ if (debug)
+ VG_(printf)("tid %d: guessed client stack range %p-%p\n",
+ ctid, seg->addr, VG_PGROUNDUP(sp));
+ } else {
+ VG_(message)(Vg_UserMsg, "!? New thread %d starts with R1(%p) unma=
pped\n",
+ ctid, sp);
+ ctst->client_stack_szB =3D 0;
+ }
+
+ if (flags & VKI_CLONE_SETTLS) {
+ if (debug)
+ VG_(printf)("clone child has SETTLS: tls at %p\n", tlsinfo);
+ vg_assert(0);
+ // ret =3D VG_(sys_set_thread_area)(ctid, tlsinfo);
+ // if (ret !=3D 0)
+ // goto out;
+ }
+
+ flags &=3D ~VKI_CLONE_SETTLS;
+
+ /* start the thread with everything blocked */
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+ /* Create the new thread */
+ word64 =3D do_syscall_clone_ppc32_linux(
+ start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
+ child_tidptr, parent_tidptr, NULL
+ );
+ res =3D VG_(mk_SysRes_ppc32_linux)( (UInt)(word64 >> 32), (UInt)word6=
4 );
+
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+ if (res.isError) {
+ /* clone failed */
+ VG_(cleanup_thread)(&ctst->arch);
+ ctst->status =3D VgTs_Empty;
+ }
+
+ return res;
+}
+
+
/* Do a clone which is really a fork() */
-//.. static Int do_fork_clone( ThreadId tid,
-//.. UInt flags, Addr esp,
-//.. Int* parent_tidptr,
-//.. Int* child_tidptr )
-//.. {
-//.. vki_sigset_t fork_saved_mask;
-//.. vki_sigset_t mask;
-//.. Int ret;
-//..=20
-//.. if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM | VK=
I_CLONE_FILES | VKI_CLONE_VFORK))
-//.. return -VKI_EINVAL;
-//..=20
-//.. /* Block all signals during fork, so that we can fix things up i=
n
-//.. the child without being interrupted. */
-//.. VG_(sigfillset)(&mask);
-//.. VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
-//..=20
-//.. /* Since this is the fork() form of clone, we don't need all tha=
t
-//.. VG_(clone) stuff */
-//.. ret =3D VG_(do_syscall5)(__NR_clone, flags, (UWord)NULL, (UWord)=
parent_tidptr,=20
-//.. (UWord)NULL, (UWord)ch=
ild_tidptr);
-//..=20
-//.. if (ret =3D=3D 0) {
-//.. /* child */
-//.. VG_(do_atfork_child)(tid);
-//..=20
-//.. /* restore signal mask */
-//.. VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
-//.. } else if (ret > 0) {
-//.. /* parent */
-//.. if (VG_(clo_trace_syscalls))
-//.. VG_(printf)(" clone(fork): process %d created child %d\n", VG_=
(getpid)(), ret);
-//..=20
-//.. /* restore signal mask */
-//.. VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
-//.. }
-//..=20
-//.. return ret;
-//.. }
+static SysRes do_fork_clone( ThreadId tid,
+ UInt flags, Addr sp,
+ Int* parent_tidptr,
+ Int* child_tidptr )
+{
+ vki_sigset_t fork_saved_mask;
+ vki_sigset_t mask;
+ SysRes res;
=20
+ if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM=20
+ | VKI_CLONE_FILES | VKI_CLONE_VFORK))
+ return VG_(mk_SysRes_Error)( VKI_EINVAL );
=20
+ /* Block all signals during fork, so that we can fix things up in
+ the child without being interrupted. */
+ VG_(sigfillset)(&mask);
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
=20
+ /* Since this is the fork() form of clone, we don't need all that
+ VG_(clone) stuff */
+ res =3D VG_(do_syscall5)( __NR_clone, flags,=20
+ (UWord)NULL, (UWord)parent_tidptr,=20
+ (UWord)NULL, (UWord)child_tidptr );
=20
+ if (!res.isError && res.val =3D=3D 0) {
+ /* child */
+ VG_(do_atfork_child)(tid);
+
+ /* restore signal mask */
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+ } else=20
+ if (!res.isError && res.val > 0) {
+ /* parent */
+ if (VG_(clo_trace_syscalls))
+ VG_(printf)(" clone(fork): process %d created child %d\n",=20
+ VG_(getpid)(), res.val);
+
+ /* restore signal mask */
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+ }
+
+ return res;
+}
+
+
/* ---------------------------------------------------------------------
LDT/GDT simulation
------------------------------------------------------------------ */
+#warning "Do we need all this LDT/GDT garbage on ppc32? Surely not."
=20
/* Details of the LDT simulation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -900,35 +896,17 @@
=20
void VG_(cleanup_thread) ( ThreadArchState* arch )
{
-//.. /* Release arch-specific resources held by this thread. */
-//.. /* On x86, we have to dump the LDT and GDT. */
-//.. deallocate_LGDTs_for_thread( &arch->vex );
} =20
=20
+void setup_child ( /*OUT*/ ThreadArchState *child,
+ /*IN*/ ThreadArchState *parent )
+{
+ /* We inherit our parent's guest state. */
+ child->vex =3D parent->vex;
+ child->vex_shadow =3D parent->vex_shadow;
+}
=20
-//.. void VG_(setup_child) ( /*OUT*/ ThreadArchState *child,
-//.. /*IN*/ ThreadArchState *parent )
-//.. {
-//.. /* We inherit our parent's guest state. */
-//.. child->vex =3D parent->vex;
-//.. child->vex_shadow =3D parent->vex_shadow;
-//.. /* We inherit our parent's LDT. */
-//.. if (parent->vex.guest_LDT =3D=3D (HWord)NULL) {
-//.. /* We hope this is the common case. */
-//.. child->vex.guest_LDT =3D (HWord)NULL;
-//.. } else {
-//.. /* No luck .. we have to take a copy of the parent's. */
-//.. child->vex.guest_LDT =3D (HWord)VG_(alloc_zeroed_x86_LDT)();
-//.. copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT=
,
-//.. (VexGuestX86SegDescr*)child->vex.guest_LDT =
);
-//.. }
-//..
-//.. /* We need an empty GDT. */
-//.. child->vex.guest_GDT =3D (HWord)NULL;
-//.. }
=20
-
-
/* ---------------------------------------------------------------------
PRE/POST wrappers for ppc32/Linux-specific syscalls
------------------------------------------------------------------ */
@@ -947,6 +925,7 @@
DECL_TEMPLATE(ppc32_linux, sys_lstat64);
DECL_TEMPLATE(ppc32_linux, sys_fstat64);
DECL_TEMPLATE(ppc32_linux, sys_ipc);
+DECL_TEMPLATE(ppc32_linux, sys_clone);
=20
PRE(sys_socketcall)
{
@@ -1441,91 +1420,99 @@
//.. }
//.. }
=20
-//.. PRE(sys_clone, Special)
-//.. {
-//.. UInt cloneflags;
-//..=20
-//.. PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG=
5);
-//.. PRE_REG_READ5(int, "clone",
-//.. unsigned long, flags,
-//.. void *, child_stack,
-//.. int *, parent_tidptr,
-//.. vki_modify_ldt_t *, tlsinfo,
-//.. int *, child_tidptr);
-//..=20
-//.. if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-//.. PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-//.. if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) =
{
-//.. SET_RESULT( -VKI_EFAULT );
-//.. return;
-//.. }
-//.. }
-//.. if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) =
{
-//.. PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
-//.. if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) =
{
-//.. SET_RESULT( -VKI_EFAULT );
-//.. return;
-//.. }
-//.. }
-//.. if (ARG1 & VKI_CLONE_SETTLS) {
-//.. PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_=
ldt_t));
-//.. if (!VG_(is_addressable)(ARG4, sizeof(vki_modify_ldt_t), VKI_=
PROT_READ)) {
-//.. SET_RESULT( -VKI_EFAULT );
-//.. return;
-//.. }
-//.. }
-//..=20
-//.. cloneflags =3D ARG1;
-//..=20
-//.. if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
-//.. SET_RESULT( -VKI_EINVAL );
-//.. return;
-//.. }
-//..=20
-//.. /* Only look at the flags we really care about */
-//.. switch(cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FIL=
ES | VKI_CLONE_VFORK)) {
-//.. case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
-//.. /* thread creation */
-//.. SET_RESULT(do_clone(tid,
-//.. ARG1, /* flags */
-//.. (Addr)ARG2, /* child ESP */
-//.. (Int *)ARG3, /* parent_tidptr */
-//.. (Int *)ARG5, /* child_tidptr */
-//.. (vki_modify_ldt_t *)ARG4)); /* set_tls */
-//.. break;
-//..=20
-//.. case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-//.. /* FALLTHROUGH - assume vfork =3D=3D fork */
-//.. cloneflags &=3D ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-//..=20
-//.. case 0: /* plain fork */
-//.. SET_RESULT(do_fork_clone(tid,
-//.. cloneflags, /* flags */
-//.. (Addr)ARG2, /* child ESP */
-//.. (Int *)ARG3, /* parent_tidptr */
-//.. (Int *)ARG5)); /* child_tidptr */
-//.. break;
-//..=20
-//.. default:
-//.. /* should we just ENOSYS? */
-//.. VG_(message)(Vg_UserMsg, "Unsupported clone() flags: %x", ARG=
1);
-//.. VG_(unimplemented)
-//.. ("Valgrind does not support general clone(). The only sup=
ported uses "
-//.. "are via a threads library, fork, or vfork.");
-//.. }
-//..=20
-//.. if (!VG_(is_kerror)(RES)) {
-//.. if (ARG1 & VKI_CLONE_PARENT_SETTID)
-//.. POST_MEM_WRITE(ARG3, sizeof(Int));
-//.. if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID=
))
-//.. POST_MEM_WRITE(ARG5, sizeof(Int));
-//..=20
-//.. /* Thread creation was successful; let the child have the cha=
nce
-//.. to run */
-//.. VG_(vg_yield)();
-//.. }
-//.. }
+PRE(sys_clone)
+{
+ UInt cloneflags;
=20
+ PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
+ PRE_REG_READ5(int, "clone",
+ unsigned long, flags,
+ void *, child_stack,
+ int *, parent_tidptr,
+ vki_modify_ldt_t *, tlsinfo,
+ int *, child_tidptr);
+
+ if (ARG1 & VKI_CLONE_PARENT_SETTID) {
+ PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
+ if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+ }
+ if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
+ PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
+ if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+ }
+
+#warning "Is this next check relevant/needed?"
+ if (ARG1 & VKI_CLONE_SETTLS) {
+ PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t=
));
+ if (!VG_(is_addressable)(ARG4, sizeof(vki_modify_ldt_t), VKI_PROT_=
READ)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+ }
+
+ cloneflags =3D ARG1;
+
+ if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
+ SET_STATUS_Failure( VKI_EINVAL );
+ return;
+ }
+
+ /* Only look at the flags we really care about */
+ switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS=20
+ | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
+ case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
+ /* thread creation */
+ SET_STATUS_from_SysRes(
+ do_clone(tid,
+ ARG1, /* flags */
+ (Addr)ARG2, /* child SP */
+ (Int *)ARG3, /* parent_tidptr */
+ (Int *)ARG5, /* child_tidptr */
+ (vki_modify_ldt_t *)ARG4)); /* set_tls */
+ break;
+
+ case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
+ /* FALLTHROUGH - assume vfork =3D=3D fork */
+ cloneflags &=3D ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
+
+ case 0: /* plain fork */
+ SET_STATUS_from_SysRes(
+ do_fork_clone(tid,
+ cloneflags, /* flags */
+ (Addr)ARG2, /* child SP */
+ (Int *)ARG3, /* parent_tidptr */
+ (Int *)ARG5)); /* child_tidptr */
+ break;
+
+ default:
+ /* should we just ENOSYS? */
+ VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
+ VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads o=
r NPTL)");
+ VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfo=
rk");
+ VG_(unimplemented)
+ ("Valgrind does not support general clone().");
+ }
+
+ if (SUCCESS) {
+ if (ARG1 & VKI_CLONE_PARENT_SETTID)
+ POST_MEM_WRITE(ARG3, sizeof(Int));
+ if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
+ POST_MEM_WRITE(ARG5, sizeof(Int));
+
+ /* Thread creation was successful; let the child have the chance
+ to run */
+ *flags |=3D SfYieldAfter;
+ }
+}
+
//.. PRE(sys_sigreturn, Special)
//.. {
//.. PRINT("sigreturn ( )");
@@ -1935,7 +1922,7 @@
=20
GENXY(__NR_open, sys_open), // 5
GENXY(__NR_close, sys_close), // 6
-//.. GENXY(__NR_waitpid, sys_waitpid), // 7
+ GENXY(__NR_waitpid, sys_waitpid), // 7
GENXY(__NR_creat, sys_creat), // 8
//.. GENX_(__NR_link, sys_link), // 9
//..=20
@@ -2071,7 +2058,7 @@
//.. GENX_(__NR_fsync, sys_fsync), // 118
//.. PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/L=
inux
//..=20
-//.. PLAX_(__NR_clone, sys_clone), // 120
+ PLAX_(__NR_clone, sys_clone), // 120
//.. // (__NR_setdomainname, sys_setdomainname), // 121 */*=
(?)
GENXY(__NR_uname, sys_newuname), // 122
//.. PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
@@ -2124,7 +2111,7 @@
//.. GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),/=
/ 160
//.. // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), /=
/ 161 */*
//.. GENXY(__NR_nanosleep, sys_nanosleep), // 162
-//.. GENX_(__NR_mremap, sys_mremap), // 163
+ GENX_(__NR_mremap, sys_mremap), // 163
//.. LINX_(__NR_setresuid, sys_setresuid16), // 164
//..=20
//.. LINXY(__NR_getresuid, sys_getresuid16), // 165
Modified: trunk/coregrind/vki_unistd-ppc32-linux.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vki_unistd-ppc32-linux.h 2005-07-02 10:13:34 UTC (rev=
4081)
+++ trunk/coregrind/vki_unistd-ppc32-linux.h 2005-07-02 11:27:02 UTC (rev=
4082)
@@ -36,7 +36,7 @@
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
-//#define __NR_waitpid 7
+#define __NR_waitpid 7
#define __NR_creat 8
//#define __NR_link 9
#define __NR_unlink 10
|