Add initial support for MacOSX 10.8.  Note this is still very borked
and pretty much unusable for real work.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12814 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/Makefile.am b/Makefile.am
index 1de4277..7d65a7f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,7 +43,7 @@
 	exp-sgcheck.supp \
 	darwin9.supp darwin9-drd.supp \
 	darwin10.supp darwin10-drd.supp \
-	darwin11.supp \
+	darwin11.supp darwin12.supp \
 	bionic.supp
 DEFAULT_SUPP_FILES = @DEFAULT_SUPP@
 
diff --git a/configure.in b/configure.in
index cefb428..90f0ee8 100644
--- a/configure.in
+++ b/configure.in
@@ -134,7 +134,7 @@
      notclang-4.*)
 	AC_MSG_RESULT([ok (${gcc_version})])
 	;;
-     clang-2.9|clang-3.*)
+     clang-2.9|clang-3.*|clang-4.*)
 	AC_MSG_RESULT([ok (clang-${gcc_version})])
 	;;
      *)
@@ -287,6 +287,7 @@
         AC_DEFINE([DARWIN_10_5], 100500, [DARWIN_VERS value for Mac OS X 10.5])
         AC_DEFINE([DARWIN_10_6], 100600, [DARWIN_VERS value for Mac OS X 10.6])
         AC_DEFINE([DARWIN_10_7], 100700, [DARWIN_VERS value for Mac OS X 10.7])
+        AC_DEFINE([DARWIN_10_8], 100800, [DARWIN_VERS value for Mac OS X 10.8])
 
 	AC_MSG_CHECKING([for the kernel version])
 	kernel=`uname -r`
@@ -323,10 +324,15 @@
 	     11.*)
 		  AC_MSG_RESULT([Darwin 11.x (${kernel}) / Mac OS X 10.7 Lion])
 		  AC_DEFINE([DARWIN_VERS], DARWIN_10_7, [Darwin / Mac OS X version])
-                  # FIXME: change these to xx11.supp
 		  DEFAULT_SUPP="darwin11.supp ${DEFAULT_SUPP}"
 		  DEFAULT_SUPP="darwin10-drd.supp ${DEFAULT_SUPP}"
 		  ;;
+	     12.*)
+		  AC_MSG_RESULT([Darwin 12.x (${kernel}) / Mac OS X 10.8 Mountain Lion])
+		  AC_DEFINE([DARWIN_VERS], DARWIN_10_8, [Darwin / Mac OS X version])
+		  DEFAULT_SUPP="darwin12.supp ${DEFAULT_SUPP}"
+		  DEFAULT_SUPP="darwin10-drd.supp ${DEFAULT_SUPP}"
+		  ;;
              *) 
 		  AC_MSG_RESULT([unsupported (${kernel})])
 		  AC_MSG_ERROR([Valgrind works on Darwin 10.x and 11.x (Mac OS X 10.6/7)])
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index f59301d..6e88124 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -956,7 +956,7 @@
 void VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
 {
    Bool do_nothing = True;
-#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
+#  if defined(VGP_x86_darwin) && (DARWIN_VERS == DARWIN_10_7 || DARWIN_VERS == DARWIN_10_8)
    do_nothing = False;
 #  endif
    if (do_nothing /* wrong platform */)
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 3d7fc1c..261586f 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -1284,6 +1284,15 @@
    else if (VG_(clo_verbosity) > 0)
       VG_(umsg)("\n");
 
+#  if defined(VGO_darwin) && DARWIN_VERS == DARWIN_10_8
+   /* Uh, this doesn't play nice with XML output. */
+   umsg_or_xml( "WARNING: Support on MacOS 10.8 is experimental and mostly broken.\n");
+   umsg_or_xml( "WARNING: Expect incorrect results, assertions and crashes.\n");
+   umsg_or_xml( "WARNING: In particular, Memcheck on 32-bit programs will fail to\n");
+   umsg_or_xml( "WARNING: detect any errors associated with heap-allocated data.\n");
+   umsg_or_xml( "\n" );
+#  endif
+
    if (VG_(clo_verbosity) > 1) {
       SysRes fd;
       VexArch vex_arch;
@@ -1602,7 +1611,12 @@
    VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
    { HChar* limLo  = (HChar*)(&VG_(interim_stack).bytes[0]);
      HChar* limHi  = limLo + sizeof(VG_(interim_stack));
-     HChar* aLocal = (HChar*)&zero; /* any auto local will do */
+     HChar* aLocal = (HChar*)&limLo; /* any auto local will do */
+     /* "Apple clang version 4.0 (tags/Apple/clang-421.0.57) (based on
+         LLVM 3.1svn)" appears to miscompile the following check,
+         causing run to abort at this point (in 64-bit mode) even
+         though aLocal is within limLo .. limHi.  Try building with
+         gcc instead. */
      if (aLocal < limLo || aLocal >= limHi) {
         /* something's wrong.  Stop. */
         VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
diff --git a/coregrind/m_syswrap/priv_syswrap-darwin.h b/coregrind/m_syswrap/priv_syswrap-darwin.h
index f811f29..41e9e17 100644
--- a/coregrind/m_syswrap/priv_syswrap-darwin.h
+++ b/coregrind/m_syswrap/priv_syswrap-darwin.h
@@ -559,6 +559,16 @@
 DECL_TEMPLATE(darwin, mach_msg_thread);
 
 // Mach traps
+#if DARWIN_VERS == DARWIN_10_8
+DECL_TEMPLATE(darwin, mach__10);
+DECL_TEMPLATE(darwin, mach__12);
+DECL_TEMPLATE(darwin, mach__14);
+DECL_TEMPLATE(darwin, mach__16);
+DECL_TEMPLATE(darwin, mach__18);
+DECL_TEMPLATE(darwin, mach__19);
+DECL_TEMPLATE(darwin, mach__20);
+DECL_TEMPLATE(darwin, mach__21);
+#endif /* DARWIN_VERS == DARWIN_10_8 */
 DECL_TEMPLATE(darwin, mach_msg_unhandled);
 DECL_TEMPLATE(darwin, mach_msg);
 DECL_TEMPLATE(darwin, mach_reply_port);
diff --git a/coregrind/m_syswrap/syswrap-amd64-darwin.c b/coregrind/m_syswrap/syswrap-amd64-darwin.c
index b71b6d6..ef4cacd 100644
--- a/coregrind/m_syswrap/syswrap-amd64-darwin.c
+++ b/coregrind/m_syswrap/syswrap-amd64-darwin.c
@@ -448,7 +448,7 @@
         idea why. */
 #      if DARWIN_VERS <= DARWIN_10_6
        UWord magic_delta = 0;
-#      elif DARWIN_VERS == DARWIN_10_7
+#      elif DARWIN_VERS >= DARWIN_10_7
        UWord magic_delta = 0x60;
 #      endif
 
diff --git a/coregrind/m_syswrap/syswrap-darwin.c b/coregrind/m_syswrap/syswrap-darwin.c
index dbafe47..fb4cb5f 100644
--- a/coregrind/m_syswrap/syswrap-darwin.c
+++ b/coregrind/m_syswrap/syswrap-darwin.c
@@ -1477,9 +1477,12 @@
 static const char *workqop_name(int op)
 {
    switch (op) {
-   case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
-   case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
-   case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
+   case VKI_WQOPS_QUEUE_ADD:        return "QUEUE_ADD";
+   case VKI_WQOPS_QUEUE_REMOVE:     return "QUEUE_REMOVE";
+   case VKI_WQOPS_THREAD_RETURN:    return "THREAD_RETURN";
+   case VKI_WQOPS_THREAD_SETCONC:   return "THREAD_SETCONC";
+   case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
+   case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
    default: return "?";
    }
 }
@@ -1498,6 +1501,8 @@
       // GrP fixme need anything here?
       // GrP fixme may block?
       break;
+   case VKI_WQOPS_QUEUE_NEWSPISUPP:
+      break; // JRS don't think we need to do anything here
 
    case VKI_WQOPS_THREAD_RETURN: {
       // The interesting case. The kernel will do one of two things:
@@ -3521,6 +3526,7 @@
 PRE(mmap)
 {
    // SysRes r;
+   if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
 
 #if VG_WORDSIZE == 4
    PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
@@ -4986,6 +4992,8 @@
       PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)", 
             name_for_port(MACH_REMOTE));
       break;
+#if DARWIN_VERS != DARWIN_10_8
+   /* These disappeared in 10.8 */
    case TASK_WIRED_LEDGER_PORT:
       PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)", 
             name_for_port(MACH_REMOTE));
@@ -4994,6 +5002,7 @@
       PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)", 
             name_for_port(MACH_REMOTE));
       break;
+#endif
    default:
       PRINT("task_get_special_port(%s, %d)", 
             name_for_port(MACH_REMOTE), req->which_port);
@@ -5032,12 +5041,15 @@
    case TASK_HOST_PORT:
       assign_port_name(reply->special_port.name, "host");
       break;
+#if DARWIN_VERS != DARWIN_10_8
+   /* These disappeared in 10.8 */
    case TASK_WIRED_LEDGER_PORT:
       assign_port_name(reply->special_port.name, "wired-ledger");
       break;
    case TASK_PAGED_LEDGER_PORT:
       assign_port_name(reply->special_port.name, "paged-ledger");
       break;
+#endif
    default:
       assign_port_name(reply->special_port.name, "special-%p");
       break;
@@ -6503,7 +6515,13 @@
    if (ARG4) semaphore_signal((semaphore_t)ARG4);
    if (ARG1  &&  ARG2) {
        ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
+#      if DARWIN_VERS == DARWIN_10_8
+       /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
+          the mig output.  Work around it for the time being. */
+       VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
+#      else
        vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
+#      endif
    }
 
    // Tell V to terminate the thread.
@@ -7811,16 +7829,74 @@
 
 
 /* ---------------------------------------------------------------------
+   Added for OSX 10.8 (Mountain Lion)
+   ------------------------------------------------------------------ */
+
+#if DARWIN_VERS == DARWIN_10_8
+
+PRE(mach__10)
+{
+   PRINT("mach__10(ARGUMENTS_UNKNOWN)");
+}
+POST(mach__10)
+{
+   ML_(sync_mappings)("after", "mach__10", 0);
+}
+
+PRE(mach__12)
+{
+   PRINT("mach__12(ARGUMENTS_UNKNOWN)");
+}
+POST(mach__12)
+{
+   ML_(sync_mappings)("after", "mach__12", 0);
+}
+
+PRE(mach__14)
+{
+   PRINT("mach__14(ARGUMENTS_UNKNOWN)");
+}
+
+PRE(mach__16)
+{
+   PRINT("mach__16(ARGUMENTS_UNKNOWN)");
+}
+
+PRE(mach__18)
+{
+   PRINT("mach__18(ARGUMENTS_UNKNOWN)");
+}
+
+PRE(mach__19)
+{
+   PRINT("mach__19(ARGUMENTS_UNKNOWN)");
+}
+
+PRE(mach__20)
+{
+   PRINT("mach__20(ARGUMENTS_UNKNOWN)");
+}
+
+PRE(mach__21)
+{
+   PRINT("mach__21(ARGUMENTS_UNKNOWN)");
+}
+
+#endif /* DARWIN_VERS == DARWIN_10_8 */
+
+
+/* ---------------------------------------------------------------------
    syscall tables
    ------------------------------------------------------------------ */
 
 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
 #define MACX_(sysno, name)    WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name) 
 #define MACXY(sysno, name)    WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
-#define _____(sysno) GENX_(sysno, sys_ni_syscall)
+#define _____(sysno) GENX_(sysno, sys_ni_syscall)  /* UNIX style only */
 
 /*
-     _____ : unsupported by the kernel (sys_ni_syscall)
+     _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
+             unfortunately misused for Mach too, causing assertion failures
   // _____ : unimplemented in valgrind
      GEN   : handlers are in syswrap-generic.c
      MAC   : handlers are in this file
@@ -8315,18 +8391,51 @@
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)), 
-   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)), 
+
+#  if DARWIN_VERS == DARWIN_10_8
+   MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10), mach__10), 
+#  else
+   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10), 
+#  endif
+
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)), 
+
+#  if DARWIN_VERS == DARWIN_10_8
+   MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), mach__12), 
+#  else
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)), 
+#  endif
+
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)), 
+
+#  if DARWIN_VERS == DARWIN_10_8
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), mach__14), 
+#  else
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)), 
+#  endif
+
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)), 
+
+#  if DARWIN_VERS == DARWIN_10_8
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), mach__16), 
+#  else
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)), 
+#  endif
+
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)), 
+
+#  if DARWIN_VERS == DARWIN_10_8
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), mach__18), 
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), mach__19), 
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), mach__20),
+   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), mach__21), 
+#  else
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)), 
-   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),   // -20
+   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)), 
+#  endif
+
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)), 
    _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)), 
diff --git a/coregrind/m_syswrap/syswrap-x86-darwin.c b/coregrind/m_syswrap/syswrap-x86-darwin.c
index 6096d4a..ff2b7d4 100644
--- a/coregrind/m_syswrap/syswrap-x86-darwin.c
+++ b/coregrind/m_syswrap/syswrap-x86-darwin.c
@@ -409,7 +409,7 @@
          idea why. */
 #     if DARWIN_VERS <= DARWIN_10_6
       UWord magic_delta = 0;
-#     elif DARWIN_VERS == DARWIN_10_7
+#     elif DARWIN_VERS >= DARWIN_10_7
       UWord magic_delta = 0x48;
 #     endif
 
diff --git a/coregrind/m_ume/macho.c b/coregrind/m_ume/macho.c
index be37ca8..142a3f9 100644
--- a/coregrind/m_ume/macho.c
+++ b/coregrind/m_ume/macho.c
@@ -76,12 +76,21 @@
 static void check_mmap(SysRes res, Addr base, SizeT len, HChar* who)
 {
    if (sr_isError(res)) {
-      VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME (%s).\n", 
+      VG_(printf)("valgrind: mmap-FIXED(0x%llx, %lld) failed in UME (%s).\n", 
                   (ULong)base, (Long)len, who);
       VG_(exit)(1);
    }
 }
 
+static void check_mmap_float(SysRes res, SizeT len, HChar* who)
+{
+   if (sr_isError(res)) {
+      VG_(printf)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s).\n", 
+                  (Long)len, who);
+      VG_(exit)(1);
+   }
+}
+
 
 static int 
 load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
@@ -370,6 +379,45 @@
 }
 
 
+/* Allocates a stack mapping at a V-chosen address.  Pertains to
+   LC_MAIN commands, which seem to have appeared in OSX 10.8.
+
+   This is a really nasty hack -- allocates 64M+stack size, then
+   deallocates the 64M, to guarantee that the stack is at least 64M
+   above zero. */
+static int
+handle_lcmain ( vki_uint8_t **out_stack_start,
+                vki_uint8_t **out_stack_end,
+                vki_size_t requested_size )
+{
+   if (requested_size == 0) {
+      requested_size = default_stack_size();
+   }
+   requested_size = VG_PGROUNDUP(requested_size);
+
+   const vki_size_t HACK = 64 * 1024 * 1024;
+   requested_size += HACK;
+
+   SysRes res = VG_(am_mmap_anon_float_client)(requested_size,
+                   VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
+   check_mmap_float(res, requested_size, "handle_lcmain");
+   vg_assert(!sr_isError(res));
+   *out_stack_start = (vki_uint8_t*)sr_Res(res);
+   *out_stack_end   = *out_stack_start + requested_size;
+
+   Bool need_discard = False;
+   res = VG_(am_munmap_client)(&need_discard, (Addr)*out_stack_start, HACK);
+   if (sr_isError(res)) return -1;
+   vg_assert(!need_discard); // True == wtf?
+
+   *out_stack_start += HACK;
+
+   return 0;
+}
+
+
+
+
 /* 
    Processes an LC_LOAD_DYLINKER command. 
    Returns 0 on success, -1 on any error.
@@ -432,6 +480,7 @@
                vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
                vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
 {
+   VG_(debugLog)(1, "ume", "load_thin_file: begin:   %s\n", filename);
    struct MACH_HEADER mh;
    vki_uint8_t *headers;
    vki_uint8_t *headers_end;
@@ -506,6 +555,23 @@
       }
 
       switch (lc->cmd) {
+
+#if   DARWIN_VERS == DARWIN_10_8
+      case LC_MAIN: { /* New in 10.8 */
+         struct entry_point_command* epcmd
+            = (struct entry_point_command*)lc;
+         if (stack_start || stack_end) {
+            print("bad executable (multiple indications of stack)");
+            return -1;
+         }
+         err = handle_lcmain ( &stack_start, &stack_end, epcmd->stacksize );
+         if (err) return -1;
+         VG_(debugLog)(2, "ume", "lc_main: created stack %p-%p\n",
+	               stack_start, stack_end);
+         break;
+      }
+#     endif
+
       case LC_SEGMENT_CMD:
          if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
             print("bad executable (invalid load commands)\n");
@@ -582,7 +648,7 @@
       // a text segment
       // an entry point (static or linker)
       if (!stack_end || !stack_start) {
-         print("bad executable (no stack)\n");
+         VG_(printf)("bad executable %s (no stack)\n", filename);
          return -1;
       }
       if (!text) {
@@ -609,6 +675,7 @@
    if (out_entry) *out_entry = entry;
    if (out_linker_entry) *out_linker_entry = linker_entry;
    
+   VG_(debugLog)(1, "ume", "load_thin_file: success: %s\n", filename);
    return 0;
 }
 
diff --git a/darwin12.supp b/darwin12.supp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/darwin12.supp
diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
index 9311fd0..2df1fc3 100644
--- a/include/pub_tool_redir.h
+++ b/include/pub_tool_redir.h
@@ -246,7 +246,7 @@
 #elif defined(VGO_darwin) && (DARWIN_VERS <= DARWIN_10_6)
 #  define  VG_Z_LIBC_SONAME  libSystemZdZaZddylib    // libSystem.*.dylib
 
-#elif defined(VGO_darwin) && (DARWIN_VERS == DARWIN_10_7)
+#elif defined(VGO_darwin) && (DARWIN_VERS >= DARWIN_10_7)
 #  define  VG_Z_LIBC_SONAME  libsystemZucZaZddylib   // libsystem_c*.dylib
 
 #else
diff --git a/include/vki/vki-darwin.h b/include/vki/vki-darwin.h
index dfc883d..70de0d9 100644
--- a/include/vki/vki-darwin.h
+++ b/include/vki/vki-darwin.h
@@ -829,9 +829,12 @@
 
 // Libc/pthreads/pthread.c
 
-#define VKI_WQOPS_QUEUE_ADD      1
-#define VKI_WQOPS_QUEUE_REMOVE   2
-#define VKI_WQOPS_THREAD_RETURN  4
+#define VKI_WQOPS_QUEUE_ADD          1
+#define VKI_WQOPS_QUEUE_REMOVE       2
+#define VKI_WQOPS_THREAD_RETURN      4
+#define VKI_WQOPS_THREAD_SETCONC     8
+#define VKI_WQOPS_QUEUE_NEWSPISUPP  16  /* check for newer SPI support */
+#define VKI_WQOPS_QUEUE_REQTHREADS  32  /* request number of threads of a prio */
 
 
 #include <sys/ttycom.h>