Index: vg_syscalls.c
===================================================================
RCS file: /cvsroot/valgrind/valgrind/coregrind/vg_syscalls.c,v
retrieving revision 1.50
diff -u -r1.50 vg_syscalls.c
--- coregrind/vg_syscalls.c	19 Oct 2003 16:46:06 -0000	1.50
+++ coregrind/vg_syscalls.c	22 Oct 2003 20:51:28 -0000
@@ -1223,9 +1223,35 @@
       char *const envp[]); */
    MAYBE_PRINTF("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n", 
 		arg1, arg1, arg2, arg3);
-   /* Resistance is futile.  Nuke all other threads.  POSIX
-      mandates this. */
-   VG_(nuke_all_threads_except)( tid );
+
+   /* Erk.  If the exec fails, then the following will have made a
+      mess of things which makes it hard for us to continue.  The
+      right thing to do is piece everything together again in
+      POST(execve), but that's hard work.  Instead, we make an effort
+      to check that the execve will work before actually calling
+      exec. */
+   {
+      struct vki_stat st;
+      Int ret = VG_(stat)((Char *)arg1, &st);
+
+      if (ret < 0) {
+	 res = ret;
+	 return;
+      }
+      /* just look for any X bit set
+	 XXX do proper permissions check?
+       */
+      if ((st.st_mode & 0111) == 0) {
+	 res = -VKI_EACCES;
+	 return;
+      }
+   }
+
+   /* Resistance is futile.  Nuke all other threads.  POSIX mandates
+      this. (Really, nuke them all, since the new process will make
+      its own new thread.) */
+   VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
+
    /* Make any binding for LD_PRELOAD disappear, so that child
       processes don't get traced into. */
    if (!VG_(clo_trace_children)) {
@@ -1242,15 +1268,15 @@
       VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
 	 ld_preload_str, ld_library_path_str );
    }
-}
 
-POST(execve)
-{
-   /* Should we still be alive here?  Don't think so. */
-   /* Actually, above comment is wrong.  execve can fail, just
-      like any other syscall -- typically the file to exec does
-      not exist.  Hence: */
-   vg_assert(VG_(is_kerror)(res));
+   res = VG_(do_syscall)(__NR_execve, arg1, arg2, arg3);
+
+   /* If we got here, then the execve failed.  We've already made too much of a mess
+      of ourselves to continue, so we have to abort. */
+   VG_(message)(Vg_UserMsg, "execve(%p \"%s\", %p, %p) failed, errno %d",
+		arg1, arg1, arg2, arg3, -res);
+   VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
+		   "Add more stringent tests in PRE(execve), or work out how to recover.");   
 }
 
 PRE(access)
@@ -4099,6 +4125,8 @@
 
    SYSB_(modify_ldt,		False),
 
+   SYSB_(execve,		False),
+
 #if SIGNAL_SIMULATION
    SYSBA(sigaltstack,		False),
    SYSBA(rt_sigaction,		False),
@@ -4184,7 +4212,6 @@
    SYSB_(ioperm,		False),
    SYSBA(capget,		False),
    SYSB_(capset,		False),
-   SYSBA(execve,		False),
    SYSB_(access,		False),
    SYSBA(brk,			False),
    SYSB_(chdir,			False),
Index: vg_kerneliface.h
===================================================================
RCS file: /cvsroot/valgrind/valgrind/include/vg_kerneliface.h,v
retrieving revision 1.3
diff -u -r1.3 vg_kerneliface.h
--- include/vg_kerneliface.h	14 Oct 2003 22:13:28 -0000	1.3
+++ include/vg_kerneliface.h	22 Oct 2003 20:52:15 -0000
@@ -358,6 +358,7 @@
 #define VKI_ENOMEM          12      /* Out of memory */
 #define VKI_EWOULDBLOCK     VKI_EAGAIN  /* Operation would block */
 #define VKI_EAGAIN          11      /* Try again */
+#define	VKI_EACCES	    13      /* Permission denied */
 #define	VKI_EFAULT          14      /* Bad address */
 #define VKI_EEXIST	    17	    /* File exists */
 #define VKI_EINVAL          22      /* Invalid argument */
Index: coregrind/vg_mylibc.c
===================================================================
RCS file: /cvsroot/valgrind/valgrind/coregrind/vg_mylibc.c,v
retrieving revision 1.54
diff -u -r1.54 vg_mylibc.c
--- coregrind/vg_mylibc.c	15 Oct 2003 14:00:35 -0000	1.54
+++ coregrind/vg_mylibc.c	22 Oct 2003 20:54:17 -0000
@@ -1209,7 +1209,7 @@
 {
    Int res;
    res = VG_(do_syscall)(__NR_stat, (UInt)file_name, (UInt)buf);
-   return VG_(is_kerror)(res) ? (-1) : 0;
+   return res;
 }
 
 Int VG_(fstat) ( Int fd, struct vki_stat* buf )
