diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index d5f6fe0..e7a8bfb 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -366,6 +366,14 @@ linux_add_process (int pid, int attached)
   return proc;
 }
 
+/* Find the main executable for the process with PID.  */
+
+static
+char *linux_pid_to_exec_file (struct target_ops *self, int pid)
+{
+  return linux_proc_pid_to_exec_file (pid);
+}
+
 /* Handle a GNU/Linux extended wait response.  If we see a clone
    event, we need to add the new lwp EVENT_CHILD to our list (and not
    report the trap to higher layers).  This function returns non-zero
@@ -562,6 +570,21 @@ handle_extended_wait (struct lwp_info *event_child, int *wstatp)
       ptrace (PTRACE_CONT, lwpid, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
       return ret;
     }
+  else if (event == PTRACE_EVENT_EXEC)
+    {
+      if (debug_threads)
+	{
+	  debug_printf ("HEW: Got exec event from LWP %ld\n",
+			lwpid_of (event_thr));
+	}
+
+      event_child->waitstatus.kind = TARGET_WAITKIND_EXECD;
+      event_child->waitstatus.value.execd_pathname
+	= xstrdup (linux_pid_to_exec_file (NULL, lwpid_of (event_thr)));
+
+      /* Report the event.  */
+      return 0;
+    }
 
   internal_error (__FILE__, __LINE__, _("unknown ptrace event %d"), event);
 }
@@ -2047,6 +2070,56 @@ linux_low_filter_event (ptid_t filter_ptid, int lwpid, int *wstatp)
 
   child = find_lwp_pid (pid_to_ptid (lwpid));
 
+  /* Check for stop events reported by a process we didn't already
+     know about - anything not already in our LWP list.
+
+     If we're expecting to receive stopped processes after
+     fork, vfork, and clone events, then we'll just add the
+     new one to our list and go back to waiting for the event
+     to be reported - the stopped process might be returned
+     from waitpid before or after the event is.
+
+     But note the case of a non-leader thread exec'ing after the
+     leader having exited, and gone from our lists.  On an exec,
+     the Linux kernel destroys all other threads (except the execing
+     one) in the thread group, and resets the execing thread's tid
+     to the tgid.  No exit notification is sent for the execing
+     thread -- from the ptracer's perspective, it appears as though
+     the execing thread just vanishes.  When they are available, we
+     use exit events (PTRACE_EVENT_EXIT) to detect thread exit
+     reliably.  As soon as all other threads (if any) are reaped or
+     have reported their PTRACE_EVENT_EXIT events, the execing
+     thread changes it's tid to the tgid, and the previous (zombie)
+     leader vanishes, giving place to the "new" leader.  The lwp
+     entry for the previous leader is deleted when we handle its
+     exit event, and we re-add the new one here.  */
+
+  if (WIFSTOPPED (wstat) && (child == NULL) && (WSTOPSIG (wstat) == SIGTRAP)
+      && (linux_ptrace_get_extended_event (wstat) == PTRACE_EVENT_EXEC))
+    {
+      ptid_t child_ptid;
+
+      /* A multi-thread exec after we had seen the leader exiting.  */
+      if (debug_threads)
+	debug_printf ("LLW: Re-adding thread group leader LWP %d.\n", lwpid);
+
+      child_ptid = ptid_build (lwpid, lwpid, 0);
+      child = add_lwp (child_ptid);
+      child->stopped = 1;
+      current_thread = child->thread;
+
+      if (non_stop && stopping_threads == NOT_STOPPING_THREADS)
+	{
+	  /* Make sure we delete the lwp entry for the exec'ing thread,
+	     which will have vanished.  We do this by sending a signal
+	     to all the other threads in the lwp list, deleting any
+	     that are not found.  Note that in all-stop mode this will
+	     happen before reporting the event.  */
+	  stop_all_lwps (0, child);
+	  unstop_all_lwps (0, child);
+	}
+    }
+
   /* If we didn't find a process, one of two things presumably happened:
      - A process we started and then detached from has exited.  Ignore it.
      - A process we are controlling has forked and the new child's stop
@@ -2383,8 +2456,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
 	 - When a non-leader thread execs, that thread just vanishes
 	   without reporting an exit (so we'd hang if we waited for it
 	   explicitly in that case).  The exec event is reported to
-	   the TGID pid (although we don't currently enable exec
-	   events).  */
+	   the TGID pid.  */
       errno = 0;
       ret = my_waitpid (-1, wstatp, options | WNOHANG);
 
@@ -2786,7 +2858,8 @@ extended_event_reported (const struct target_waitstatus *waitstatus)
 
   return (waitstatus->kind == TARGET_WAITKIND_FORKED
 	  || waitstatus->kind == TARGET_WAITKIND_VFORKED
-	  || waitstatus->kind == TARGET_WAITKIND_VFORK_DONE);
+	  || waitstatus->kind == TARGET_WAITKIND_VFORK_DONE
+	  || waitstatus->kind == TARGET_WAITKIND_EXECD);
 }
 
 /* Wait for process, returns status.  */
@@ -3413,6 +3486,7 @@ static void
 send_sigstop (struct lwp_info *lwp)
 {
   int pid;
+  int ret;
 
   pid = lwpid_of (get_lwp_thread (lwp));
 
@@ -3430,7 +3504,21 @@ send_sigstop (struct lwp_info *lwp)
     debug_printf ("Sending sigstop to lwp %d\n", pid);
 
   lwp->stop_expected = 1;
-  kill_lwp (pid, SIGSTOP);
+  errno = 0;
+  ret = kill_lwp (pid, SIGSTOP);
+  if (ret == -1 && errno == ESRCH)
+    {
+      /* If the kill fails with "No such process", on GNU/Linux we know
+	 that the LWP has vanished - it is not a zombie, it is gone.
+	 This is due to a thread other than the thread group leader
+	 calling exec.  See comments in linux_low_filter_event regarding
+	 PTRACE_EVENT_EXEC.  */
+      delete_lwp (lwp);
+      set_desired_thread (0);
+
+      if (debug_threads)
+	debug_printf ("send_sigstop: lwp %d has vanished\n", pid);
+    }
 }
 
 static int
@@ -6530,6 +6618,7 @@ initialize_low (void)
   linux_ptrace_set_requested_options (PTRACE_O_TRACEFORK
 				      | PTRACE_O_TRACEVFORK
 				      | PTRACE_O_TRACEVFORKDONE
-				      | PTRACE_O_TRACEEXIT);
+				      | PTRACE_O_TRACEEXIT
+				      | PTRACE_O_TRACEEXEC);
   linux_ptrace_check_options ();
 }
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index b4a523a..35784b5 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -1107,6 +1107,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
     case TARGET_WAITKIND_STOPPED:
     case TARGET_WAITKIND_FORKED:
     case TARGET_WAITKIND_VFORKED:
+    case TARGET_WAITKIND_EXECD:
       {
 	struct thread_info *saved_thread;
 	const char **regp;
@@ -1123,6 +1124,24 @@ prepare_resume_reply (char *buf, ptid_t ptid,
 		      ptid_get_pid (status->value.related_pid),
 		      ptid_get_lwp (status->value.related_pid));
 	  }
+	else if ((status->kind == TARGET_WAITKIND_EXECD) && multi_process)
+	  {
+	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
+	    const char *event = "exec";
+	    char hexified_pathname[PATH_MAX];
+
+	    sprintf (buf, "T%02x%s:", signal, event);
+	    buf += strlen (buf);
+
+	    /* Encode pathname to hexified format.  */
+	    bin2hex ((const gdb_byte *) status->value.execd_pathname,
+		      hexified_pathname, strlen(status->value.execd_pathname));
+
+	    sprintf (buf, "%s;", hexified_pathname);
+	    xfree (status->value.execd_pathname);
+	    status->value.execd_pathname = NULL;
+	    buf += strlen (buf);
+	  }
 	else
 	  sprintf (buf, "T%02x", status->value.sig);
 
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index f0487e9..e81a560 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -686,7 +686,6 @@ linux_nat_pass_signals (struct target_ops *self,
 /* Prototypes for local functions.  */
 static int stop_wait_callback (struct lwp_info *lp, void *data);
 static int linux_thread_alive (ptid_t ptid);
-static char *linux_child_pid_to_exec_file (struct target_ops *self, int pid);
 
 
 
@@ -1793,6 +1792,14 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping)
   return 1;
 }
 
+/* Find the main executable for the process with PID.  */
+
+static
+char *linux_pid_to_exec_file (struct target_ops *self, int pid)
+{
+  return linux_proc_pid_to_exec_file (pid);
+}
+
 /* Handle a GNU/Linux extended wait response.  If we see a clone
    event, we need to add the new LWP to our list (and not report the
    trap to higher layers).  This function returns non-zero if the
@@ -2015,7 +2022,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
 
       ourstatus->kind = TARGET_WAITKIND_EXECD;
       ourstatus->value.execd_pathname
-	= xstrdup (linux_child_pid_to_exec_file (NULL, pid));
+	= xstrdup (linux_pid_to_exec_file (NULL, pid));
 
       return 0;
     }
@@ -3862,23 +3869,6 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
   return result;
 }
 
-/* Accepts an integer PID; Returns a string representing a file that
-   can be opened to get the symbols for the child process.  */
-
-static char *
-linux_child_pid_to_exec_file (struct target_ops *self, int pid)
-{
-  static char buf[PATH_MAX];
-  char name[PATH_MAX];
-
-  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
-  memset (buf, 0, PATH_MAX);
-  if (readlink (name, buf, PATH_MAX - 1) <= 0)
-    strcpy (buf, name);
-
-  return buf;
-}
-
 /* Implement the to_xfer_partial interface for memory reads using the /proc
    filesystem.  Because we can use a single read() call for /proc, this
    can be much more efficient than banging away at PTRACE_PEEKTEXT,
@@ -4271,7 +4261,7 @@ linux_target_install_ops (struct target_ops *t)
   t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
   t->to_remove_exec_catchpoint = linux_child_remove_exec_catchpoint;
   t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint;
-  t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
+  t->to_pid_to_exec_file = linux_pid_to_exec_file;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
   t->to_post_attach = linux_child_post_attach;
   t->to_follow_fork = linux_child_follow_fork;
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index 30797da..bdbe10b 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -113,3 +113,20 @@ linux_proc_pid_is_zombie (pid_t pid)
 {
   return linux_proc_pid_has_state (pid, "Z (zombie)");
 }
+
+/* Accepts an integer PID; Returns a string representing a file that
+   can be opened to get the symbols for the child process.  */
+
+char *
+linux_proc_pid_to_exec_file (int pid)
+{
+  static char buf[PATH_MAX];
+  char name[PATH_MAX];
+
+  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
+  memset (buf, 0, PATH_MAX);
+  if (readlink (name, buf, PATH_MAX - 1) <= 0)
+    strcpy (buf, name);
+
+  return buf;
+}
diff --git a/gdb/nat/linux-procfs.h b/gdb/nat/linux-procfs.h
index d13fff7..e6ee9a8 100644
--- a/gdb/nat/linux-procfs.h
+++ b/gdb/nat/linux-procfs.h
@@ -40,4 +40,8 @@ extern int linux_proc_pid_is_stopped (pid_t pid);
 
 extern int linux_proc_pid_is_zombie (pid_t pid);
 
+/* Return pathname of exec file for process with PID.  */
+
+extern char *linux_proc_pid_to_exec_file (int pid);
+
 #endif /* COMMON_LINUX_PROCFS_H */
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index e8fd58c..741b4f1 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -488,6 +488,7 @@ linux_test_for_traceexit (int child_pid)
   if (ret != 0)
     return;
 
+
   /* We don't know for sure that the feature is available; old
      versions of PTRACE_SETOPTIONS ignored unknown options.  So
      see if the process exit will generate a PTRACE_EVENT_EXIT.
@@ -508,8 +509,12 @@ linux_test_for_traceexit (int child_pid)
       if (ret == child_pid && WIFSTOPPED (status)
 	  && linux_ptrace_get_extended_event (status) == PTRACE_EVENT_EXIT)
 	{
-	  /* PTRACE_O_TRACEEXIT is supported.  */
-	  available_ptrace_options |= PTRACE_O_TRACEEXIT;
+	  /* PTRACE_O_TRACEEXIT is supported.
+
+	     We use exit events to implement support for exec events.
+	     Because exit events are supported, we can assume exec events
+	     are also supported, so we add them as well.  */
+	  available_ptrace_options |= PTRACE_O_TRACEEXIT | PTRACE_O_TRACEEXEC;
 	}
     }
 }
diff --git a/gdb/remote.c b/gdb/remote.c
index de715f5..7409860 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5614,11 +5614,13 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event)
 	     pnum and set p1 to point to the character following it.
 	     Otherwise p1 points to p.  */
 
-	  /* If this packet is an awatch packet, don't parse the 'a'
-	     as a register number.  */
+	  /* If this packet has a stop reason string that starts
+	     with a character that could be a hex digit, don't parse
+	     it as a register number.  */
 
 	  if (strncmp (p, "awatch", strlen("awatch")) != 0
 	      && strncmp (p, "core", strlen ("core") != 0)
+	      && strncmp (p, "exec", strlen ("exec") != 0)
 	      && strncmp (p, "fork", strlen ("fork") != 0))
 	    {
 	      /* Read the ``P'' register number.  */
@@ -5691,6 +5693,25 @@ Packet: '%s'\n"),
 		  event->ws.kind = TARGET_WAITKIND_VFORK_DONE;
 		  p = p_temp;
 		}
+	      else if (strncmp (p, "exec", p1 - p) == 0)
+		{
+		  ULONGEST pid;
+		  char pathname[PATH_MAX];
+
+		  p = unpack_varlen_hex (++p1, &pid);
+
+		  /* Save the pathname for event reporting and for
+		     the next run command.  */
+		  hex2bin (p1, (gdb_byte *) pathname, (p - p1)/2);
+		  /* Add the null terminator.  */
+		  pathname[(p - p1)/2] = '\0';
+		  /* This is freed during event handling.  */
+		  event->ws.value.execd_pathname = xstrdup (pathname);
+		  event->ws.kind = TARGET_WAITKIND_EXECD;
+		  /* Save the pathname for the next run command.  */
+		  xfree (remote_exec_file);
+		  remote_exec_file = xstrdup (pathname);
+		}
 	      else
 		{
 		  /* Silently skip unknown optional info.  */
