* add syscall wrappers for some new OSX 10.10 specific calls
  necp_match_policy
    sysctlbyname
      getattrlistbulk (kludged)

* add initial entries for the resync-filter on OSX 10.10.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14718 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/priv_syswrap-darwin.h b/coregrind/m_syswrap/priv_syswrap-darwin.h
index e03d91e..566d782 100644
--- a/coregrind/m_syswrap/priv_syswrap-darwin.h
+++ b/coregrind/m_syswrap/priv_syswrap-darwin.h
@@ -534,7 +534,7 @@
 // NYI sfi_pidctl      // 457
 // NYI coalition       // 458
 // NYI coalition_info  // 459
-// NYI necp_match_policy  // 460
+DECL_TEMPLATE(darwin, necp_match_policy);        // 460
 DECL_TEMPLATE(darwin, getattrlistbulk);          // 461
 // 462
 // NYI openat          // 463
diff --git a/coregrind/m_syswrap/syswrap-darwin.c b/coregrind/m_syswrap/syswrap-darwin.c
index ab6eb06..39c8ecd 100644
--- a/coregrind/m_syswrap/syswrap-darwin.c
+++ b/coregrind/m_syswrap/syswrap-darwin.c
@@ -788,7 +788,7 @@
    CheckHowOften check = CheckAlways;
 
 #  if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
-   /* ------ BEGIN filter for 64-bit 10.9.x ------ */
+   /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
    if (when_after && where_mmr) {
       // "after mach_msg_receive <number>"
       switch (num) {
@@ -841,9 +841,68 @@
       // upd 1736 diff 78+,0- 
       check = CheckEvery20;
    }
-   /* ------- END filter for 64-bit 10.9.x ------- */
+   /* ----------- END filter for 64-bit 10.9.x ----------- */
 #  endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
 
+#  if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
+   /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
+   if (when_after && where_mmr) {
+      // "after mach_msg_receive <number>"
+      switch (num) {
+         case 0x00000000: // upd 2380 diff 23+,0-
+            check = CheckEvery20;
+            break;
+         default:
+            break;
+      }
+   }
+   else
+   if (when_after && where_mmrU) {
+      // "after mach_msg_receive-UNHANDLED <number>"
+      switch (num) {
+         case 0x00000000: // upd 2370 diff 93+,1-  <==dangerous
+         case 0x0000004f: // upd  212 diff 2+,0-
+         case 0x0000157f: // upd  201 diff 2+,0-
+         case 0x0000157d: // upd  197 diff 1+,0-        
+         case 0x0000333d: // upd  112 diff 0+,0-
+         case 0x0000333f: // upd  223 diff 10+,0-
+         case 0x000072ae: // upd  193 diff 10+,0-
+         case 0x000072ec: // upd  319 diff 7+,0-
+         case 0x77303074: // upd  113 diff 3+,0-
+         case 0x10000000: // upd  314 diff 6+,0-
+            check = CheckEvery20;
+            break;
+         default:
+            break;
+      }
+   }
+   else
+   if (when_in && where_MwcN && num == 0x00000000) {
+      // in ML_(wqthread_continue_NORETURN) 0x00000000
+      // upd 1110 diff 37+,0-
+      check = CheckEvery20;
+   }
+   else
+   if (when_after && where_woQR && num == 0x00000000) {
+      // after workq_ops(QUEUE_REQTHREADS) 0x00000000
+      // upd 1099 diff 37+,0-
+      check = CheckEvery20;
+   }
+   else
+   if (when_after && where_woTR && num == 0x00000000) {
+      // after workq_ops(THREAD_RETURN) 0x00000000
+      // 1239 diff 53+,0-
+      check = CheckEvery20;
+   }
+   else
+   if (when_after && where_ke64 && num == 0x00000000) {
+      // after kevent64 0x00000000
+      // upd 1463 diff 15+,0-
+      check = CheckEvery20;
+   }
+   /* ----------- END filter for 64-bit 10.10.x ----------- */
+#  endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
+
    /* Regardless of what the filter says, force a sync every 1 time in
       1000, to stop things getting too far out of sync. */
    {
@@ -1501,7 +1560,7 @@
 
    default:
       PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
-      VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
+      VG_(printf)("UNKNOWN fcntl %ld!\n", ARG2);
       break;
    }
 }
@@ -1921,7 +1980,8 @@
 
 PRE(__mac_syscall)
 {
-   PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
+         ARG1, (HChar*)ARG1, ARG2, ARG3);
    PRE_REG_READ3(int,"__mac_syscall", char *,"policy", 
                  int,"call", void *,"arg");
 
@@ -3972,100 +4032,122 @@
 }
 
 
-PRE(__sysctl)
+/* This function holds common elements of PRE(__sysctl) and
+   PRE(sysctlbyname). */
+static void common_PRE_sysctl (
+               /*IMPLICIT ARGS*/
+               ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
+               /*!IMPLICIT ARGS*/
+               Bool is_kern_dot_userstack,
+               UWord oldp, UWord oldlenp,
+               UWord newp, UWord newlen )
 {
-   PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", 
-          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
-
-   PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen, 
-                 void*, oldp, vki_size_t *, oldlenp, 
-                 void*, newp, vki_size_t *, newlenp);
-
-   PRE_MEM_READ("sysctl(name)", ARG1, ARG2);  // reads name[0..namelen-1]
-   if (ARG4) {
-      // writes *ARG4
-      PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
-      if (ARG3) {
-         // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
-         PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
-         PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
+   if (oldlenp) {
+      // writes *oldlenp
+      PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
+      if (oldp) {
+         // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
+         PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
+         PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
       }
    }
-   if (ARG5) {
-      PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
-   }
-
-   if (VG_(clo_trace_syscalls)) {
-      unsigned int i;
-      int *name = (int *)ARG1;
-      VG_(printf)(" mib: [ ");
-      for (i = 0; i < ARG2; i++) {
-         VG_(printf)("%d ", name[i]);
-      }
-      VG_(printf)("]");
+   if (newp) {
+      PRE_MEM_READ("sysctl(newp)", newp, newlen);
    }
 
    // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
    // (executable path and arguments and environment
-
-   {
-      // Intercept sysctl(kern.usrstack). The kernel's reply would be
-      // Valgrind's stack, not the client's stack.
-      // GrP fixme kern_usrstack64
-      if (ARG1  &&  ARG2 == 2  &&  
-          ((int *)ARG1)[0] == VKI_CTL_KERN  &&  
-#if VG_WORDSIZE == 4
-          ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
-#else
-          ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
-#endif
-          )
-      {
-         if (ARG5/*newp*/  ||  ARG6/*newlen*/) {
-            SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
-         } else {
-            Addr *oldp = (Addr *)ARG3;
-            size_t *oldlenp = (size_t *)ARG4;
-            if (oldlenp) {
-               // According to some searches on the net, it looks like USRSTACK
-               // gives the address of the byte following the highest byte of the stack
-               // As VG_(clstk_end) is the address of the highest addressable byte, we
-               // add +1.
-               Addr stack_end = VG_(clstk_end)+1;
-               size_t oldlen = *oldlenp;
-               // always return actual size
-               *oldlenp = sizeof(Addr);
-               if (oldp  &&  oldlen >= sizeof(Addr)) {
-                  // oldp is big enough
-                  // copy value and return 0
-                  *oldp = stack_end;
-                  SET_STATUS_Success(0);
-               } else {
-                  // oldp isn't big enough
-                  // copy as much as possible and return ENOMEM
-                  if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
-                  SET_STATUS_Failure(VKI_ENOMEM);
-               }
+        
+   if (is_kern_dot_userstack) {
+      // Intercept sysctl(kern.usrstack). The kernel's reply
+      // would be Valgrind's stack, not the client's stack.
+      // GrP fixme kern_usrstack64 */
+      if (newp || newlen) {
+         SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
+      } else {
+         Addr* t_oldp = (Addr*)oldp;
+         size_t* t_oldlenp = (size_t*)oldlenp;
+         if (t_oldlenp) {
+            // According to some searches on the net, it looks like
+            // USRSTACK gives the address of the byte following the
+            // highest byte of the stack.  As VG_(clstk_end) is the
+            // address of the highest addressable byte, we add 1.
+            Addr stack_end = VG_(clstk_end)+1;
+            size_t oldlen = *t_oldlenp;
+            // always return actual size
+            *t_oldlenp = sizeof(Addr);
+            if (t_oldp && oldlen >= sizeof(Addr)) {
+               // oldp is big enough.  copy value and return 0
+               *t_oldp = stack_end;
+               SET_STATUS_Success(0);
+            } else {
+               // oldp isn't big enough.  copy as much as possible
+               // and return ENOMEM
+               if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
+               SET_STATUS_Failure(VKI_ENOMEM);
             }
          }
       }
    }
 
-   if (!SUCCESS  &&  !FAILURE) {
+   if (!SUCCESS && !FAILURE) {
       // Don't set SfPostOnFail if we've already handled it locally.
       *flags |= SfPostOnFail;
    }
 }
 
+
+PRE(__sysctl)
+{
+   UWord name    = ARG1;
+   UWord namelen = ARG2;
+   UWord oldp    = ARG3;
+   UWord oldlenp = ARG4;
+   UWord newp    = ARG5;
+   UWord newlen  = ARG6;
+
+   PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", 
+          name, namelen, oldp, oldlenp, newp, newlen );
+
+   PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen, 
+                 void*, oldp, vki_size_t *, oldlenp, 
+                 void*, newp, vki_size_t *, newlenp);
+
+   PRE_MEM_READ("sysctl(name)", name, namelen);  // reads name[0..namelen-1]
+
+   if (VG_(clo_trace_syscalls)) {
+      UInt i;
+      Int* t_name = (Int*)name;
+      VG_(printf)(" mib: [ ");
+      for (i = 0; i < namelen; i++) {
+         VG_(printf)("%d ", t_name[i]);
+      }
+      VG_(printf)("]");
+   }
+
+   Int vKI_KERN_USRSTACKXX
+      = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64; 
+   Bool is_kern_dot_userstack
+      = name && namelen == 2
+        && ((Int*)name)[0] == VKI_CTL_KERN
+        && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
+
+   common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
+                      is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
+}
+
 POST(__sysctl)
 {
-   if (SUCCESS  ||  ERR == VKI_ENOMEM) {
+   UWord oldp    = ARG3;
+   UWord oldlenp = ARG4;
+
+   if (SUCCESS || ERR == VKI_ENOMEM) {
       // sysctl can write truncated data and return VKI_ENOMEM
-      if (ARG4) {
-         POST_MEM_WRITE(ARG4, sizeof(size_t));
+      if (oldlenp) {
+         POST_MEM_WRITE(oldlenp, sizeof(size_t));
       }
-      if (ARG3  &&  ARG4) {
-         POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
+      if (oldp && oldlenp) {
+         POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
       }
    }
 }
@@ -8939,13 +9021,70 @@
 
 #if DARWIN_VERS >= DARWIN_10_10
 
+PRE(necp_match_policy)
+{
+   // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
+   //                       struct necp_aggregate_result *returned_result)
+   PRINT("necp_match_policy(FIXME)(%lx,%ld, %lx)", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
+                 size_t, parameters_size, struct necp_aggregate_result*,
+                 returned_result);
+   PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
+}
+POST(necp_match_policy)
+{
+   POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
+}
+
 PRE(sysctlbyname)
 {
-   // int sysctlbyname(const char *name, size_t namelen, void *old,
-   //                  size_t *oldlenp, void *new, size_t newlen)
-   PRINT("sysctlbyname(FIXME)(%lx(%s),%ld, %lx,%lx, %lx,%lx)",
-         ARG1, ARG1 ? (const HChar*)ARG1 : "(null)",
-         ARG2, ARG3, ARG4, ARG5, ARG6);
+   UWord name    = ARG1;
+   UWord namelen = ARG2;
+   UWord oldp    = ARG3;
+   UWord oldlenp = ARG4;
+   UWord newp    = ARG5;
+   UWord newlen  = ARG6;
+
+   PRINT( "sysctlbyname ( %#lx,%ld, %#lx,%#lx, %#lx,%ld )", 
+          name, namelen, oldp, oldlenp, newp, newlen );
+
+   PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
+                 void*, oldp, vki_size_t *, oldlenp, 
+                 void*, newp, vki_size_t *, newlenp);
+
+   // reads name[0..namelen-1]
+   PRE_MEM_READ("sysctlbyname(name)", name, namelen);
+
+   if (VG_(clo_trace_syscalls)) {
+      UInt i;
+      const HChar* t_name = (const HChar*)name;
+      VG_(printf)(" name: ");
+      for (i = 0; i < namelen; i++) {
+         VG_(printf)("%c", t_name[i]);
+      }
+      VG_(printf)(" ");
+   }
+  
+   Bool is_kern_dot_userstack
+      = False;
+
+   common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
+                      is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
+}
+POST(sysctlbyname)
+{
+   UWord oldp    = ARG3;
+   UWord oldlenp = ARG4;
+
+   if (SUCCESS || ERR == VKI_ENOMEM) {
+      // sysctl can write truncated data and return VKI_ENOMEM
+      if (oldlenp) {
+         POST_MEM_WRITE(oldlenp, sizeof(size_t));
+      }
+      if (oldp && oldlenp) {
+         POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
+      }
+   }
 }
 
 PRE(getattrlistbulk)
@@ -8954,8 +9093,23 @@
    //                     void *attributeBuffer, size_t bufferSize,
    //                     uint64_t options);
    // Presumably the last arg is value-pair in the 32 bit case.
-   PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx, %lu, %lu)",
+   PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
          ARG1, ARG2, ARG3, ARG4, ARG5);
+   PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
+                 void*, attributeBuffer, size_t, bufferSize,
+                 uint32_t, options_lo32);
+   PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
+   PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
+}
+POST(getattrlistbulk)
+{
+   // FIXME: this isn't right.  It seems as if what is returned is a
+   // set of variable-length records -- see complication in
+   // POST(getattrlist).  For now, just paint the entire result buffer
+   // as defined.  Sigh.
+   vg_assert(SUCCESS);
+   if (ARG3 && /* "at least one output element was written" */RES > 0)
+      POST_MEM_WRITE(ARG3, ARG4);
 }
 
 PRE(bsdthread_ctl)
@@ -8963,6 +9117,8 @@
    // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1, 
    //                   user_addr_t arg2, user_addr_t arg3)
    PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(int, "bsdthreadctl",
+                 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
 }
 
 #endif /* DARWIN_VERS >= DARWIN_10_10 */
@@ -9478,9 +9634,10 @@
     MACX_(__NR_disconnectx, disconnectx),
 #endif
 #if DARWIN_VERS >= DARWIN_10_10
-   MACX_(__NR_sysctlbyname,    sysctlbyname),      // 274
-   MACX_(__NR_getattrlistbulk, getattrlistbulk),   // 461
-   MACX_(__NR_bsdthread_ctl,   bsdthread_ctl),     // 478
+   MACXY(__NR_sysctlbyname,        sysctlbyname),       // 274
+   MACXY(__NR_necp_match_policy,   necp_match_policy),  // 460
+   MACXY(__NR_getattrlistbulk,     getattrlistbulk),    // 461
+   MACX_(__NR_bsdthread_ctl,       bsdthread_ctl),      // 478
 #endif
 // _____(__NR_MAXSYSCALL)
    MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
diff --git a/include/vki/vki-darwin.h b/include/vki/vki-darwin.h
index bacda44..ea50a77 100644
--- a/include/vki/vki-darwin.h
+++ b/include/vki/vki-darwin.h
@@ -1062,4 +1062,20 @@
 //#define vki_errno_t
 typedef int vki_errno_t;
 
+
+/* necp stuff.  This doesn't appear to exist in any user space include
+   file. */
+#if DARWIN_VERS == DARWIN_10_10
+struct vki_necp_aggregate_result {
+   vki_u_int32_t field1;
+   unsigned int  field2;
+   vki_u_int32_t field3;
+   vki_u_int32_t field4;
+   vki_uuid_t    field5;
+   u_int32_t     field6;
+   u_int32_t     field7;
+};
+#endif /* DARWIN_VERS == DARWIN_10_10 */
+
+
 #endif
diff --git a/include/vki/vki-scnums-darwin.h b/include/vki/vki-scnums-darwin.h
index 49cdcac..8eeca10 100644
--- a/include/vki/vki-scnums-darwin.h
+++ b/include/vki/vki-scnums-darwin.h
@@ -712,6 +712,7 @@
 #endif /* DARWIN_VERS >= DARWIN_10_9 */
 
 #if DARWIN_VERS == DARWIN_10_10
+#define __NR_necp_match_policy      VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(460)
 #define __NR_getattrlistbulk        VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(461)
 #define __NR_bsdthread_ctl          VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(478)
 #endif