diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/gdbserver/linux-low.c | 26 | ||||
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 18 | ||||
-rw-r--r-- | gdb/gdbserver/server.h | 1 | ||||
-rw-r--r-- | gdb/remote.c | 22 |
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; |