diff options
author | 2012-04-13 16:40:09 +0000 | |
---|---|---|
committer | 2012-04-13 16:40:09 +0000 | |
commit | 6a28fc6fdccc6e3ecf4cf9bd4d4e5fdbfdd0bea4 (patch) | |
tree | 45e8a494b5ca2ad2263114e727834cbb4d38fcf1 | |
parent | First stab at making ptrace(2) usable for debugging multi-threaded programs. (diff) | |
download | wireguard-openbsd-6a28fc6fdccc6e3ecf4cf9bd4d4e5fdbfdd0bea4.tar.xz wireguard-openbsd-6a28fc6fdccc6e3ecf4cf9bd4d4e5fdbfdd0bea4.zip |
Add support for live debugging of multi-threaded code.
-rw-r--r-- | gnu/usr.bin/binutils/gdb/obsd-nat.c | 92 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/obsd-nat.h | 1 |
2 files changed, 93 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/gdb/obsd-nat.c b/gnu/usr.bin/binutils/gdb/obsd-nat.c index 56474369968..3dd8ec893bb 100644 --- a/gnu/usr.bin/binutils/gdb/obsd-nat.c +++ b/gnu/usr.bin/binutils/gdb/obsd-nat.c @@ -24,8 +24,10 @@ #include "inferior.h" #include "target.h" +#include "gdb_assert.h" #include <sys/types.h> #include <sys/ptrace.h> +#include <sys/wait.h> #include "obsd-nat.h" @@ -69,3 +71,93 @@ obsd_find_new_threads (void) perror_with_name (("ptrace")); } } + +ptid_t +obsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus) +{ + pid_t pid; + int status, save_errno; + + do + { + set_sigint_trap (); + set_sigio_trap (); + + do + { + pid = waitpid (ptid_get_pid (ptid), &status, 0); + save_errno = errno; + } + while (pid == -1 && errno == EINTR); + + clear_sigio_trap (); + clear_sigint_trap (); + + if (pid == -1) + { + fprintf_unfiltered (gdb_stderr, + _("Child process unexpectedly missing: %s.\n"), + safe_strerror (save_errno)); + + /* Claim it exited with unknown signal. */ + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; + return minus_one_ptid; + } + + /* Ignore terminated detached child processes. */ + if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) + pid = -1; + } + while (pid == -1); + + ptid = pid_to_ptid (pid); + + if (WIFSTOPPED (status)) + { + ptrace_state_t pe; + pid_t fpid; + + if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&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, + (caddr_t)&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); + } + + ptid = ptid_build (pid, pe.pe_tid, 0); + if (!in_thread_list (ptid)) + { + /* HACK: Twiddle INFERIOR_PTID such that the initial thread + of a process isn't recognized as a new thread. */ + if (ptid_get_lwp (inferior_ptid) == 0) + inferior_ptid = ptid; + add_thread (ptid); + } + } + + store_waitstatus (ourstatus, status); + return ptid; +} diff --git a/gnu/usr.bin/binutils/gdb/obsd-nat.h b/gnu/usr.bin/binutils/gdb/obsd-nat.h index a2bae58e1e8..f30670d480b 100644 --- a/gnu/usr.bin/binutils/gdb/obsd-nat.h +++ b/gnu/usr.bin/binutils/gdb/obsd-nat.h @@ -24,5 +24,6 @@ extern char *obsd_pid_to_str (ptid_t ptid); extern void obsd_find_new_threads (void); +extern ptid_t obsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus); #endif /* obsd-nat.h */ |