Valgrind: r16186 - in /trunk: ./ coregrind/m_syswrap/ include/vki/ none/tests/linux/

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Valgrind: r16186 - in /trunk: ./ coregrind/m_syswrap/ include/vki/ none/tests/linux/

svn-2
Author: philippe
Date: Sun Dec 11 21:39:23 2016
New Revision: 16186

Log:
Fix 342040 Valgrind mishandles clone with CLONE_VFORK | CLONE_VM that clones to a different stack
Fix 373192 Calling posix_spawn in glibc 2.24 completely broken

Functionally, this patch just does the following 2 changes to the
fork clone handling:
* It does not mask anymore CLONE_VFORK :
  The only effect of this flag is to suspend the parent, waiting for
  the child to either exit or execve.
  If some applications depends on this synchronisation, better keep it,
  as it will not harm to suspend the parent valgrind waiting for the
  child valgrind to exit or execve.
* In case the guest calls the clone syscall providing a non zero client stack,
  set the child guest SP after the syscall, before executing guest instructions.
  Not setting the guest stack ptr was the source of the problem reported
  in the bugs.

This also adds a test case  none/tests/linux/clonev.
Before this patch, test gives a SEGV, which is fixed by the patch.

The patch is however a lot bigger : this fix was touching some (mostly
identical/duplicated) code in all the linux platforms.
So, the clone/fork code has been factorised as much as possible.
This removes about 1700 lines of code.

This has been tested on:
* amd64
* x86
* ppc64 be and le
* ppc32
* arm64

This has been compiled on but *not really tested* on:
* mips64 (not too clear how to properly build and run valgrind on gcc22)

It has *not* been compiled and *not* tested on:
* arm
* mips32
* tilegx
* darwin   (normally, no impact)
* solaris  (normally, no impact)

The changes are relatively mechanical, so it is not impossible that
it will compile and work out of the box on these platforms.
Otherwise, questions welcome.

A few points of interest:
* Some platforms did have a typedef void vki_modify_ldt_t,
  and some platforms had no definition for this type at all.
  To make it easier to factorise, for such platforms, the following has
  been used:
     typedef char vki_modify_ldt_t;
    When the sizeof vki_modify_ldt_t is > 1, then the arg syscall is checked.
  This is somewhat a hack, but was simplifying the factorisation.

* for mips32/mips64 and tilegx, there is a strange unconditional assignment
  of 0 to a register (guest_r2 on mips, guest_r0 on tilegx).
  Unclear what this is, in particular because this is assigned whatever
  the result of the syscall (success or not).
 


Added:
    trunk/none/tests/linux/clonev.c
    trunk/none/tests/linux/clonev.stderr.exp
    trunk/none/tests/linux/clonev.stdout.exp
    trunk/none/tests/linux/clonev.vgtest
Modified:
    trunk/NEWS
    trunk/coregrind/m_syswrap/priv_syswrap-linux.h
    trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
    trunk/coregrind/m_syswrap/syswrap-arm-linux.c
    trunk/coregrind/m_syswrap/syswrap-arm64-linux.c
    trunk/coregrind/m_syswrap/syswrap-linux.c
    trunk/coregrind/m_syswrap/syswrap-mips32-linux.c
    trunk/coregrind/m_syswrap/syswrap-mips64-linux.c
    trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
    trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c
    trunk/coregrind/m_syswrap/syswrap-s390x-linux.c
    trunk/coregrind/m_syswrap/syswrap-tilegx-linux.c
    trunk/coregrind/m_syswrap/syswrap-x86-linux.c
    trunk/include/vki/vki-arm64-linux.h
    trunk/include/vki/vki-mips32-linux.h
    trunk/include/vki/vki-mips64-linux.h
    trunk/include/vki/vki-ppc32-linux.h
    trunk/include/vki/vki-ppc64-linux.h
    trunk/include/vki/vki-s390x-linux.h
    trunk/none/tests/linux/Makefile.am

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 11 21:39:23 2016
@@ -28,7 +28,12 @@
 
 * ================== PLATFORM CHANGES =================
 
-  Support for demangling Rust symbols (n-i-bz)
+  - Support for demangling Rust symbols (n-i-bz)
+  
+  - On linux, clone handling was improved to honour the CLONE_VFORK flag
+    and setting a child stack. Note however that CLONE_VFORK | CLONE_VM
+    is handled like CLONE_VFORK (so removing CLONE_VM flag).
+    Applications that depends on CLONE_VM exact semantic will (still) not work.
 
 * ==================== TOOL CHANGES ====================
 
@@ -71,6 +76,8 @@
   https://bugs.kde.org/show_bug.cgi?id=XXXXXX
 where XXXXXX is the bug number as listed below.
 
+342040  Valgrind mishandles clone with CLONE_VFORK | CLONE_VM that clones
+        to a different stack.
 348616  Wine/valgrind: noted but unhandled ioctl 0x5390 [..] (DVD_READ_STRUCT)
 352395  Please provide SVN revision info in --version -v
 352767  Wine/valgrind: noted but unhandled ioctl 0x5307 [..] (CDROMSTOP)
@@ -83,6 +90,7 @@
 372504  Hanging on exit_group
 372600  process loops forever when fatal signals are arriving quickly
 373046  Stacks registered by core are never deregistered
+373192  Calling posix_spawn in glibc 2.24 completely broken
 
 Release 3.12.0 (20 October 2016)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Modified: trunk/coregrind/m_syswrap/priv_syswrap-linux.h
==============================================================================
--- trunk/coregrind/m_syswrap/priv_syswrap-linux.h (original)
+++ trunk/coregrind/m_syswrap/priv_syswrap-linux.h Sun Dec 11 21:39:23 2016
@@ -39,12 +39,10 @@
 extern Addr ML_(allocstack)            ( ThreadId tid );
 extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr,
                  void (*f)(Word), Word arg1 );
-extern SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
-                                   Int* parent_tidptr, Int* child_tidptr );
-
 
 // Linux-specific (but non-arch-specific) syscalls
 
+DECL_TEMPLATE(linux, sys_clone)
 DECL_TEMPLATE(linux, sys_mount);
 DECL_TEMPLATE(linux, sys_oldumount);
 DECL_TEMPLATE(linux, sys_umount);
@@ -61,6 +59,10 @@
 DECL_TEMPLATE(linux, sys_readahead);
 DECL_TEMPLATE(linux, sys_move_pages);
 
+// clone is similar enough between linux variants to have a generic
+// version, but which will call an extern defined in syswrap-<platform>-linux.c
+DECL_TEMPLATE(linux, sys_clone);
+
 // POSIX, but various sub-cases differ between Linux and Darwin.
 DECL_TEMPLATE(linux, sys_fcntl);
 DECL_TEMPLATE(linux, sys_fcntl64);
@@ -368,7 +370,83 @@
 DECL_TEMPLATE(linux, sys_socketpair);
 DECL_TEMPLATE(linux, sys_kcmp);
 
-#endif   // __PRIV_SYSWRAP_LINUX_H
+// Some arch specific functions called from syswrap-linux.c
+extern Int do_syscall_clone_x86_linux ( Word (*fn)(void *),
+                                        void* stack,
+                                        Int   flags,
+                                        void* arg,
+                                        Int*  child_tid,
+                                        Int*  parent_tid,
+                                        void* tls_ptr);
+extern SysRes ML_(x86_sys_set_thread_area) ( ThreadId tid,
+                                             vki_modify_ldt_t* info );
+extern void ML_(x86_setup_LDT_GDT) ( /*OUT*/ ThreadArchState *child,
+                                     /*IN*/  ThreadArchState *parent );
+
+extern Long do_syscall_clone_amd64_linux ( Word (*fn)(void *),
+                                           void* stack,
+                                           Long  flags,
+                                           void* arg,
+                                           Int* child_tid,
+                                           Int* parent_tid,
+                                           void* tls_ptr);
+extern ULong do_syscall_clone_ppc32_linux ( Word (*fn)(void *),
+                                            void* stack,
+                                            Int   flags,
+                                            void* arg,
+                                            Int*  child_tid,
+                                            Int*  parent_tid,
+                                            void* tls_ptr);
+extern ULong do_syscall_clone_ppc64_linux ( Word (*fn)(void *),
+                                            void* stack,
+                                            Int   flags,
+                                            void* arg,
+                                            Int*  child_tid,
+                                            Int*  parent_tid,
+                                            void* tls_ptr );
+extern ULong do_syscall_clone_s390x_linux ( void  *stack,
+                                            ULong flags,
+                                            Int   *parent_tid,
+                                            Int   *child_tid,
+                                            void*  tls_ptr,
+                                            Word (*fn)(void *),
+                                            void  *arg);
+extern Long do_syscall_clone_arm64_linux ( Word (*fn)(void *),
+                                           void* stack,
+                                           Long  flags,
+                                           void* arg,
+                                           Int*  child_tid,
+                                           Int*  parent_tid,
+                                           void* tls_ptr );
+extern ULong do_syscall_clone_arm_linux   ( Word (*fn)(void *),
+                                            void* stack,
+                                            Int   flags,
+                                            void* arg,
+                                            Int*  child_tid,
+                                            Int*  parent_tid,
+                                            void* tls_ptr );
+extern ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *),  /* a0 - 4 */
+                                             void* stack,          /* a1 - 5 */
+                                             Int   flags,          /* a2 - 6 */
+                                             void* arg,            /* a3 - 7 */
+                                             Int*  parent_tid,     /* a4 - 8 */
+                                             void* tls_ptr,        /* a5 - 9 */
+                                             Int*  child_tid );    /* a6 - 10 */
+extern UInt do_syscall_clone_mips_linux ( Word (*fn) (void *), //a0     0    32
+                                          void* stack,         //a1     4    36
+                                          Int   flags,         //a2     8    40
+                                          void* arg,           //a3     12   44
+                                          Int*  child_tid,     //stack  16   48
+                                          Int*  parent_tid,    //stack  20   52
+                                          void* tls_ptr);      //stack  24   56
+extern Long do_syscall_clone_tilegx_linux ( Word (*fn) (void *),  //r0
+                                            void* stack,          //r1
+                                            Long  flags,          //r2
+                                            void* arg,            //r3
+                                            Long* child_tid,      //r4
+                                            Long* parent_tid,     //r5
+                                            void* tls_ptr );      //r6
+ #endif   // __PRIV_SYSWRAP_LINUX_H
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/

Modified: trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-amd64-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-amd64-linux.c Sun Dec 11 21:39:23 2016
@@ -130,14 +130,7 @@
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
 
-extern
-Long do_syscall_clone_amd64_linux ( Word (*fn)(void *),
-                                    void* stack,
-                                    Long  flags,
-                                    void* arg,
-                                    Long* child_tid,
-                                    Long* parent_tid,
-                                    vki_modify_ldt_t * );
+// See priv_syswrap-linux.h for arg profile.
 asm(
 ".text\n"
 ".globl do_syscall_clone_amd64_linux\n"
@@ -183,126 +176,6 @@
 #undef __NR_EXIT
 
 
-// forward declaration
-static void setup_child ( ThreadArchState*, ThreadArchState* );
-
-/*
-   When a client clones, we need to keep track of the new thread.  This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-
-   2. initialize the thread's new VCPU state
-
-   3. create the thread using the same args as the client requested,
-   but using the scheduler entrypoint for EIP, and a separate stack
-   for ESP.
- */
-static SysRes do_clone ( ThreadId ptid,
-                         ULong flags, Addr rsp,
-                         Long* parent_tidptr,
-                         Long* child_tidptr,
-                         Addr tlsaddr )
-{
-   static const Bool debug = False;
-
-   ThreadId     ctid = VG_(alloc_ThreadState)();
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
-   UWord*       stack;
-   SysRes       res;
-   Long         rax;
-   vki_sigset_t blockall, savedmask;
-
-   VG_(sigfillset)(&blockall);
-
-   vg_assert(VG_(is_running_thread)(ptid));
-   vg_assert(VG_(is_valid_tid)(ctid));
-
-   stack = (UWord*)ML_(allocstack)(ctid);
-   if (stack == NULL) {
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
-      goto out;
-   }
-
-   /* Copy register state
-
-      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 rsp for the new thread, then
-      it actually gets a copy of the parent's rsp.
-   */
-   setup_child( &ctst->arch, &ptst->arch );
-
-   /* Make sys_clone appear to have returned Success(0) in the
-      child. */
-   ctst->arch.vex.guest_RAX = 0;
-
-   if (rsp != 0)
-      ctst->arch.vex.guest_RSP = rsp;
-
-   ctst->os_state.parent = ptid;
-
-   /* inherit signal mask */
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   /* Start the child with its threadgroup being the same as the
-      parent's.  This is so that any exit_group calls that happen
-      after the child is created but before it sets its
-      os_state.threadgroup field for real (in thread_wrapper in
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
-      a race condition in which the thread is unkillable (via
-      exit_group) because its threadgroup is not set.  The race window
-      is probably only a few hundred or a few thousand cycles long.
-      See #226116. */
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack) (rsp, ctst);
-
-   /* Assume the clone will succeed, and tell any tool that wants to
-      know that this thread has come into existence.  If the clone
-      fails, we'll send out a ll_exit notification for it at the out:
-      label below, to clean up. */
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
-
-   if (flags & VKI_CLONE_SETTLS) {
-      if (debug)
- VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
-      ctst->arch.vex.guest_FS_CONST = tlsaddr;
-   }
-
-   flags &= ~VKI_CLONE_SETTLS;
-
-   /* start the thread with everything blocked */
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
-
-   /* Create the new thread */
-   rax = do_syscall_clone_amd64_linux(
-            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
-            child_tidptr, parent_tidptr, NULL
-         );
-   res = VG_(mk_SysRes_amd64_linux)( rax );
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-
-  out:
-   if (sr_isError(res)) {
-      /* clone failed */
-      VG_(cleanup_thread)(&ctst->arch);
-      ctst->status = VgTs_Empty;
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
-      VG_TRACK( pre_thread_ll_exit, ctid );
-   }
-
-   return res;
-}
-
-
 /* ---------------------------------------------------------------------
    More thread stuff
    ------------------------------------------------------------------ */
@@ -311,16 +184,6 @@
 {  
 }  
 
-void setup_child ( /*OUT*/ ThreadArchState *child,
-                   /*IN*/  ThreadArchState *parent )
-{  
-   /* We inherit our parent's guest state. */
-   child->vex = parent->vex;
-   child->vex_shadow1 = parent->vex_shadow1;
-   child->vex_shadow2 = parent->vex_shadow2;
-}  
-
-
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for AMD64/Linux-specific syscalls
    ------------------------------------------------------------------ */
@@ -333,7 +196,6 @@
    the right thing to do is to make these wrappers 'static' since they
    aren't visible outside this file, but that requires even more macro
    magic. */
-DECL_TEMPLATE(amd64_linux, sys_clone);
 DECL_TEMPLATE(amd64_linux, sys_rt_sigreturn);
 DECL_TEMPLATE(amd64_linux, sys_arch_prctl);
 DECL_TEMPLATE(amd64_linux, sys_ptrace);
@@ -342,108 +204,6 @@
 DECL_TEMPLATE(amd64_linux, sys_syscall184);
 
 
-PRE(sys_clone)
-{
-   ULong cloneflags;
-
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
-   PRE_REG_READ2(int, "clone",
-                 unsigned long, flags,
-                 void *, child_stack);
-
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-      if (VG_(tdict).track_pre_reg_read) {
-         PRA3("clone", int *, parent_tidptr);
-      }
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-   if (ARG1 & VKI_CLONE_SETTLS) {
-      if (VG_(tdict).track_pre_reg_read) {
-         PRA4("clone", vki_modify_ldt_t *, tlsinfo);
-      }
-      PRE_MEM_READ("clone(tlsinfo)", ARG4, sizeof(vki_modify_ldt_t));
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
-                                             VKI_PROT_READ)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
-      if (VG_(tdict).track_pre_reg_read) {
-         PRA5("clone", int *, child_tidptr);
-      }
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int), VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-
-   cloneflags = 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
-                         | 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 ESP */
-                  (Long *)ARG3,  /* parent_tidptr */
-                  (Long *)ARG4,  /* child_tidptr */
-                  (Addr)ARG5));  /* set_tls */
-      break;
-
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-      /* FALLTHROUGH - assume vfork == fork */
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-
-   case 0: /* plain fork */
-      SET_STATUS_from_SysRes(
-         ML_(do_fork_clone)(tid,
-                       cloneflags,      /* flags */
-                       (Int *)ARG3,     /* parent_tidptr */
-                       (Int *)ARG4));   /* child_tidptr */
-      break;
-
-   default:
-      /* should we just ENOSYS? */
-      VG_(message)(Vg_UserMsg,
-                   "Unsupported clone() flags: 0x%lx\n", ARG1);
-      VG_(message)(Vg_UserMsg,
-                   "\n");
-      VG_(message)(Vg_UserMsg,
-                   "The only supported clone() uses are:\n");
-      VG_(message)(Vg_UserMsg,
-                   " - via a threads library (LinuxThreads or NPTL)\n");
-      VG_(message)(Vg_UserMsg,
-                   " - via the implementation of fork or vfork\n");
-      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(ARG4, sizeof(Int));
-
-      /* Thread creation was successful; let the child have the chance
-         to run */
-      *flags |= SfYieldAfter;
-   }
-}
-
 PRE(sys_rt_sigreturn)
 {
    /* This isn't really a syscall at all - it's a misuse of the
@@ -761,7 +521,7 @@
    LINX_(__NR_setsockopt,        sys_setsockopt),     // 54
 
    LINXY(__NR_getsockopt,        sys_getsockopt),     // 55
-   PLAX_(__NR_clone,             sys_clone),          // 56
+   LINX_(__NR_clone,             sys_clone),          // 56
    GENX_(__NR_fork,              sys_fork),           // 57
    GENX_(__NR_vfork,             sys_fork),           // 58 treat as fork
    GENX_(__NR_execve,            sys_execve),         // 59

Modified: trunk/coregrind/m_syswrap/syswrap-arm-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-arm-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-arm-linux.c Sun Dec 11 21:39:23 2016
@@ -102,14 +102,7 @@
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
 
-extern
-ULong do_syscall_clone_arm_linux   ( Word (*fn)(void *),
-                                     void* stack,
-                                     Int   flags,
-                                     void* arg,
-                                     Int*  child_tid,
-                                     Int*  parent_tid,
-                                     void* tls );
+// See priv_syswrap-linux.h for arg profile.
 asm(
 ".text\n"
 ".globl do_syscall_clone_arm_linux\n"
@@ -148,104 +141,8 @@
 #undef __NR_EXIT
 
 // forward declarations
-static void setup_child ( ThreadArchState*, ThreadArchState* );
-static void assign_guest_tls(ThreadId ctid, Addr tlsptr);
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
             
-/*
-   When a client clones, we need to keep track of the new thread.  This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-
-   2. initialize the thread's new VCPU state
-
-   3. create the thread using the same args as the client requested,
-   but using the scheduler entrypoint for IP, and a separate stack
-   for SP.
- */
-static SysRes do_clone ( ThreadId ptid,
-                         UInt flags, Addr sp,
-                         Int *parent_tidptr,
-                         Int *child_tidptr,
-                         Addr child_tls)
-{
-   ThreadId ctid = VG_(alloc_ThreadState)();
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
-   UInt r0;
-   UWord *stack;
-   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 = (UWord*)ML_(allocstack)(ctid);
-
-   if(stack == NULL) {
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
-      goto out;
-   }
-
-   setup_child( &ctst->arch, &ptst->arch );
-
-   ctst->arch.vex.guest_R0 = 0;
-   if(sp != 0)
-      ctst->arch.vex.guest_R13 = sp;
-
-   ctst->os_state.parent = ptid;
-
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   /* Start the child with its threadgroup being the same as the
-      parent's.  This is so that any exit_group calls that happen
-      after the child is created but before it sets its
-      os_state.threadgroup field for real (in thread_wrapper in
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
-      a race condition in which the thread is unkillable (via
-      exit_group) because its threadgroup is not set.  The race window
-      is probably only a few hundred or a few thousand cycles long.
-      See #226116. */
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack) (sp, ctst);
-
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
-
-   if (flags & VKI_CLONE_SETTLS) {
-      /* Just assign the tls pointer in the guest TPIDRURO. */
-      assign_guest_tls(ctid, child_tls);
-   }
-    
-   flags &= ~VKI_CLONE_SETTLS;
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
-
-   r0 = do_syscall_clone_arm_linux(
-      ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
-      child_tidptr, parent_tidptr, NULL
-   );
-   //VG_(printf)("AFTER SYSCALL, %x and %x  CHILD: %d PARENT: %d\n",child_tidptr, parent_tidptr,*child_tidptr,*parent_tidptr);
-    
-   res = VG_(mk_SysRes_arm_linux)( r0 );
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-
-out:
-   if (sr_isError(res)) {
-      VG_(cleanup_thread)(&ctst->arch);
-      ctst->status = VgTs_Empty;
-      VG_TRACK( pre_thread_ll_exit, ctid );
-   }
-
-   return res;
-}
-
-
-
 /* ---------------------------------------------------------------------
    More thread stuff
    ------------------------------------------------------------------ */
@@ -256,26 +153,13 @@
 {
 }  
 
-void setup_child ( /*OUT*/ ThreadArchState *child,
-                   /*IN*/  ThreadArchState *parent )
-{
-   child->vex = parent->vex;
-   child->vex_shadow1 = parent->vex_shadow1;
-   child->vex_shadow2 = parent->vex_shadow2;
-}
-
-static void assign_guest_tls(ThreadId tid, Addr tlsptr)
-{
-   VG_(threads)[tid].arch.vex.guest_TPIDRURO = tlsptr;
-}
-
 /* Assigns tlsptr to the guest TPIDRURO.
    If needed for the specific hardware, really executes
    the set_tls syscall.
 */
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
 {
-   assign_guest_tls(tid, tlsptr);
+   VG_(threads)[tid].arch.vex.guest_TPIDRURO = tlsptr;
 
    if (KernelVariantiS(KernelVariant_android_no_hw_tls,
                        VG_(clo_kernel_variant))) {
@@ -333,7 +217,6 @@
 DECL_TEMPLATE(arm_linux, sys_lstat64);
 DECL_TEMPLATE(arm_linux, sys_fstatat64);
 DECL_TEMPLATE(arm_linux, sys_fstat64);
-DECL_TEMPLATE(arm_linux, sys_clone);
 DECL_TEMPLATE(arm_linux, sys_sigreturn);
 DECL_TEMPLATE(arm_linux, sys_rt_sigreturn);
 DECL_TEMPLATE(arm_linux, sys_sigsuspend);
@@ -424,100 +307,6 @@
    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
 }
 
-PRE(sys_clone)
-{
-    UInt cloneflags;
-
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
-   PRE_REG_READ5(int, "clone",
-                 unsigned long, flags,
-                 void *, child_stack,
-                 int *, parent_tidptr,
-                 void *, child_tls,
-                 int *, child_tidptr);
-
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(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_(am_is_valid_for_client)(ARG5, sizeof(Int),
-                                             VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-   if (ARG1 & VKI_CLONE_SETTLS) {
-      PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
-                                             VKI_PROT_READ)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-
-   cloneflags = 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
-                         | 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 ESP */
-                  (Int *)ARG3,  /* parent_tidptr */
-                  (Int *)ARG5,  /* child_tidptr */
-                  (Addr)ARG4)); /* set_tls */
-      break;
-
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-      /* FALLTHROUGH - assume vfork == fork */
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-
-   case 0: /* plain fork */
-      SET_STATUS_from_SysRes(
-         ML_(do_fork_clone)(tid,
-                       cloneflags,      /* flags */
-                       (Int *)ARG3,     /* parent_tidptr */
-                       (Int *)ARG5));   /* child_tidptr */
-      break;
-
-   default:
-      /* should we just ENOSYS? */
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
-      VG_(message)(Vg_UserMsg, "\n");
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
-      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
-      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 |= SfYieldAfter;
-   }
-}
-
 PRE(sys_sigreturn)
 {
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
@@ -901,7 +690,7 @@
    GENX_(__NR_fsync,             sys_fsync),          // 118
    PLAX_(__NR_sigreturn,         sys_sigreturn),      // 119 ?/Linux
 
-   PLAX_(__NR_clone,             sys_clone),          // 120
+   LINX_(__NR_clone,             sys_clone),          // 120
 //zz    //   (__NR_setdomainname,     sys_setdomainname),  // 121 */*(?)
    GENXY(__NR_uname,             sys_newuname),       // 122
 //   PLAX_(__NR_modify_ldt,        sys_modify_ldt),     // 123

Modified: trunk/coregrind/m_syswrap/syswrap-arm64-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-arm64-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-arm64-linux.c Sun Dec 11 21:39:23 2016
@@ -138,14 +138,7 @@
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
 
-extern
-Long do_syscall_clone_arm64_linux ( Word (*fn)(void *),
-                                    void* child_stack,
-                                    Long  flags,
-                                    void* arg,
-                                    Int*  child_tid,
-                                    Int*  parent_tid,
-                                    void* tls );
+// See priv_syswrap-linux.h for arg profile.
 asm(
 ".text\n"
 ".globl do_syscall_clone_arm64_linux\n"
@@ -196,121 +189,6 @@
 static void assign_guest_tls(ThreadId ctid, Addr tlsptr);
 //ZZ static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
             
-/*
-   When a client clones, we need to keep track of the new thread.  This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-
-   2. initialize the thread's new VCPU state
-
-   3. create the thread using the same args as the client requested,
-   but using the scheduler entrypoint for IP, and a separate stack
-   for SP.
- */
-static SysRes do_clone ( ThreadId ptid,
-                         ULong flags,
-                         Addr  child_xsp,
-                         Int*  parent_tidptr,
-                         Int*  child_tidptr,
-                         Addr  child_tls )
-{
-   ThreadId     ctid = VG_(alloc_ThreadState)();
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
-   UWord*       stack;
-   SysRes       res;
-   ULong        x0;
-   vki_sigset_t blockall, savedmask;
-
-   VG_(sigfillset)(&blockall);
-
-   vg_assert(VG_(is_running_thread)(ptid));
-   vg_assert(VG_(is_valid_tid)(ctid));
-
-   stack = (UWord*)ML_(allocstack)(ctid);
-   if (stack == NULL) {
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
-      goto out;
-   }
-
-   /* Copy register state
-
-      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 xsp for the new thread, then
-      it actually gets a copy of the parent's xsp.
-   */
-   setup_child( &ctst->arch, &ptst->arch );
-
-   /* Make sys_clone appear to have returned Success(0) in the
-      child. */
-   ctst->arch.vex.guest_X0 = 0;
-
-   if (child_xsp != 0)
-      ctst->arch.vex.guest_XSP = child_xsp;
-
-   ctst->os_state.parent = ptid;
-
-   /* inherit signal mask */
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   /* Start the child with its threadgroup being the same as the
-      parent's.  This is so that any exit_group calls that happen
-      after the child is created but before it sets its
-      os_state.threadgroup field for real (in thread_wrapper in
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
-      a race condition in which the thread is unkillable (via
-      exit_group) because its threadgroup is not set.  The race window
-      is probably only a few hundred or a few thousand cycles long.
-      See #226116. */
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack)(child_xsp, ctst);
-
-   /* Assume the clone will succeed, and tell any tool that wants to
-      know that this thread has come into existence.  If the clone
-      fails, we'll send out a ll_exit notification for it at the out:
-      label below, to clean up. */
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
-
-   if (flags & VKI_CLONE_SETTLS) {
-      /* Just assign the tls pointer in the guest TPIDR_EL0. */
-      assign_guest_tls(ctid, child_tls);
-   }
-    
-   flags &= ~VKI_CLONE_SETTLS;
-
-   /* start the thread with everything blocked */
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
-
-   x0 = do_syscall_clone_arm64_linux(
-      ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
-      child_tidptr, parent_tidptr, NULL
-   );
-    
-   res = VG_(mk_SysRes_arm64_linux)( x0 );
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-
-  out:
-   if (sr_isError(res)) {
-      /* clone failed */
-      VG_(cleanup_thread)(&ctst->arch);
-      ctst->status = VgTs_Empty;
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
-      VG_TRACK( pre_thread_ll_exit, ctid );
-   }
-
-   return res;
-}
-
-
 /* ---------------------------------------------------------------------
    More thread stuff
    ------------------------------------------------------------------ */
@@ -397,7 +275,6 @@
 //ZZ DECL_TEMPLATE(arm_linux, sys_lstat64);
 //ZZ DECL_TEMPLATE(arm_linux, sys_fstatat64);
 //ZZ DECL_TEMPLATE(arm_linux, sys_fstat64);
-DECL_TEMPLATE(arm64_linux, sys_clone);
 //ZZ DECL_TEMPLATE(arm_linux, sys_sigreturn);
 DECL_TEMPLATE(arm64_linux, sys_rt_sigreturn);
 //ZZ DECL_TEMPLATE(arm_linux, sys_sigsuspend);
@@ -512,110 +389,6 @@
 //ZZ    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
 //ZZ }
 
-/* Aarch64 seems to use CONFIG_CLONE_BACKWARDS in the kernel.  See:
-      http://dev.gentoo.org/~vapier/aarch64/linux-3.12.6.config
-      http://people.redhat.com/wcohen/aarch64/aarch64_config
-   from linux-3.10.5/kernel/fork.c
-    #ifdef CONFIG_CLONE_BACKWARDS
-    SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
-                     int __user *, parent_tidptr,
-                     int, tls_val,
-                     int __user *, child_tidptr)
-*/
-PRE(sys_clone)
-{
-   UInt cloneflags;
-
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
-   PRE_REG_READ5(int, "clone",
-                 unsigned long, flags,
-                 void *, child_stack,
-                 int *, parent_tidptr,
-                 void *, child_tls,
-                 int *, child_tidptr);
-
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
-                                             VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-//ZZ    if (ARG1 & VKI_CLONE_SETTLS) {
-//ZZ       PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
-//ZZ       if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
-//ZZ                                              VKI_PROT_READ)) {
-//ZZ          SET_STATUS_Failure( VKI_EFAULT );
-//ZZ          return;
-//ZZ       }
-//ZZ    }
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
-                                             VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-
-   cloneflags = 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
-                         | 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 */
-                  (Addr)ARG4)); /* tls_val */
-      break;
-
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-      /* FALLTHROUGH - assume vfork == fork */
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-
-   case 0: /* plain fork */
-      SET_STATUS_from_SysRes(
-         ML_(do_fork_clone)(tid,
-                       cloneflags,     /* flags */
-                       (Int*)ARG3,     /* parent_tidptr */
-                       (Int*)ARG5));   /* child_tidptr */
-      break;
-
-   default:
-      /* should we just ENOSYS? */
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
-      VG_(message)(Vg_UserMsg, "\n");
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
-      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
-      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 |= SfYieldAfter;
-   }
-}
-
 //ZZ PRE(sys_sigreturn)
 //ZZ {
 //ZZ    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
@@ -1072,7 +845,7 @@
    LINX_(__NR_add_key,           sys_add_key),           // 217
 
    LINXY(__NR_keyctl,            sys_keyctl),            // 219
-   PLAX_(__NR_clone,             sys_clone),             // 220
+   LINX_(__NR_clone,             sys_clone),             // 220
    GENX_(__NR_execve,            sys_execve),            // 221
    PLAX_(__NR_mmap,              sys_mmap),              // 222
    PLAX_(__NR_fadvise64,         sys_fadvise64),         // 223

Modified: trunk/coregrind/m_syswrap/syswrap-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-linux.c Sun Dec 11 21:39:23 2016
@@ -93,9 +93,8 @@
    VG_TRACK(pre_thread_first_insn, tid);
 
    tst->os_state.lwpid = VG_(gettid)();
-   /* Set the threadgroup for real.  This overwrites the provisional
-      value set in do_clone() syswrap-*-linux.c.  See comments in
-      do_clone for background, also #226116. */
+   /* Set the threadgroup for real.  This overwrites the provisional value set
+      in do_clone().  See comments in do_clone for background, also #226116. */
    tst->os_state.threadgroup = VG_(getpid)();
 
    /* Thread created with all signals blocked; scheduler will set the
@@ -430,17 +429,327 @@
    vg_assert(0);
 }
 
+/* Clone a new thread. Note that in the clone syscalls, we hard-code
+   tlsaddr argument as NULL : the guest TLS is emulated via guest
+   registers, and Valgrind itself has no thread local storage. */
+static SysRes clone_new_thread ( Word (*fn)(void *),
+                                 void* stack,
+                                 Word  flags,
+                                 ThreadState* ctst,
+                                 Int* child_tidptr,
+                                 Int* parent_tidptr)
+{
+   SysRes res;
+   /* Note that in all the below, we make sys_clone appear to have returned
+      Success(0) in the child, by assigning the relevant child guest
+      register(s) just before the clone syscall. */
+#if defined(VGP_x86_linux)
+   Int          eax;
+   ctst->arch.vex.guest_EAX = 0;
+   eax = do_syscall_clone_x86_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   res = VG_(mk_SysRes_x86_linux)( eax );
+#elif defined(VGP_amd64_linux)
+   Long         rax;
+   ctst->arch.vex.guest_RAX = 0;
+   rax = do_syscall_clone_amd64_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   res = VG_(mk_SysRes_amd64_linux)( rax );
+#elif defined(VGP_ppc32_linux)
+   ULong        word64;
+   UInt old_cr = LibVEX_GuestPPC32_get_CR( &ctst->arch.vex );
+   /* %r3 = 0 */
+   ctst->arch.vex.guest_GPR3 = 0;
+   /* %cr0.so = 0 */
+   LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
+   word64 = do_syscall_clone_ppc32_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   /* High half word64 is syscall return value.  Low half is
+      the entire CR, from which we need to extract CR0.SO. */
+   /* VG_(printf)("word64 = 0x%llx\n", word64); */
+   res = VG_(mk_SysRes_ppc32_linux)(/*val*/(UInt)(word64 >> 32),
+                                    /*errflag*/ (((UInt)word64) >> 28) & 1);
+#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
+   ULong        word64;
+   UInt old_cr = LibVEX_GuestPPC64_get_CR( &ctst->arch.vex );
+   /* %r3 = 0 */
+   ctst->arch.vex.guest_GPR3 = 0;
+   /* %cr0.so = 0 */
+   LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
+   word64 = do_syscall_clone_ppc64_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   /* Low half word64 is syscall return value.  Hi half is
+      the entire CR, from which we need to extract CR0.SO. */
+   /* VG_(printf)("word64 = 0x%llx\n", word64); */
+   res = VG_(mk_SysRes_ppc64_linux)
+      (/*val*/(UInt)(word64 & 0xFFFFFFFFULL),
+       /*errflag*/ (UInt)((word64 >> (32+28)) & 1));
+#elif defined(VGP_s390x_linux)
+   ULong        r2;
+   ctst->arch.vex.guest_r2 = 0;
+   r2 = do_syscall_clone_s390x_linux
+      (stack, flags, parent_tidptr, child_tidptr, NULL,
+       ML_(start_thread_NORETURN), ctst);
+   res = VG_(mk_SysRes_s390x_linux)( r2 );
+#elif defined(VGP_arm64_linux)
+   ULong        x0;
+   ctst->arch.vex.guest_X0 = 0;
+   x0 = do_syscall_clone_arm64_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   res = VG_(mk_SysRes_arm64_linux)( x0 );
+#elif defined(VGP_arm_linux)
+   UInt r0;
+   ctst->arch.vex.guest_R0 = 0;
+   r0 = do_syscall_clone_arm_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   res = VG_(mk_SysRes_arm_linux)( r0 );
+#elif defined(VGP_mips64_linux)
+   UInt ret = 0;
+   ctst->arch.vex.guest_r2 = 0;
+   ctst->arch.vex.guest_r7 = 0;
+   ret = do_syscall_clone_mips64_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       parent_tidptr, NULL, child_tidptr);
+   res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0);
+#elif defined(VGP_mips32_linux)
+   UInt ret = 0;
+   ctst->arch.vex.guest_r2 = 0;
+   ctst->arch.vex.guest_r7 = 0;
+   ret = do_syscall_clone_mips_linux
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   /* High half word64 is syscall return value.  Low half is
+      the entire CR, from which we need to extract CR0.SO. */
+   res = VG_ (mk_SysRes_mips32_linux) (/*val */ ret, 0, /*errflag */ 0);
+#elif defined(VGP_tilegx_linux)
+   Long ret = 0;
+   ctst->arch.vex.guest_r0 = 0;
+   ctst->arch.vex.guest_r3 = 0;
+   ret = do_syscall_clone_tilegx_linux
+      (ML_ (start_thread_NORETURN), stack, flags, ctst,
+       child_tidptr, parent_tidptr, NULL);
+   /* High half word64 is syscall return value. */
+   res = VG_(mk_SysRes_tilegx_linux) (/*val */ ret);
+#else
+# error Unknown platform
+#endif
+   return res;
+}
+
+static void setup_child ( /*OUT*/ ThreadArchState *child,
+                          /*IN*/  ThreadArchState *parent )
+{  
+   /* We inherit our parent's guest state. */
+   child->vex = parent->vex;
+   child->vex_shadow1 = parent->vex_shadow1;
+   child->vex_shadow2 = parent->vex_shadow2;
+
+#if defined(VGP_x86_linux)
+   extern void ML_(x86_setup_LDT_GDT) ( /*OUT*/ ThreadArchState *child,
+                                        /*IN*/  ThreadArchState *parent );
+   ML_(x86_setup_LDT_GDT)(child, parent);
+#endif
+}
+
+static SysRes setup_child_tls (ThreadId ctid, Addr tlsaddr)
+{
+   static const Bool debug = False;
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   // res is succesful by default, overriden if a real syscall is needed/done.
+   SysRes res = VG_(mk_SysRes_Success)(0);
+
+   if (debug)
+      VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
+
+#if defined(VGP_x86_linux)
+   vki_modify_ldt_t* tlsinfo = (vki_modify_ldt_t*)tlsaddr;
+   if (debug)
+      VG_(printf)("clone child has SETTLS: tls info at %p: idx=%u "
+                  "base=%#lx limit=%x; esp=%#x fs=%x gs=%x\n",
+                  tlsinfo, tlsinfo->entry_number,
+                  tlsinfo->base_addr, tlsinfo->limit,
+                  ctst->arch.vex.guest_ESP,
+                  ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
+   res = ML_(x86_sys_set_thread_area)(ctid, tlsinfo);
+#elif defined(VGP_amd64_linux)
+   ctst->arch.vex.guest_FS_CONST = tlsaddr;
+#elif defined(VGP_ppc32_linux)
+   ctst->arch.vex.guest_GPR2 = tlsaddr;
+#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
+   ctst->arch.vex.guest_GPR13 = tlsaddr;
+#elif defined(VGP_s390x_linux)
+   ctst->arch.vex.guest_a0 = (UInt) (tlsaddr >> 32);
+   ctst->arch.vex.guest_a1 = (UInt) tlsaddr;
+#elif defined(VGP_arm64_linux)
+   /* Just assign the tls pointer in the guest TPIDR_EL0. */
+   ctst->arch.vex.guest_TPIDR_EL0 = tlsaddr;
+#elif defined(VGP_arm_linux)
+   /* Just assign the tls pointer in the guest TPIDRURO. */
+   ctst->arch.vex.guest_TPIDRURO = tlsaddr;
+#elif defined(VGP_mips64_linux)
+   ctst->arch.vex.guest_ULR = tlsaddr;
+   ctst->arch.vex.guest_r27 = tlsaddr;
+#elif defined(VGP_mips32_linux)
+   ctst->arch.vex.guest_ULR = tlsaddr;
+   ctst->arch.vex.guest_r27 = tlsaddr;
+#elif defined(VGP_tilegx_linux)
+   ctst->arch.vex.guest_r53 = tlsaddr;
+#else
+# error Unknown platform
+#endif
+   return res;
+}
+
+/*
+   When a client clones, we need to keep track of the new thread.  This means:
+   1. allocate a ThreadId+ThreadState+stack for the thread
+
+   2. initialize the thread's new VCPU state
+
+   3. create the thread using the same args as the client requested,
+   but using the scheduler entrypoint for EIP, and a separate stack
+   for ESP.
+ */
+static SysRes do_clone ( ThreadId ptid,
+                         UWord flags, Addr sp,
+                         Int* parent_tidptr,
+                         Int* child_tidptr,
+                         Addr tlsaddr)
+{
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(ptid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   UWord*       stack;
+   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 = (UWord*)ML_(allocstack)(ctid);
+   if (stack == NULL) {
+      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
+      goto out;
+   }
+
+   /* Copy register state
+
+      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 );
+
+   if (sp != 0)
+      VG_(set_SP)(ctid, sp);
+
+   ctst->os_state.parent = ptid;
+
+   /* inherit signal mask */
+   ctst->sig_mask     = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   /* Start the child with its threadgroup being the same as the
+      parent's.  This is so that any exit_group calls that happen
+      after the child is created but before it sets its
+      os_state.threadgroup field for real (in thread_wrapper in
+      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
+      a race condition in which the thread is unkillable (via
+      exit_group) because its threadgroup is not set.  The race window
+      is probably only a few hundred or a few thousand cycles long.
+      See #226116. */
+   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+
+   ML_(guess_and_register_stack) (sp, ctst);
+  
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  We cannot defer
+      it beyond this point because setup_tls, just below,
+      causes checks to assert by making references to the new ThreadId
+      if we don't state the new thread exists prior to that point.
+      If the clone fails, we'll send out a ll_exit notification for it
+      at the out: label below, to clean up. */
+   vg_assert(VG_(owns_BigLock_LL)(ptid));
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
+   if (flags & VKI_CLONE_SETTLS) {
+      res = setup_child_tls(ctid, tlsaddr);
+      if (sr_isError(res))
+ goto out;
+   }
+   flags &= ~VKI_CLONE_SETTLS;
+
+   /* start the thread with everything blocked */
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+   /* Create the new thread */
+   res = clone_new_thread ( ML_(start_thread_NORETURN), stack, flags, ctst,
+                            child_tidptr, parent_tidptr);
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+  out:
+   if (sr_isError(res)) {
+      /* clone failed */
+      VG_(cleanup_thread)(&ctst->arch);
+      ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
+   }
+
+#if defined(VGP_mips64_linux) || defined(VGP_mips32_linux)
+   // ??? why do we set unconditionally r2 to 0, even when error out ???
+   ptst->arch.vex.guest_r2 = 0;
+#elif defined(VGP_tilegx_linux)
+   // ??? why do we set unconditionally r0 to 0, even when error out ???
+   ptst->arch.vex.guest_r0 = 0;
+#endif
 
-/* Do a clone which is really a fork() */
-SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
-                            Int* parent_tidptr, Int* child_tidptr )
+   return res;
+}
+
+/* Do a clone which is really a fork().
+   ML_(do_fork_clone) uses the clone syscall to fork a child process.
+   Note that this should not be called for a thread creation.
+   Also, some flags combinations are not supported, and such combinations
+   are handled either by masking the non supported flags or by asserting.
+
+   The CLONE_VFORK flag is accepted, as this just tells that the parent is
+   suspended till the child exits or calls execve. We better keep this flag,
+   just in case the guests parent/client code depends on this synchronisation.
+
+   We cannot keep the flag CLONE_VM, as Valgrind will do whatever host
+   instructions in the child process, that will mess up the parent host
+   memory. So, we hope for the best and assumes that the guest application does
+   not (really) depends on sharing the memory between parent and child in the
+   interval between clone and exits/execve.
+
+   If child_sp != 0, the child (guest) sp will be set to child_sp just after the
+   clone syscall, before child guest instructions are executed. */
+static SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
+                                   Int* parent_tidptr, Int* child_tidptr,
+                                   Addr child_sp)
 {
    vki_sigset_t fork_saved_mask;
    vki_sigset_t mask;
    SysRes       res;
 
    if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
-                | VKI_CLONE_FILES | VKI_CLONE_VFORK))
+                | VKI_CLONE_FILES))
       return VG_(mk_SysRes_Error)( VKI_EINVAL );
 
    /* Block all signals during fork, so that we can fix things up in
@@ -476,6 +785,8 @@
 
    if (!sr_isError(res) && sr_Res(res) == 0) {
       /* child */
+      if (child_sp != 0)
+          VG_(set_SP)(tid, child_sp);
       VG_(do_atfork_child)(tid);
 
       /* restore signal mask */
@@ -508,7 +819,6 @@
    return res;
 }
 
-
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for arch-generic, Linux-specific syscalls
    ------------------------------------------------------------------ */
@@ -519,6 +829,157 @@
 #define PRE(name)       DEFN_PRE_TEMPLATE(linux, name)
 #define POST(name)      DEFN_POST_TEMPLATE(linux, name)
 
+PRE(sys_clone)
+{
+   UInt cloneflags;
+   Bool badarg = False;
+
+   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
+
+// Order of arguments differs between platforms.
+#if defined(VGP_x86_linux) \
+    || defined(VGP_ppc32_linux) \
+    || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
+    || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
+    || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
+#define ARG_CHILD_TIDPTR ARG5
+#define PRA_CHILD_TIDPTR PRA5
+#define ARG_TLS          ARG4
+#define PRA_TLS          PRA4
+#elif defined(VGP_amd64_linux) || defined(VGP_tilegx_linux) \
+    || defined(VGP_s390x_linux)
+#define ARG_CHILD_TIDPTR ARG4
+#define PRA_CHILD_TIDPTR PRA4
+#define ARG_TLS          ARG5
+#define PRA_TLS          PRA5
+#else
+# error Unknown platform
+#endif
+// And s390x is even more special, and inverts flags and child stack args
+#if defined(VGP_s390x_linux)
+#define ARG_FLAGS       ARG2
+#define PRA_FLAGS       PRA2
+#define ARG_CHILD_STACK ARG1
+#define PRA_CHILD_STACK PRA1
+#else
+#define ARG_FLAGS       ARG1
+#define PRA_FLAGS       PRA1
+#define ARG_CHILD_STACK ARG2
+#define PRA_CHILD_STACK PRA2
+#endif
+
+   if (VG_(tdict).track_pre_reg_read) {
+      PRA_FLAGS("clone", unsigned long, flags);
+      PRA_CHILD_STACK("clone",  void *, child_stack);
+   }
+
+   if (ARG_FLAGS & VKI_CLONE_PARENT_SETTID) {
+      if (VG_(tdict).track_pre_reg_read) {
+         PRA3("clone", int *, parent_tidptr);
+      }
+      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
+      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
+                                             VKI_PROT_WRITE)) {
+         badarg = True;
+      }
+   }
+   if (ARG_FLAGS & VKI_CLONE_SETTLS) {
+      if (VG_(tdict).track_pre_reg_read) {
+         PRA_TLS("clone", vki_modify_ldt_t *, tlsinfo);
+      }
+      /* Not very clear what is vki_modify_ldt_t: for many platforms, it is a
+         dummy type (that we define as a char). We only dereference/check the
+         ARG_TLS pointer if the type looks like a real type, i.e. sizeof > 1. */
+      if (sizeof(vki_modify_ldt_t) > 1) {
+         PRE_MEM_READ("clone(tlsinfo)", ARG_TLS, sizeof(vki_modify_ldt_t));
+         if (!VG_(am_is_valid_for_client)(ARG_TLS, sizeof(vki_modify_ldt_t),
+                                          VKI_PROT_READ)) {
+            badarg = True;
+         }
+      }
+   }
+   if (ARG_FLAGS & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
+      if (VG_(tdict).track_pre_reg_read) {
+         PRA_CHILD_TIDPTR("clone", int *, child_tidptr);
+      }
+      PRE_MEM_WRITE("clone(child_tidptr)", ARG_CHILD_TIDPTR, sizeof(Int));
+      if (!VG_(am_is_valid_for_client)(ARG_CHILD_TIDPTR, sizeof(Int),
+                                             VKI_PROT_WRITE)) {
+         badarg = True;
+      }
+   }
+
+   if (badarg) {
+      SET_STATUS_Failure( VKI_EFAULT );
+      return;
+   }
+
+   cloneflags = ARG_FLAGS;
+
+   if (!ML_(client_signal_OK)(ARG_FLAGS & 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
+                         | 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,
+                  ARG_FLAGS,               /* flags */
+                  (Addr)ARG_CHILD_STACK,   /* child ESP */
+                  (Int*)ARG3,              /* parent_tidptr */
+                  (Int*)ARG_CHILD_TIDPTR,  /* child_tidptr */
+                  (Addr)ARG_TLS));         /* set_tls */
+      break;
+
+   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
+      // FALLTHROUGH - assume vfork (somewhat) == fork, see ML_(do_fork_clone).
+      cloneflags &= ~VKI_CLONE_VM;
+
+   case 0: /* plain fork */
+      SET_STATUS_from_SysRes(
+         ML_(do_fork_clone)(tid,
+                       cloneflags,      /* flags */
+                       (Int*)ARG3,     /* parent_tidptr */
+                       (Int*)ARG_CHILD_TIDPTR,     /* child_tidptr */
+                       (Addr)ARG_CHILD_STACK));
+      break;
+
+   default:
+      /* should we just ENOSYS? */
+      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG_FLAGS);
+      VG_(message)(Vg_UserMsg, "\n");
+      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
+      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
+      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
+      VG_(unimplemented)
+         ("Valgrind does not support general clone().");
+   }
+
+   if (SUCCESS) {
+      if (ARG_FLAGS & VKI_CLONE_PARENT_SETTID)
+         POST_MEM_WRITE(ARG3, sizeof(Int));
+      if (ARG_FLAGS & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
+         POST_MEM_WRITE(ARG_CHILD_TIDPTR, sizeof(Int));
+
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      *flags |= SfYieldAfter;
+   }
+
+#undef ARG_CHILD_TIDPTR
+#undef PRA_CHILD_TIDPTR
+#undef ARG_TLS
+#undef PRA_TLS
+#undef ARG_FLAGS
+#undef PRA_FLAGS
+#undef ARG_CHILD_STACK
+#undef PRA_CHILD_STACK
+}
+
 /* ---------------------------------------------------------------------
    *mount wrappers
    ------------------------------------------------------------------ */

Modified: trunk/coregrind/m_syswrap/syswrap-mips32-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-mips32-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-mips32-linux.c Sun Dec 11 21:39:23 2016
@@ -144,14 +144,7 @@
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
 
-//extern
-UInt do_syscall_clone_mips_linux (Word (*fn) (void *), //a0      0     32
-                                   void *stack,         //a1      4     36
-                                   Int flags,           //a2      8     40
-                                   void *arg,           //a3      12    44
-                                   Int * child_tid,     //stack   16    48
-                                   Int * parent_tid,    //stack   20    52
-                                   Int tls);          //stack   24    56
+// See priv_syswrap-linux.h for arg profile.
 asm (
 ".text\n"
 "   .globl   do_syscall_clone_mips_linux\n"
@@ -219,109 +212,10 @@
 #undef __NR_EXIT
 
 // forward declarations
-
-static void setup_child (ThreadArchState *, ThreadArchState *);
 static SysRes sys_set_tls (ThreadId tid, Addr tlsptr);
 static SysRes mips_PRE_sys_mmap (ThreadId tid,
                                  UWord arg1, UWord arg2, UWord arg3,
                                  UWord arg4, UWord arg5, Off64T arg6);
-/*
-   When a client clones, we need to keep track of the new thread.  This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-   2. initialize the thread's new VCPU state
-   3. create the thread using the same args as the client requested,
-   but using the scheduler entrypoint for IP, and a separate stack
-   for SP.
- */
-
-static SysRes do_clone (ThreadId ptid,
-                        UInt flags, Addr sp,
-                        Int * parent_tidptr,
-                        Int * child_tidptr,
-                        Addr child_tls)
-{
-   const Bool debug = False;
-   ThreadId ctid = VG_ (alloc_ThreadState) ();
-   ThreadState * ptst = VG_ (get_ThreadState) (ptid);
-   ThreadState * ctst = VG_ (get_ThreadState) (ctid);
-   UInt ret = 0;
-   UWord * stack;
-   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 = (UWord *) ML_ (allocstack) (ctid);
-   if (stack == NULL) {
-      res = VG_ (mk_SysRes_Error) (VKI_ENOMEM);
-      goto out;
-   }
-   setup_child (&ctst->arch, &ptst->arch);
-
-   /* on MIPS we need to set V0 and A3 to zero */
-   ctst->arch.vex.guest_r2 = 0;
-   ctst->arch.vex.guest_r7 = 0;
-   if (sp != 0)
-      ctst->arch.vex.guest_r29 = sp;
-
-   ctst->os_state.parent = ptid;
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   /* Start the child with its threadgroup being the same as the
-      parent's.  This is so that any exit_group calls that happen
-      after the child is created but before it sets its
-      os_state.threadgroup field for real (in thread_wrapper in
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
-      a race condition in which the thread is unkillable (via
-      exit_group) because its threadgroup is not set.  The race window
-      is probably only a few hundred or a few thousand cycles long.
-      See #226116. */
-
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack) (sp, ctst);
-
-   VG_TRACK (pre_thread_ll_create, ptid, ctid);
-   if (flags & VKI_CLONE_SETTLS) {
-      if (debug)
-        VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
-      ctst->arch.vex.guest_r27 = child_tls;
-      res = sys_set_tls(ctid, child_tls);
-      if (sr_isError(res))
-         goto out;
-      ctst->arch.vex.guest_r27 = child_tls;
-  }
-
-   flags &= ~VKI_CLONE_SETTLS;
-   VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask);
-   /* Create the new thread */
-   ret = do_syscall_clone_mips_linux (ML_ (start_thread_NORETURN),
-                                    stack, flags, &VG_ (threads)[ctid],
-                                    child_tidptr, parent_tidptr,
-                                    0 /*child_tls*/);
-
-   /* High half word64 is syscall return value.  Low half is
-      the entire CR, from which we need to extract CR0.SO. */
-   if (debug)
-      VG_(printf)("ret: 0x%x\n", ret);
-
-   res = VG_ (mk_SysRes_mips32_linux) (/*val */ ret, 0, /*errflag */ 0);
-
-   VG_ (sigprocmask) (VKI_SIG_SETMASK, &savedmask, NULL);
-
-   out:
-   if (sr_isError (res)) {
-      VG_(cleanup_thread) (&ctst->arch);
-      ctst->status = VgTs_Empty;
-      VG_TRACK (pre_thread_ll_exit, ctid);
-   }
-   ptst->arch.vex.guest_r2 = 0;
-
-   return res;
-}
-
 /* ---------------------------------------------------------------------
    More thread stuff
    ------------------------------------------------------------------ */
@@ -331,16 +225,6 @@
 void
 VG_ (cleanup_thread) (ThreadArchState * arch) { }
 
-void
-setup_child ( /*OUT*/ ThreadArchState * child,
-              /*IN*/ ThreadArchState * parent)
-{
-   /* We inherit our parent's guest state. */
-   child->vex = parent->vex;
-   child->vex_shadow1 = parent->vex_shadow1;
-   child->vex_shadow2 = parent->vex_shadow2;
-}
-
 SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
 {
    VG_(threads)[tid].arch.vex.guest_ULR = tlsptr;
@@ -521,7 +405,6 @@
 DECL_TEMPLATE (mips_linux, sys_fadvise64);
 DECL_TEMPLATE (mips_linux, sys_fstatat64);
 DECL_TEMPLATE (mips_linux, sys_fstat64);
-DECL_TEMPLATE (mips_linux, sys_clone);
 DECL_TEMPLATE (mips_linux, sys_sigreturn);
 DECL_TEMPLATE (mips_linux, sys_rt_sigreturn);
 DECL_TEMPLATE (mips_linux, sys_cacheflush);
@@ -636,96 +519,6 @@
   POST_MEM_WRITE (ARG2, sizeof (struct vki_stat64));
 }
 
-PRE(sys_clone)
-  {
-    Bool badarg = False;
-    UInt cloneflags;
-    PRINT ("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3,
-                                                        ARG4, ARG5);
-    PRE_REG_READ2 (int, "clone", unsigned long, flags,  void *, child_stack);
-    if (ARG1 & VKI_CLONE_PARENT_SETTID)
-      {
-        if (VG_ (tdict).track_pre_reg_read)
-          {
-            PRA3 ("clone", int *, parent_tidptr);
-          }
-        PRE_MEM_WRITE ("clone(parent_tidptr)", ARG3, sizeof (Int));
-        if (!VG_ (am_is_valid_for_client)(ARG3, sizeof (Int), VKI_PROT_WRITE))
-        {
-          badarg = True;
-        }
-      }
-    if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
-      {
-        if (VG_ (tdict).track_pre_reg_read)
-          {
-            PRA5 ("clone", int *, child_tidptr);
-          }
-        PRE_MEM_WRITE ("clone(child_tidptr)", ARG5, sizeof (Int));
-        if (!VG_ (am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE))
-          {
-            badarg = True;
-          }
-      }
-    if (badarg)
-      {
-        SET_STATUS_Failure (VKI_EFAULT);
-        return;
-      }
-    cloneflags = 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
-           |VKI_CLONE_FILES | VKI_CLONE_VFORK))
-      {
-        case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
-        /* thread creation */
-        PRINT ("sys_clone1 ( %#lx, %#lx, %#lx, %#lx, %#lx )",
-               ARG1, ARG2, ARG3, ARG4, ARG5);
-        SET_STATUS_from_SysRes (do_clone (tid,
-                                          ARG1, /* flags */
-                                          (Addr) ARG2, /* child SP */
-                                          (Int *) ARG3, /* parent_tidptr */
-                                          (Int *) ARG5, /* child_tidptr */
-                                          (Addr) ARG4)); /* child_tls */
-
-        break;
-        case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-          /* FALLTHROUGH - assume vfork == fork */
-          cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-        case 0:  /* plain fork */
-          SET_STATUS_from_SysRes (ML_ (do_fork_clone) (tid,
-                                  cloneflags, /* flags */
-                                  (Int *) ARG3, /* parent_tidptr */
-                                  (Int *) ARG5)); /* child_tidptr */
-        break;
-        default:
-          /* should we just ENOSYS? */
-          VG_ (message) (Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
-          VG_ (message) (Vg_UserMsg, "\n");
-          VG_ (message) (Vg_UserMsg, "The only supported clone() uses are:\n");
-          VG_ (message) (Vg_UserMsg,
-                          " - via a threads library (LinuxThreads or NPTL)\n");
-          VG_ (message) (Vg_UserMsg,
-                          " - via the implementation of fork or vfork\n");
-          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 |= SfYieldAfter;
-      }
-}
-
 PRE(sys_sigreturn)
 {
   PRINT ("sys_sigreturn ( )");
@@ -991,7 +784,7 @@
    LINXY (__NR_ipc,                    sys_ipc),                     // 117
    GENX_ (__NR_fsync,                  sys_fsync),                   // 118
    PLAX_ (__NR_sigreturn,              sys_sigreturn),               // 119
-   PLAX_ (__NR_clone,                  sys_clone),                   // 120
+   LINX_ (__NR_clone,                  sys_clone),                   // 120
    //..    //   (__NR_setdomainname,     sys_setdomainname),     // 121
    GENXY (__NR_uname,                  sys_newuname),                // 122
    //..    PLAX_(__NR_modify_ldt,        sys_modify_ldt),        // 123

Modified: trunk/coregrind/m_syswrap/syswrap-mips64-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-mips64-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-mips64-linux.c Sun Dec 11 21:39:23 2016
@@ -136,14 +136,7 @@
 #define __NR_CLONE        __NR_clone
 #define __NR_EXIT         __NR_exit
 
-ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *),  /* a0 - 4 */
-                                      void* stack,          /* a1 - 5 */
-                                      Int   flags,          /* a2 - 6 */
-                                      void* arg,            /* a3 - 7 */
-                                      Int*  parent_tid,     /* a4 - 8 */
-                                      void* /* Int tls */,  /* a5 - 9 */
-                                      Int*  child_tid );    /* a6 - 10 */
-
+// See priv_syswrap-linux.h for arg profile.
 asm(
 ".text\n"
 ".set noreorder\n"
@@ -199,104 +192,13 @@
 #undef __NR_EXIT
 
 /* forward declarations */
-static void setup_child ( ThreadArchState *, ThreadArchState *);
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr);
 
-/* When a client clones, we need to keep track of the new thread. This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-
-   2. initialize the thread's new VCPU state
-
-   3. create the thread using the same args as the client requested, but using
-      the scheduler entrypoint for IP, and a separate stack for SP. */
-static SysRes do_clone ( ThreadId ptid,
-                         UInt flags, Addr sp,
-                         Int* parent_tidptr,
-                         Int* child_tidptr,
-                         Addr child_tls )
-{
-   const Bool debug = False;
-   ThreadId ctid = VG_ (alloc_ThreadState) ();
-   ThreadState * ptst = VG_ (get_ThreadState) (ptid);
-   ThreadState * ctst = VG_ (get_ThreadState) (ctid);
-   UInt ret = 0;
-   UWord * stack;
-   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 = (UWord *)ML_(allocstack)(ctid);
-   if (stack == NULL) {
-      res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
-      goto out;
-   }
-   setup_child(&ctst->arch, &ptst->arch);
-
-   /* on MIPS we need to set V0 and A3 to zero */
-   ctst->arch.vex.guest_r2 = 0;
-   ctst->arch.vex.guest_r7 = 0;
-   if (sp != 0)
-      ctst->arch.vex.guest_r29 = sp;
-
-   ctst->os_state.parent = ptid;
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack) (sp, ctst);
-
-   VG_TRACK(pre_thread_ll_create, ptid, ctid);
-   if (flags & VKI_CLONE_SETTLS) {
-       if (debug)
-         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
-       res = sys_set_tls(ctid, child_tls);
-       if (sr_isError(res))
-          goto out;
-       ctst->arch.vex.guest_r27 = child_tls;
-   }
-
-   flags &= ~VKI_CLONE_SETTLS;
-   VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask);
-   /* Create the new thread */
-   ret = do_syscall_clone_mips64_linux(ML_(start_thread_NORETURN),
-                                       stack, flags, &VG_(threads)[ctid],
-                                       parent_tidptr, NULL /*child_tls*/,
-                                       child_tidptr);
-   if (debug)
-     VG_(printf)("ret: 0x%x\n", ret);
-
-   res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0);
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-
-   out:
-   if (sr_isError (res)) {
-      VG_ (cleanup_thread) (&ctst->arch);
-      ctst->status = VgTs_Empty;
-      VG_TRACK (pre_thread_ll_exit, ctid);
-   }
-   ptst->arch.vex.guest_r2 = 0;
-
-   return res;
-}
-
 /* ---------------------------------------------------------------------
                           More thread stuff
    ------------------------------------------------------------------ */
 void VG_(cleanup_thread) ( ThreadArchState * arch ) { };
 
-void setup_child ( /* OUT */ ThreadArchState * child,
-                   /* IN  */ ThreadArchState * parent )
-{
-   /* We inherit our parent's guest state. */
-   child->vex = parent->vex;
-   child->vex_shadow1 = parent->vex_shadow1;
-   child->vex_shadow2 = parent->vex_shadow2;
-}
-
 SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
 {
    VG_(threads)[tid].arch.vex.guest_ULR = tlsptr;
@@ -316,7 +218,6 @@
    file, but that requires even more macro magic. */
 
 DECL_TEMPLATE (mips_linux, sys_set_thread_area);
-DECL_TEMPLATE (mips_linux, sys_clone);
 DECL_TEMPLATE (mips_linux, sys_tee);
 DECL_TEMPLATE (mips_linux, sys_splice);
 DECL_TEMPLATE (mips_linux, sys_vmsplice);
@@ -494,84 +395,6 @@
                                  (Off64T) ARG6);
    SET_STATUS_from_SysRes(r);
 }
-
-PRE(sys_clone)
-{
-   Bool badarg = False;
-   UInt cloneflags;
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3,
-                                                      ARG4, ARG5);
-   PRE_REG_READ2(int, "clone", unsigned long, flags, void *, child_stack);
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-      if (VG_(tdict).track_pre_reg_read) {
-         PRA3("clone", int *, parent_tidptr);
-      }
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
-         badarg = True;
-      }
-   }
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
-      if (VG_(tdict).track_pre_reg_read) {
-         PRA5("clone", int *, child_tidptr);
-      }
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof (Int));
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE))
-         badarg = True;
-   }
-   if (badarg) {
-      SET_STATUS_Failure(VKI_EFAULT);
-      return;
-   }
-   cloneflags = 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
-           |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 */
-                                         (Addr)ARG4));  /* child_tls */
-         break;
-
-      case VKI_CLONE_VFORK | VKI_CLONE_VM:  /* vfork */
-         /* FALLTHROUGH - assume vfork == fork */
-         cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-      case 0:  /* plain fork */
-         SET_STATUS_from_SysRes(ML_(do_fork_clone)(tid,
-                                cloneflags,     /* flags */
-                                (Int *)ARG3,    /* parent_tidptr */
-                                (Int *)ARG5));  /* child_tidptr */
-         break;
-
-      default:
-         /* should we just ENOSYS? */
-         VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
-         VG_(message)(Vg_UserMsg, "\n");
-         VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
-         VG_(message)(Vg_UserMsg,
-                       " - via a threads library (LinuxThreads or NPTL)\n");
-         VG_(message)(Vg_UserMsg,
-                       " - via the implementation of fork or vfork\n");
-         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 |= SfYieldAfter;
-   }
-}
-
 PRE(sys_rt_sigreturn)
 {
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-s390x-linux.c for
@@ -766,7 +589,7 @@
    LINXY (__NR_socketpair, sys_socketpair),
    LINX_ (__NR_setsockopt, sys_setsockopt),
    LINXY (__NR_getsockopt, sys_getsockopt),
-   PLAX_ (__NR_clone, sys_clone),
+   LINX_ (__NR_clone, sys_clone),
    GENX_ (__NR_fork, sys_fork),
    GENX_ (__NR_execve, sys_execve),
    GENX_ (__NR_exit, sys_exit),

Modified: trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c Sun Dec 11 21:39:23 2016
@@ -146,14 +146,7 @@
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
 
-extern
-ULong do_syscall_clone_ppc32_linux ( Word (*fn)(void *),
-                                     void* stack,
-                                     Int   flags,
-                                     void* arg,
-                                     Int*  child_tid,
-                                     Int*  parent_tid,
-                                     vki_modify_ldt_t * );
+// See priv_syswrap-linux.h for arg profile.
 asm(
 ".text\n"
 ".globl do_syscall_clone_ppc32_linux\n"
@@ -216,145 +209,6 @@
 #undef __NR_CLONE
 #undef __NR_EXIT
 
-// forward declarations
-static void setup_child ( ThreadArchState*, ThreadArchState* );
-
-/*
-   When a client clones, we need to keep track of the new thread.  This means:
-   1. allocate a ThreadId+ThreadState+stack for the thread
-
-   2. initialize the thread's new VCPU state
-
-   3. create the thread using the same args as the client requested,
-   but using the scheduler entrypoint for IP, and a separate stack
-   for SP.
- */
-static SysRes do_clone ( ThreadId ptid,
-                         UInt flags, Addr sp,
-                         Int *parent_tidptr,
-                         Int *child_tidptr,
-                         Addr child_tls)
-{
-   const Bool debug = False;
-
-   ThreadId     ctid = VG_(alloc_ThreadState)();
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
-   ULong        word64;
-   UWord*       stack;
-   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 = (UWord*)ML_(allocstack)(ctid);
-   if (stack == NULL) {
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
-      goto out;
-   }
-
-//?   /* make a stack frame */
-//?   stack -= 16;
-//?   *(UWord *)stack = 0;
-
-
-   /* Copy register state
-
-      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.
-
-      The child's TLS register (r2) gets set to the tlsaddr argument
-      if the CLONE_SETTLS flag is set.
-   */
-   setup_child( &ctst->arch, &ptst->arch );
-
-   /* Make sys_clone appear to have returned Success(0) in the
-      child. */
-   { UInt old_cr = LibVEX_GuestPPC32_get_CR( &ctst->arch.vex );
-     /* %r3 = 0 */
-     ctst->arch.vex.guest_GPR3 = 0;
-     /* %cr0.so = 0 */
-     LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
-   }
-
-   if (sp != 0)
-      ctst->arch.vex.guest_GPR1 = sp;
-
-   ctst->os_state.parent = ptid;
-
-   /* inherit signal mask */
-   ctst->sig_mask = ptst->sig_mask;
-   ctst->tmp_sig_mask = ptst->sig_mask;
-
-   /* Start the child with its threadgroup being the same as the
-      parent's.  This is so that any exit_group calls that happen
-      after the child is created but before it sets its
-      os_state.threadgroup field for real (in thread_wrapper in
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
-      a race condition in which the thread is unkillable (via
-      exit_group) because its threadgroup is not set.  The race window
-      is probably only a few hundred or a few thousand cycles long.
-      See #226116. */
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-
-   ML_(guess_and_register_stack) (sp, ctst);
-
-   /* Assume the clone will succeed, and tell any tool that wants to
-      know that this thread has come into existence.  If the clone
-      fails, we'll send out a ll_exit notification for it at the out:
-      label below, to clean up. */
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
-
-   if (flags & VKI_CLONE_SETTLS) {
-      if (debug)
-         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
-      ctst->arch.vex.guest_GPR2 = child_tls;
-   }
-
-   flags &= ~VKI_CLONE_SETTLS;
-
-   /* start the thread with everything blocked */
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
-
-   /* Create the new thread */
-   word64 = do_syscall_clone_ppc32_linux(
-               ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
-               child_tidptr, parent_tidptr, NULL
-            );
-   /* High half word64 is syscall return value.  Low half is
-      the entire CR, from which we need to extract CR0.SO. */
-   /* VG_(printf)("word64 = 0x%llx\n", word64); */
-   res = VG_(mk_SysRes_ppc32_linux)(
-            /*val*/(UInt)(word64 >> 32),
-            /*errflag*/ (((UInt)word64) >> 28) & 1
-         );
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
-
-  out:
-   if (sr_isError(res)) {
-      /* clone failed */
-      VG_(cleanup_thread)(&ctst->arch);
-      ctst->status = VgTs_Empty;
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
-      VG_TRACK( pre_thread_ll_exit, ctid );
-   }
-
-   return res;
-}
-
-
 
 /* ---------------------------------------------------------------------
    More thread stuff
@@ -364,16 +218,6 @@
 {
 }  
 
-void setup_child ( /*OUT*/ ThreadArchState *child,
-                   /*IN*/  ThreadArchState *parent )
-{
-   /* We inherit our parent's guest state. */
-   child->vex = parent->vex;
-   child->vex_shadow1 = parent->vex_shadow1;
-   child->vex_shadow2 = parent->vex_shadow2;
-}
-
-
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for ppc32/Linux-specific syscalls
    ------------------------------------------------------------------ */
@@ -393,7 +237,6 @@
 DECL_TEMPLATE(ppc32_linux, sys_lstat64);
 DECL_TEMPLATE(ppc32_linux, sys_fstatat64);
 DECL_TEMPLATE(ppc32_linux, sys_fstat64);
-DECL_TEMPLATE(ppc32_linux, sys_clone);
 DECL_TEMPLATE(ppc32_linux, sys_sigreturn);
 DECL_TEMPLATE(ppc32_linux, sys_rt_sigreturn);
 DECL_TEMPLATE(ppc32_linux, sys_sigsuspend);
@@ -530,91 +373,6 @@
 //..    }
 //.. }
 
-PRE(sys_clone)
-{
-   UInt cloneflags;
-
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
-   PRE_REG_READ5(int, "clone",
-                 unsigned long, flags,
-                 void *,        child_stack,
-                 int *,         parent_tidptr,
-                 void *,        child_tls,
-                 int *,         child_tidptr);
-
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
-      if (!VG_(am_is_valid_for_client)(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_(am_is_valid_for_client)(ARG5, sizeof(Int),
-                                             VKI_PROT_WRITE)) {
-         SET_STATUS_Failure( VKI_EFAULT );
-         return;
-      }
-   }
-
-   cloneflags = 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
-                         | 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 */
-                  (Addr)ARG4)); /* child_tls */
-      break;
-
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
-      /* FALLTHROUGH - assume vfork == fork */
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
-
-   case 0: /* plain fork */
-      SET_STATUS_from_SysRes(
-         ML_(do_fork_clone)(tid,
-                       cloneflags,      /* flags */
-                       (Int *)ARG3,     /* parent_tidptr */
-                       (Int *)ARG5));   /* child_tidptr */
-      break;
-
-   default:
-      /* should we just ENOSYS? */
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
-      VG_(message)(Vg_UserMsg, "\n");
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
-      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 |= SfYieldAfter;
-   }
-}
-
 PRE(sys_sigreturn)
 {
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
@@ -999,7 +757,7 @@
    GENX_(__NR_fsync,             sys_fsync),             // 118
    PLAX_(__NR_sigreturn,         sys_sigreturn),         // 119 ?/Linux
 //..
-   PLAX_(__NR_clone,             sys_clone),             // 120
+   LINX_(__NR_clone,             sys_clone),             // 120
 //..    //   (__NR_setdomainname,     sys_setdomainname),     // 121 */*(?)
    GENXY(__NR_uname,             sys_newuname),          // 122
 //..    PLAX_(__NR_modify_ldt,        sys_modify_ldt),        // 123


[... 1414 lines stripped ...]

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/xeonphi
_______________________________________________
Valgrind-developers mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers
Reply | Threaded
Open this post in threaded view
|

Re: Valgrind: r16186 - in /trunk: ./ coregrind/m_syswrap/ include/vki/ none/tests/linux/

Petar Jovanovic
On Sun, Dec 11, 2016 at 10:39 PM,  <[hidden email]> wrote:
>
> * for mips32/mips64 and tilegx, there is a strange unconditional assignment
>   of 0 to a register (guest_r2 on mips, guest_r0 on tilegx).

Not needed. Removed in r16188.
Thanks for noticing.

Regards,
Petar

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Valgrind-developers mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers
Reply | Threaded
Open this post in threaded view
|

Re: Valgrind: r16186 - in /trunk: ./ coregrind/m_syswrap/ include/vki/ none/tests/linux/

Philippe Waroquiers
On Fri, 2016-12-16 at 19:37 +0100, Petar Jovanovic wrote:
> On Sun, Dec 11, 2016 at 10:39 PM,  <[hidden email]> wrote:
> >
> > * for mips32/mips64 and tilegx, there is a strange unconditional assignment
> >   of 0 to a register (guest_r2 on mips, guest_r0 on tilegx).
>
> Not needed. Removed in r16188.
> Thanks for noticing.
And thanks for the cleanup.

The same question/remark is still pending for tilegx.
I do not remember any tilegx related commit/feedback/bug report or
whatever since more than one year.

Is there a contact person for tilegx/tilera ?


Philippe




------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/intel
_______________________________________________
Valgrind-developers mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers