diff options
author | Don Breazeal <donb@codesourcery.com> | 2014-09-30 11:01:57 -0700 |
---|---|---|
committer | Don Breazeal <donb@codesourcery.com> | 2014-09-30 11:01:57 -0700 |
commit | d83ad864a285fe3127e1a98830197e8461ad2745 (patch) | |
tree | 17fc116484b87e08c0a992063513490208c3e1ef /gdb/inf-ttrace.c | |
parent | 63b434a4374b61aa34b095a789cd0d03b2a5a526 (diff) | |
download | gdb-d83ad864a285fe3127e1a98830197e8461ad2745.zip gdb-d83ad864a285fe3127e1a98830197e8461ad2745.tar.gz gdb-d83ad864a285fe3127e1a98830197e8461ad2745.tar.bz2 |
Refactor native follow-fork.
This patch reorganizes the code that implements follow-fork and
detach-on-fork in preparation for implementation of those features for the
extended-remote target. The function linux-nat.c:linux_child_follow_fork
contained target-independent code mixed in with target-dependent code. The
target-independent pieces need to be accessible for the host-side
implementation of follow-fork for extended-remote Linux targets.
The changes are fairly mechanical. A new routine, follow_fork_inferior,
is implemented in infrun.c, containing those parts of
linux_child_follow_fork that manage inferiors and the inferior list. The
parts of linux_child_follow_fork that deal with LWPs and target-specifics
were left in-place. Although the order of some operations was changed, the
resulting functionality was not.
Modifications were made to the other native target follow-fork functions,
inf_ttrace_follow_fork and inf_ptrace_follow_fork, that should allow them
to work with follow_fork_inferior. Some other adjustments were necessary
in inf-ttrace.c. The changes to inf-ttrace.c and inf-ptrace.c were not
tested.
gdb/ChangeLog:
* inf-ptrace.c (inf_ptrace_follow_fork): Remove target-independent
code so as to work with follow_fork_inferior.
* inf-ttrace.c (inf_ttrace_follow_fork): Ditto.
(inf_ttrace_create_inferior): Remove reference to
inf_ttrace_vfork_ppid.
(inf_ttrace_attach): Ditto.
(inf_ttrace_detach): Ditto.
(inf_ttrace_kill): Use current_inferior instead of
inf_ttrace_vfork_ppid.
(inf_ttrace_wait): Eliminate use of inf_ttrace_vfork_ppid, report
TARGET_WAITKIND_VFORK_DONE event, delete HACK that switched the
inferior away from the parent.
* infrun.c (follow_fork): Call follow_fork_inferior instead of
target_follow_fork.
(follow_fork_inferior): New function.
(follow_inferior_reset_breakpoints): Make function static.
* infrun.h (follow_inferior_reset_breakpoints): Remove declaration.
* linux-nat.c (linux_child_follow_fork): Move target-independent
code to infrun.c:follow_fork_inferior.
Diffstat (limited to 'gdb/inf-ttrace.c')
-rw-r--r-- | gdb/inf-ttrace.c | 179 |
1 files changed, 21 insertions, 158 deletions
diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c index 847beb3..dceea42 100644 --- a/gdb/inf-ttrace.c +++ b/gdb/inf-ttrace.c @@ -403,128 +403,18 @@ inf_ttrace_stopped_by_watchpoint (struct target_ops *ops) } -/* When tracking a vfork(2), we cannot detach from the parent until - after the child has called exec(3) or has exited. If we are still - attached to the parent, this variable will be set to the process ID - of the parent. Otherwise it will be set to zero. */ -static pid_t inf_ttrace_vfork_ppid = -1; +/* Target hook for follow_fork. On entry and at return inferior_ptid + is the ptid of the followed inferior. */ static int inf_ttrace_follow_fork (struct target_ops *ops, int follow_child, int detach_fork) { - pid_t pid, fpid; - lwpid_t lwpid, flwpid; - ttstate_t tts; struct thread_info *tp = inferior_thread (); gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED); - pid = ptid_get_pid (inferior_ptid); - lwpid = ptid_get_lwp (inferior_ptid); - - /* Get all important details that core GDB doesn't (and shouldn't) - know about. */ - if (ttrace (TT_LWP_GET_STATE, pid, lwpid, - (uintptr_t)&tts, sizeof tts, 0) == -1) - perror_with_name (("ttrace")); - - gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK); - - if (tts.tts_u.tts_fork.tts_isparent) - { - pid = tts.tts_pid; - lwpid = tts.tts_lwpid; - fpid = tts.tts_u.tts_fork.tts_fpid; - flwpid = tts.tts_u.tts_fork.tts_flwpid; - } - else - { - pid = tts.tts_u.tts_fork.tts_fpid; - lwpid = tts.tts_u.tts_fork.tts_flwpid; - fpid = tts.tts_pid; - flwpid = tts.tts_lwpid; - } - - if (follow_child) - { - struct inferior *inf; - struct inferior *parent_inf; - - parent_inf = find_inferior_pid (pid); - - inferior_ptid = ptid_build (fpid, flwpid, 0); - inf = add_inferior (fpid); - inf->attach_flag = parent_inf->attach_flag; - inf->pspace = parent_inf->pspace; - inf->aspace = parent_inf->aspace; - copy_terminal_info (inf, parent_inf); - detach_breakpoints (ptid_build (pid, lwpid, 0)); - - target_terminal_ours (); - fprintf_unfiltered (gdb_stdlog, - _("Attaching after fork to child process %ld.\n"), - (long)fpid); - } - else - { - inferior_ptid = ptid_build (pid, lwpid, 0); - /* Detach any remaining breakpoints in the child. In the case - of fork events, we do not need to do this, because breakpoints - should have already been removed earlier. */ - if (tts.tts_event == TTEVT_VFORK) - detach_breakpoints (ptid_build (fpid, flwpid, 0)); - - target_terminal_ours (); - fprintf_unfiltered (gdb_stdlog, - _("Detaching after fork from child process %ld.\n"), - (long)fpid); - } - - if (tts.tts_event == TTEVT_VFORK) - { - gdb_assert (!tts.tts_u.tts_fork.tts_isparent); - - if (follow_child) - { - /* We can't detach from the parent yet. */ - inf_ttrace_vfork_ppid = pid; - - reattach_breakpoints (fpid); - } - else - { - if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - - /* Wait till we get the TTEVT_VFORK event in the parent. - This indicates that the child has called exec(3) or has - exited and that the parent is ready to be traced again. */ - if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) - perror_with_name (("ttrace_wait")); - gdb_assert (tts.tts_event == TTEVT_VFORK); - gdb_assert (tts.tts_u.tts_fork.tts_isparent); - - reattach_breakpoints (pid); - } - } - else - { - gdb_assert (tts.tts_u.tts_fork.tts_isparent); - - if (follow_child) - { - if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - } - else - { - if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - } - } - if (follow_child) { struct thread_info *ti; @@ -533,17 +423,21 @@ inf_ttrace_follow_fork (struct target_ops *ops, int follow_child, inf_ttrace_num_lwps = 1; inf_ttrace_num_lwps_in_syscall = 0; - /* Delete parent. */ - delete_thread_silent (ptid_build (pid, lwpid, 0)); - detach_inferior (pid); - - /* Add child thread. inferior_ptid was already set above. */ - ti = add_thread_silent (inferior_ptid); + ti = inferior_thread (); ti->private = xmalloc (sizeof (struct inf_ttrace_private_thread_info)); memset (ti->private, 0, sizeof (struct inf_ttrace_private_thread_info)); } + else + { + pid_t child_pid; + + /* Following parent. Detach child now. */ + child_pid = ptid_get_pid (tp->pending_follow.value.related_pid); + if (ttrace (TT_PROC_DETACH, child_pid, 0, 0, 0, 0) == -1) + perror_with_name (("ttrace")); + } return 0; } @@ -661,7 +555,6 @@ inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file, gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); gdb_assert (inf_ttrace_page_dict.count == 0); gdb_assert (inf_ttrace_reenable_page_protections == 0); - gdb_assert (inf_ttrace_vfork_ppid == -1); pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL, inf_ttrace_prepare, NULL, NULL); @@ -772,7 +665,6 @@ inf_ttrace_attach (struct target_ops *ops, const char *args, int from_tty) gdb_assert (inf_ttrace_num_lwps == 0); gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); - gdb_assert (inf_ttrace_vfork_ppid == -1); if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1) perror_with_name (("ttrace")); @@ -822,13 +714,6 @@ inf_ttrace_detach (struct target_ops *ops, const char *args, int from_tty) if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1) perror_with_name (("ttrace")); - if (inf_ttrace_vfork_ppid != -1) - { - if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - inf_ttrace_vfork_ppid = -1; - } - inf_ttrace_num_lwps = 0; inf_ttrace_num_lwps_in_syscall = 0; @@ -850,13 +735,6 @@ inf_ttrace_kill (struct target_ops *ops) perror_with_name (("ttrace")); /* ??? Is it necessary to call ttrace_wait() here? */ - if (inf_ttrace_vfork_ppid != -1) - { - if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - inf_ttrace_vfork_ppid = -1; - } - target_mourn_inferior (); } @@ -967,20 +845,6 @@ inf_ttrace_wait (struct target_ops *ops, if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) perror_with_name (("ttrace_wait")); - if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent) - { - if (inf_ttrace_vfork_ppid != -1) - { - gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid); - - if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - inf_ttrace_vfork_ppid = -1; - } - - tts.tts_event = TTEVT_NONE; - } - clear_sigint_trap (); } while (tts.tts_event == TTEVT_NONE); @@ -1075,17 +939,16 @@ inf_ttrace_wait (struct target_ops *ops, break; case TTEVT_VFORK: - gdb_assert (!tts.tts_u.tts_fork.tts_isparent); - - related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, - tts.tts_u.tts_fork.tts_flwpid, 0); - - ourstatus->kind = TARGET_WAITKIND_VFORKED; - ourstatus->value.related_pid = related_ptid; + if (tts.tts_u.tts_fork.tts_isparent) + ourstatus->kind = TARGET_WAITKIND_VFORK_DONE; + else + { + related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, + tts.tts_u.tts_fork.tts_flwpid, 0); - /* HACK: To avoid touching the parent during the vfork, switch - away from it. */ - inferior_ptid = ptid; + ourstatus->kind = TARGET_WAITKIND_VFORKED; + ourstatus->value.related_pid = related_ptid; + } break; case TTEVT_LWP_CREATE: |