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@
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})])
;;
*)
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`
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)])
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 */)
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;
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",
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);
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
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 "?";
}
}
// 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:
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 )",
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));
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);
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;
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.
}
+/* ---------------------------------------------------------------------
+ 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
_____(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)),
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
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,
}
+/* 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.
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;
}
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");
// 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) {
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;
}
#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
// 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>