diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 01f11b7..a13631a 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5133,6 +5133,30 @@ linux_supports_multi_process (void)
   return 1;
 }

+/* Check if fork events are supported.  */
+
+static int
+linux_supports_fork_events (void)
+{
+  return linux_supports_tracefork ();
+}
+
+/* Check if vfork events are supported.  */
+
+static int
+linux_supports_vfork_events (void)
+{
+  return linux_supports_tracefork ();
+}
+
+/* Check if exec events are supported.  */
+
+static int
+linux_supports_exec_events (void)
+{
+  return linux_supports_tracefork ();
+}
+
 static int
 linux_supports_disable_randomization (void)
 {
@@ -6044,6 +6068,9 @@ static struct target_ops linux_target_ops = {
   linux_async,
   linux_start_non_stop,
   linux_supports_multi_process,
+  linux_supports_fork_events,
+  linux_supports_vfork_events,
+  linux_supports_exec_events,
 #ifdef USE_THREAD_DB
   thread_db_handle_monitor_command,
 #else
@@ -6119,4 +6146,14 @@ initialize_low (void)
   sigaction (SIGCHLD, &sigchld_action, NULL);

   initialize_low_arch ();
+
+#if PTRACE_EVENT_SUPPORT
+  /* Always try to enable ptrace event extensions.  Leave
+     PTRACE_O_TRACESYSGOOD out until it is supported.  */
+  linux_ptrace_set_additional_flags (PTRACE_O_TRACEVFORKDONE
+				     | PTRACE_O_TRACEVFORK
+				     | PTRACE_O_TRACEFORK
+				     | PTRACE_O_TRACEEXEC);
+#endif
+  linux_test_for_event_reporting ();
 }
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 6178e03..dc4ffb2 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -753,6 +753,9 @@ static struct target_ops lynx_target_ops = {
   NULL,  /* async */
   NULL,  /* start_non_stop */
   NULL,  /* supports_multi_process */
+  NULL,  /* supports_fork_events */
+  NULL,  /* supports_vfork_events */
+  NULL,  /* supports_exec_events */
   NULL,  /* handle_monitor_command */
 };

diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 173a22e..71c954f 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -57,6 +57,9 @@ static int exit_requested;
 int run_once;

 int multi_process;
+int report_fork_events;
+int report_vfork_events;
+int report_exec_events;
 int non_stop;

 /* Whether we should attempt to disable the operating system's address
@@ -1841,6 +1844,24 @@ handle_query (char *own_buf, int packet_len, int
*new_packet_len_p)
 		  /* GDB supports relocate instruction requests.  */
 		  gdb_supports_qRelocInsn = 1;
 		}
+	      if (strcmp (p, "fork-events+") == 0)
+		{
+		  /* GDB supports and wants fork events if possible.  */
+		  if (target_supports_fork_events ())
+		    report_fork_events = 1;
+		}
+	      if (strcmp (p, "vfork-events+") == 0)
+		{
+		  /* GDB supports and wants vfork events if possible.  */
+		  if (target_supports_vfork_events ())
+		    report_vfork_events = 1;
+		}
+	      if (strcmp (p, "exec-events+") == 0)
+		{
+		  /* GDB supports and wants fork events if possible.  */
+		  if (target_supports_exec_events ())
+		    report_exec_events = 1;
+		}
 	      else
 		target_process_qsupported (p);

@@ -1891,6 +1912,15 @@ handle_query (char *own_buf, int packet_len, int
*new_packet_len_p)
       if (target_supports_multi_process ())
 	strcat (own_buf, ";multiprocess+");

+      if (target_supports_fork_events ())
+	strcat (own_buf, ";fork-events+");
+
+      if (target_supports_vfork_events ())
+	strcat (own_buf, ";vfork-events+");
+
+      if (target_supports_exec_events ())
+	strcat (own_buf, ";exec-events+");
+
       if (target_supports_non_stop ())
 	strcat (own_buf, ";QNonStop+");

@@ -3242,6 +3272,9 @@ captured_main (int argc, char *argv[])

       noack_mode = 0;
       multi_process = 0;
+      report_fork_events = 0;
+      report_vfork_events = 0;
+      report_exec_events = 0;
       /* Be sure we're out of tfind mode.  */
       current_traceframe = -1;
       cont_thread = null_ptid;
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 5e29b7f..a427840 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -262,6 +262,15 @@ struct target_ops
   /* Returns true if the target supports multi-process debugging.  */
   int (*supports_multi_process) (void);

+  /* Returns true if fork events are supported.  */
+  int (*supports_fork_events) (void);
+
+  /* Returns true if vfork events are supported.  */
+  int (*supports_vfork_events) (void);
+
+  /* Returns true if exec events are supported.  */
+  int (*supports_exec_events) (void);
+
   /* If not NULL, target-specific routine to process monitor command.
      Returns 1 if handled, or 0 to perform default processing.  */
   int (*handle_monitor_command) (char *);
@@ -390,6 +399,18 @@ void set_target_ops (struct target_ops *);

 int kill_inferior (int);

+#define target_supports_fork_events() \
+  (the_target->supports_fork_events ? \
+   (*the_target->supports_fork_events) () : 0)
+
+#define target_supports_vfork_events() \
+  (the_target->supports_vfork_events ? \
+   (*the_target->supports_vfork_events) () : 0)
+
+#define target_supports_exec_events() \
+  (the_target->supports_exec_events ? \
+   (*the_target->supports_exec_events) () : 0)
+
 #define detach_inferior(pid) \
   (*the_target->detach) (pid)

diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index e714933..bf95db4 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -1823,6 +1823,9 @@ static struct target_ops win32_target_ops = {
   NULL, /* async */
   NULL, /* start_non_stop */
   NULL, /* supports_multi_process */
+  NULL, /* supports_fork_events */
+  NULL, /* supports_vfork_events */
+  NULL, /* supports_exec_events */
   NULL, /* handle_monitor_command */
   NULL, /* core_of_thread */
   NULL, /* read_loadmap */
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index 8bc3f16..2760ddd 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -310,8 +310,8 @@ static void linux_test_for_tracefork (int child_pid);

 /* Determine ptrace features available on this target.  */

-static void
-linux_check_ptrace_features (void)
+void
+linux_test_for_event_reporting (void)
 {
   int child_pid, ret, status;

@@ -430,9 +430,10 @@ linux_test_for_tracefork (int child_pid)
 	  /* We got the PID from the grandchild, which means fork
 	     tracing is supported.  */
 	  current_ptrace_options |= PTRACE_O_TRACECLONE;
-	  current_ptrace_options |= (additional_flags & (PTRACE_O_TRACEFORK
-                                                         |
PTRACE_O_TRACEVFORK
-                                                         |
PTRACE_O_TRACEEXEC));
+	  current_ptrace_options |= (additional_flags
+				     & (PTRACE_O_TRACEFORK
+					| PTRACE_O_TRACEVFORK
+					| PTRACE_O_TRACEEXEC));

 	  /* Do some cleanup and kill the grandchild.  */
 	  my_waitpid (second_pid, &second_status, 0);
@@ -457,7 +458,7 @@ linux_enable_event_reporting (pid_t pid)
   /* Check if we have initialized the ptrace features for this
      target.  If not, do it now.  */
   if (current_ptrace_options == -1)
-    linux_check_ptrace_features ();
+    linux_test_for_event_reporting ();

   /* Set the options.  */
   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
diff --git a/gdb/nat/linux-ptrace.h b/gdb/nat/linux-ptrace.h
index 31a77cd..437907e 100644
--- a/gdb/nat/linux-ptrace.h
+++ b/gdb/nat/linux-ptrace.h
@@ -85,6 +85,7 @@ struct buffer;

 extern void linux_ptrace_attach_fail_reason (pid_t pid, struct buffer
*buffer);
 extern void linux_ptrace_init_warnings (void);
+extern void linux_test_for_event_reporting (void);
 extern void linux_enable_event_reporting (pid_t pid);
 extern void linux_disable_event_reporting (pid_t pid);
 extern int linux_supports_tracefork (void);
diff --git a/gdb/remote.c b/gdb/remote.c
index 4b9b099..cb40955 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1327,6 +1327,15 @@ enum {
   /* Support for qXfer:libraries-svr4:read with a non-empty annex.  */
   PACKET_augmented_libraries_svr4_read_feature,

+  /* Support for fork events.  */
+  PACKET_fork_event_feature,
+
+  /* Support for vfork events.  */
+  PACKET_vfork_event_feature,
+
+  /* Support for exec events.  */
+  PACKET_exec_event_feature,
+
   PACKET_MAX
 };

@@ -1432,6 +1441,32 @@ remote_multi_process_p (struct remote_state *rs)
   return packet_support (PACKET_multiprocess_feature) == PACKET_ENABLE;
 }

+#if PTRACE_EVENT_SUPPORT
+/* Returns true if fork events are supported.  */
+
+static int
+remote_fork_event_p (struct remote_state *rs)
+{
+  return packet_support (PACKET_fork_event_feature) == PACKET_ENABLE;
+}
+
+/* Returns true if vfork events are supported.  */
+
+static int
+remote_vfork_event_p (struct remote_state *rs)
+{
+  return packet_support (PACKET_vfork_event_feature) == PACKET_ENABLE;
+}
+
+/* Returns true if exec events are supported.  */
+
+static int
+remote_exec_event_p (struct remote_state *rs)
+{
+  return packet_support (PACKET_exec_event_feature) == PACKET_ENABLE;
+}
+#endif
+
 /* Tokens for use by the asynchronous signal handlers for SIGINT.  */
 static struct async_signal_handler *async_sigint_remote_twice_token;
 static struct async_signal_handler *async_sigint_remote_token;
@@ -4010,7 +4045,13 @@ static const struct protocol_feature
remote_protocol_features[] = {
   { "Qbtrace:off", PACKET_DISABLE, remote_supported_packet,
PACKET_Qbtrace_off },
   { "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet,
PACKET_Qbtrace_bts },
   { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_btrace }
+    PACKET_qXfer_btrace },
+  { "fork-events", PACKET_DISABLE, remote_supported_packet,
+    PACKET_fork_event_feature },
+  { "vfork-events", PACKET_DISABLE, remote_supported_packet,
+    PACKET_vfork_event_feature },
+  { "exec-events", PACKET_DISABLE, remote_supported_packet,
+    PACKET_exec_event_feature }
