summaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorDon Breazeal <donb@codesourcery.com>2015-05-12 09:52:41 -0700
committerDon Breazeal <donb@codesourcery.com>2015-05-12 09:52:41 -0700
commit89245bc05692aaa107fa2884c032da21682edc72 (patch)
tree06b9fb3a6f8a8ff0569695b7ce0f25bb572247b2 /gdb/gdbserver
parent15eddee17fd772021fc3a331904e8f6b55b354c7 (diff)
downloadbinutils-gdb-89245bc05692aaa107fa2884c032da21682edc72.tar.gz
Identify remote fork event support
This patch implements a mechanism for GDB to determine whether fork events are supported in gdbserver. This is a preparatory patch for remote fork and exec event support. Two new RSP packets are defined to represent fork and vfork event support. These packets are used just like PACKET_multiprocess_feature to denote whether the corresponding event is supported. GDB sends fork-events+ and vfork-events+ to gdbserver to inquire about fork event support. If the response enables these packets, then GDB knows that gdbserver supports the corresponding events and will enable them. Target functions used to query for support are included along with each new packet. In order for gdbserver to know whether the events are supported at the point where the qSupported packet arrives, the code in nat/linux-ptrace.c had to be reorganized. Previously it would test for fork/exec event support, then enable the events using the pid of the inferior. When the qSupported packet arrives there may not be an inferior. So the mechanism was split into two parts: a function that checks whether the events are supported, called when gdbserver starts up, and another that enables the events when the inferior stops for the first time. Another gdbserver change was to add some global variables similar to multi_process, one per new packet. These are used to control whether the corresponding fork events are enabled. If GDB does not inquire about the event support in the qSupported packet, then gdbserver will not set these "report the event" flags. If the flags are not set, the events are ignored like they were in the past. Thus, gdbserver will never send fork event notification to an older GDB that doesn't recognize fork events. Tested on Ubuntu x64, native/remote/extended-remote, and as part of subsequent patches in the series. gdb/gdbserver/ChangeLog: * linux-low.c (linux_supports_fork_events): New function. (linux_supports_vfork_events): New function. (linux_target_ops): Initialize new structure members. (initialize_low): Call linux_check_ptrace_features. * lynx-low.c (lynx_target_ops): Initialize new structure members. * server.c (report_fork_events, report_vfork_events): New global flags. (handle_query): Add new features to qSupported packet and response. (captured_main): Initialize new global variables. * target.h (struct target_ops) <supports_fork_events>: New member. <supports_vfork_events>: New member. (target_supports_fork_events): New macro. (target_supports_vfork_events): New macro. * win32-low.c (win32_target_ops): Initialize new structure members. gdb/ChangeLog: * nat/linux-ptrace.c (linux_check_ptrace_features): Change from static to extern. * nat/linux-ptrace.h (linux_check_ptrace_features): Declare. * remote.c (anonymous enum): <PACKET_fork_event_feature, * PACKET_vfork_event_feature>: New enumeration constants. (remote_protocol_features): Add table entries for new packets. (remote_query_supported): Add new feature queries to qSupported packet. (_initialize_remote): Exempt new packets from the requirement to have 'set remote' commands.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog21
-rw-r--r--gdb/gdbserver/linux-low.c20
-rw-r--r--gdb/gdbserver/lynx-low.c2
-rw-r--r--gdb/gdbserver/server.c22
-rw-r--r--gdb/gdbserver/target.h14
-rw-r--r--gdb/gdbserver/win32-low.c2
6 files changed, 81 insertions, 0 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 94146b8f48b..a37051d5c69 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,24 @@
+2015-05-12 Don Breazeal <donb@codesourcery.com>
+
+ * linux-low.c (linux_supports_fork_events): New function.
+ (linux_supports_vfork_events): New function.
+ (linux_target_ops): Initialize new structure members.
+ (initialize_low): Call linux_check_ptrace_features.
+ * lynx-low.c (lynx_target_ops): Initialize new structure
+ members.
+ * server.c (report_fork_events, report_vfork_events):
+ New global flags.
+ (handle_query): Add new features to qSupported packet and
+ response.
+ (captured_main): Initialize new global variables.
+ * target.h (struct target_ops) <supports_fork_events>:
+ New member.
+ <supports_vfork_events>: New member.
+ (target_supports_fork_events): New macro.
+ (target_supports_vfork_events): New macro.
+ * win32-low.c (win32_target_ops): Initialize new structure
+ members.
+
2015-05-12 Gary Benson <gbenson@redhat.com>
* server.c (handle_qxfer_exec_file): Use current process
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index bc76ffc1266..1724b5491d8 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5438,6 +5438,22 @@ 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 ();
+}
+
static int
linux_supports_disable_randomization (void)
{
@@ -6411,6 +6427,8 @@ 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,
#ifdef USE_THREAD_DB
thread_db_handle_monitor_command,
#else
@@ -6488,4 +6506,6 @@ initialize_low (void)
sigaction (SIGCHLD, &sigchld_action, NULL);
initialize_low_arch ();
+
+ linux_check_ptrace_features ();
}
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 364c79f363c..f08741601d1 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -762,6 +762,8 @@ 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, /* handle_monitor_command */
};
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 174ab398b0b..1544e99bdb3 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -57,6 +57,8 @@ static int exit_requested;
int run_once;
int multi_process;
+int report_fork_events;
+int report_vfork_events;
int non_stop;
int swbreak_feature;
int hwbreak_feature;
@@ -2046,6 +2048,18 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_stopped_by_hw_breakpoint ())
hwbreak_feature = 1;
}
+ else if (strcmp (p, "fork-events+") == 0)
+ {
+ /* GDB supports and wants fork events if possible. */
+ if (target_supports_fork_events ())
+ report_fork_events = 1;
+ }
+ else if (strcmp (p, "vfork-events+") == 0)
+ {
+ /* GDB supports and wants vfork events if possible. */
+ if (target_supports_vfork_events ())
+ report_vfork_events = 1;
+ }
else
target_process_qsupported (p);
@@ -2096,6 +2110,12 @@ 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_non_stop ())
strcat (own_buf, ";QNonStop+");
@@ -3472,6 +3492,8 @@ captured_main (int argc, char *argv[])
noack_mode = 0;
multi_process = 0;
+ report_fork_events = 0;
+ report_vfork_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 b3d08cddd1a..697b223bcb3 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -281,6 +281,12 @@ 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);
+
/* 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 *);
@@ -420,6 +426,14 @@ 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 detach_inferior(pid) \
(*the_target->detach) (pid)
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 6cf56bd54d3..a58f9634883 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -1831,6 +1831,8 @@ 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, /* handle_monitor_command */
NULL, /* core_of_thread */
NULL, /* read_loadmap */