aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/gdbserver/ChangeLog11
-rw-r--r--gdb/gdbserver/linux-low.c26
-rw-r--r--gdb/gdbserver/remote-utils.c18
-rw-r--r--gdb/gdbserver/server.h1
-rw-r--r--gdb/remote.c22
6 files changed, 78 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c9c2e62..e84f23f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
2015-05-12 Don Breazeal <donb@codesourcery.com>
+ * remote.c (remove_vfork_event_p): New function.
+ (remote_follow_fork): Add vfork event type to event checking.
+ (remote_parse_stop_reply): New stop reasons "vfork" and
+ "vforkdone" for RSP 'T' Stop Reply Packet.
+
+2015-05-12 Don Breazeal <donb@codesourcery.com>
+
* linux-nat.c (linux_nat_ptrace_options): New function.
(linux_init_ptrace, wait_lwp, linux_nat_filter_event):
Call linux_nat_ptrace_options and use different argument to
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 0bdcdf3..1e20a36 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,16 @@
2015-05-12 Don Breazeal <donb@codesourcery.com>
+ * linux-low.c (handle_extended_wait): Handle PTRACE_EVENT_FORK and
+ PTRACE_EVENT_VFORK_DONE.
+ (linux_low_ptrace_options, extended_event_reported): Add vfork
+ events.
+ * remote-utils.c (prepare_resume_reply): New stop reasons "vfork"
+ and "vforkdone" for RSP 'T' Stop Reply Packet.
+ * server.h (report_vfork_events): Declare
+ global variable.
+
+2015-05-12 Don Breazeal <donb@codesourcery.com>
+
* linux-aarch64-low.c (aarch64_linux_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
* linux-arm-low.c (arm_new_fork): New function.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index d9053ad..9f3ea48 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -425,7 +425,8 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat)
struct thread_info *event_thr = get_lwp_thread (event_lwp);
struct lwp_info *new_lwp;
- if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_CLONE))
+ if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_VFORK)
+ || (event == PTRACE_EVENT_CLONE))
{
ptid_t ptid;
unsigned long new_pid;
@@ -451,7 +452,7 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat)
warning ("wait returned unexpected status 0x%x", status);
}
- if (event == PTRACE_EVENT_FORK)
+ if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK)
{
struct process_info *parent_proc;
struct process_info *child_proc;
@@ -494,8 +495,13 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat)
the_low_target.new_fork (parent_proc, child_proc);
/* Save fork info in the parent thread. */
- event_lwp->waitstatus.kind = TARGET_WAITKIND_FORKED;
+ if (event == PTRACE_EVENT_FORK)
+ event_lwp->waitstatus.kind = TARGET_WAITKIND_FORKED;
+ else if (event == PTRACE_EVENT_VFORK)
+ event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORKED;
+
event_lwp->waitstatus.value.related_pid = ptid;
+
/* The status_pending field contains bits denoting the
extended event, so when the pending event is handled,
the handler will look at lwp->waitstatus. */
@@ -538,6 +544,13 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat)
/* Don't report the event. */
return 1;
}
+ else if (event == PTRACE_EVENT_VFORK_DONE)
+ {
+ event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORK_DONE;
+
+ /* Report the event. */
+ return 0;
+ }
internal_error (__FILE__, __LINE__, _("unknown ptrace event %d"), event);
}
@@ -2010,6 +2023,9 @@ linux_low_ptrace_options (int attached)
if (report_fork_events)
options |= PTRACE_O_TRACEFORK;
+ if (report_vfork_events)
+ options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);
+
return options;
}
@@ -2714,7 +2730,9 @@ extended_event_reported (const struct target_waitstatus *waitstatus)
if (waitstatus == NULL)
return 0;
- return (waitstatus->kind == TARGET_WAITKIND_FORKED);
+ return (waitstatus->kind == TARGET_WAITKIND_FORKED
+ || waitstatus->kind == TARGET_WAITKIND_VFORKED
+ || waitstatus->kind == TARGET_WAITKIND_VFORK_DONE);
}
/* Wait for process, returns status. */
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 6078348..bb31456 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -1115,16 +1115,20 @@ prepare_resume_reply (char *buf, ptid_t ptid,
{
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_FORKED:
+ case TARGET_WAITKIND_VFORKED:
{
struct thread_info *saved_thread;
const char **regp;
struct regcache *regcache;
- if (status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
+ if ((status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
+ || (status->kind == TARGET_WAITKIND_VFORKED && report_vfork_events))
{
enum gdb_signal signal = GDB_SIGNAL_TRAP;
+ const char *event = (status->kind == TARGET_WAITKIND_FORKED
+ ? "fork" : "vfork");
- sprintf (buf, "T%02xfork:", signal);
+ sprintf (buf, "T%02x%s:", signal, event);
buf += strlen (buf);
buf = write_ptid (buf, status->value.related_pid);
strcat (buf, ";");
@@ -1244,6 +1248,16 @@ prepare_resume_reply (char *buf, ptid_t ptid,
else
sprintf (buf, "X%02x", status->value.sig);
break;
+ case TARGET_WAITKIND_VFORK_DONE:
+ if (report_vfork_events)
+ {
+ enum gdb_signal signal = GDB_SIGNAL_TRAP;
+
+ sprintf (buf, "T%02xvforkdone:;", signal);
+ }
+ else
+ sprintf (buf, "T%02x", GDB_SIGNAL_0);
+ break;
default:
error ("unhandled waitkind");
break;
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 696a24e..09a5624 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -85,6 +85,7 @@ extern int disable_packet_qfThreadInfo;
extern int run_once;
extern int multi_process;
extern int report_fork_events;
+extern int report_vfork_events;
extern int non_stop;
/* True if the "swbreak+" feature is active. In that case, GDB wants
diff --git a/gdb/remote.c b/gdb/remote.c
index 390d30d..df8fca3 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1470,6 +1470,14 @@ 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;
+}
+
/* 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;
@@ -4537,8 +4545,10 @@ remote_follow_fork (struct target_ops *ops, int follow_child,
int detach_fork)
{
struct remote_state *rs = get_remote_state ();
+ enum target_waitkind kind = inferior_thread ()->pending_follow.kind;
- if (remote_fork_event_p (rs))
+ if ((kind == TARGET_WAITKIND_FORKED && remote_fork_event_p (rs))
+ || (kind == TARGET_WAITKIND_VFORKED && remote_vfork_event_p (rs)))
{
/* When following the parent and detaching the child, we detach
the child here. For the case of following the child and
@@ -5727,6 +5737,16 @@ Packet: '%s'\n"),
event->ws.value.related_pid = read_ptid (++p1, &p);
event->ws.kind = TARGET_WAITKIND_FORKED;
}
+ else if (strncmp (p, "vfork", p1 - p) == 0)
+ {
+ event->ws.value.related_pid = read_ptid (++p1, &p);
+ event->ws.kind = TARGET_WAITKIND_VFORKED;
+ }
+ else if (strncmp (p, "vforkdone", p1 - p) == 0)
+ {
+ event->ws.kind = TARGET_WAITKIND_VFORK_DONE;
+ p = skip_to_semicolon (p1 + 1);
+ }
else
{
ULONGEST pnum;