diff options
author | Mark Kettenis <kettenis@gnu.org> | 2005-07-25 21:11:02 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2005-07-25 21:11:02 +0000 |
commit | 735f54b499f18e9f36644d69737a5653ace1c008 (patch) | |
tree | 381ec4166bebabf7bb29e2443e7378656c18352e /gdb | |
parent | 4b8a1a2882dbf0f5bc93eed673d8fb6068ddb924 (diff) | |
download | gdb-735f54b499f18e9f36644d69737a5653ace1c008.zip gdb-735f54b499f18e9f36644d69737a5653ace1c008.tar.gz gdb-735f54b499f18e9f36644d69737a5653ace1c008.tar.bz2 |
* inf-ptrace.c [PT_GET_PROCESS_STATE] (inf_ptrace_follow_fork):
New function.
(inf_ptrace_him, inf_ptrace_attach) [PT_GET_PROCESS_STATE]: Set
PTRACE_FORK event flag.
(inf_ptrace_wait) [PT_GET_PROCESS_STATE]: Handle PTRACE_FORK
event.
(inf_ptrace_target) [PT_GET_PROCESS_STATE]: Set to_follow_fork.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/inf-ptrace.c | 120 |
2 files changed, 130 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 348dd8d..77d4be8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2005-07-25 Mark Kettenis <kettenis@gnu.org> + * inf-ptrace.c [PT_GET_PROCESS_STATE] (inf_ptrace_follow_fork): + New function. + (inf_ptrace_him, inf_ptrace_attach) [PT_GET_PROCESS_STATE]: Set + PTRACE_FORK event flag. + (inf_ptrace_wait) [PT_GET_PROCESS_STATE]: Handle PTRACE_FORK + event. + (inf_ptrace_target) [PT_GET_PROCESS_STATE]: Set to_follow_fork. + +2005-07-25 Mark Kettenis <kettenis@gnu.org> + * gdb_ptrace.h (PT_TRACE_ME): Define to zero if not already defined. * inf-ptrace.c: Tweak comments. diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index 9c4a77f..033840a 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -41,6 +41,59 @@ static struct target_ops *ptrace_ops_hack; +#ifdef PT_GET_PROCESS_STATE + +static int +inf_ptrace_follow_fork (int follow_child) +{ + pid_t pid, fpid; + ptrace_state_t pe; + + /* FIXME: kettenis/20050720: This stuff should really be passed as + an argument by our caller. */ + { + ptid_t ptid; + struct target_waitstatus status; + + get_last_target_status (&ptid, &status); + gdb_assert (status.kind == TARGET_WAITKIND_FORKED); + + pid = ptid_get_pid (ptid); + } + + if (ptrace (PT_GET_PROCESS_STATE, pid, + (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + + gdb_assert (pe.pe_report_event == PTRACE_FORK); + fpid = pe.pe_other_pid; + + if (follow_child) + { + inferior_ptid = pid_to_ptid (fpid); + detach_breakpoints (pid); + + /* Reset breakpoints in the child as appropriate. */ + follow_inferior_reset_breakpoints (); + + if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1) + perror_with_name (("ptrace")); + } + else + { + inferior_ptid = pid_to_ptid (pid); + detach_breakpoints (fpid); + + if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1) + perror_with_name (("ptrace")); + } + + return 0; +} + +#endif /* PT_GET_PROCESS_STATE */ + + /* Prepare to be traced. */ static void @@ -55,6 +108,19 @@ inf_ptrace_me (void) static void inf_ptrace_him (int pid) { +#ifdef PT_GET_PROCESS_STATE + { + ptrace_event_t pe; + + /* Set the initial event mask. */ + memset (&pe, 0, sizeof pe); + pe.pe_set_event |= PTRACE_FORK; + if (ptrace (PT_SET_EVENT_MASK, pid, + (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + } +#endif + push_target (ptrace_ops_hack); /* On some targets, there must be some explicit synchronization @@ -156,6 +222,19 @@ inf_ptrace_attach (char *args, int from_tty) error (_("This system does not support attaching to a process")); #endif +#ifdef PT_GET_PROCESS_STATE + { + ptrace_event_t pe; + + /* Set the initial event mask. */ + memset (&pe, 0, sizeof pe); + pe.pe_set_event |= PTRACE_FORK; + if (ptrace (PT_SET_EVENT_MASK, pid, + (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + } +#endif + inferior_ptid = pid_to_ptid (pid); push_target (ptrace_ops_hack); @@ -310,6 +389,44 @@ inf_ptrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) } while (pid == -1); +#ifdef PT_GET_PROCESS_STATE + if (WIFSTOPPED (status)) + { + ptrace_state_t pe; + pid_t fpid; + + if (ptrace (PT_GET_PROCESS_STATE, pid, + (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + + switch (pe.pe_report_event) + { + case PTRACE_FORK: + ourstatus->kind = TARGET_WAITKIND_FORKED; + ourstatus->value.related_pid = pe.pe_other_pid; + + /* Make sure the other end of the fork is stopped too. */ + fpid = waitpid (pe.pe_other_pid, &status, 0); + if (fpid == -1) + perror_with_name (("waitpid")); + + if (ptrace (PT_GET_PROCESS_STATE, fpid, + (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + + gdb_assert (pe.pe_report_event == PTRACE_FORK); + gdb_assert (pe.pe_other_pid == pid); + if (fpid == ptid_get_pid (inferior_ptid)) + { + ourstatus->value.related_pid = pe.pe_other_pid; + return pid_to_ptid (fpid); + } + + return pid_to_ptid (pid); + } + } +#endif + store_waitstatus (ourstatus, status); return pid_to_ptid (pid); } @@ -471,6 +588,9 @@ inf_ptrace_target (void) t->to_files_info = inf_ptrace_files_info; t->to_kill = inf_ptrace_kill; t->to_create_inferior = inf_ptrace_create_inferior; +#ifdef PT_GET_PROCESS_STATE + t->to_follow_fork = inf_ptrace_follow_fork; +#endif t->to_mourn_inferior = inf_ptrace_mourn_inferior; t->to_thread_alive = inf_ptrace_thread_alive; t->to_pid_to_str = normal_pid_to_str; |