1 /* Native-dependent code for OpenBSD. 2 3 Copyright 2012 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 #include "defs.h" 23 #include "gdbthread.h" 24 #include "inferior.h" 25 #include "target.h" 26 27 #include "gdb_assert.h" 28 #include <sys/types.h> 29 #include <sys/ptrace.h> 30 #include <sys/wait.h> 31 32 #include "obsd-nat.h" 33 34 char * 35 obsd_pid_to_str (ptid_t ptid) 36 { 37 if (ptid_get_lwp (ptid) != 0) 38 { 39 static char buf[64]; 40 41 xsnprintf (buf, sizeof buf, "thread %ld", ptid_get_lwp (ptid)); 42 return buf; 43 } 44 45 return normal_pid_to_str (ptid); 46 } 47 48 void 49 obsd_find_new_threads (void) 50 { 51 pid_t pid = ptid_get_pid (inferior_ptid); 52 struct ptrace_thread_state pts; 53 54 if (ptrace(PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) 55 perror_with_name (("ptrace")); 56 57 while (pts.pts_tid != -1) 58 { 59 ptid_t ptid = ptid_build (pid, pts.pts_tid, 0); 60 61 if (!in_thread_list (ptid)) 62 { 63 /* HACK: Twiddle INFERIOR_PTID such that the initial thread 64 of a process isn't recognized as a new thread. */ 65 if (ptid_get_lwp (inferior_ptid) == 0) 66 inferior_ptid = ptid; 67 add_thread (ptid); 68 } 69 70 if (ptrace(PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) 71 perror_with_name (("ptrace")); 72 } 73 } 74 75 ptid_t 76 obsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 77 { 78 pid_t pid; 79 int status, save_errno; 80 81 do 82 { 83 set_sigint_trap (); 84 set_sigio_trap (); 85 86 do 87 { 88 pid = waitpid (ptid_get_pid (ptid), &status, 0); 89 save_errno = errno; 90 } 91 while (pid == -1 && errno == EINTR); 92 93 clear_sigio_trap (); 94 clear_sigint_trap (); 95 96 if (pid == -1) 97 { 98 fprintf_unfiltered (gdb_stderr, 99 _("Child process unexpectedly missing: %s.\n"), 100 safe_strerror (save_errno)); 101 102 /* Claim it exited with unknown signal. */ 103 ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 104 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; 105 return minus_one_ptid; 106 } 107 108 /* Ignore terminated detached child processes. */ 109 if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) 110 pid = -1; 111 } 112 while (pid == -1); 113 114 ptid = pid_to_ptid (pid); 115 116 if (WIFSTOPPED (status)) 117 { 118 ptrace_state_t pe; 119 pid_t fpid; 120 121 if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) 122 perror_with_name (("ptrace")); 123 124 switch (pe.pe_report_event) 125 { 126 case PTRACE_FORK: 127 ourstatus->kind = TARGET_WAITKIND_FORKED; 128 ourstatus->value.related_pid = pe.pe_other_pid; 129 130 /* Make sure the other end of the fork is stopped too. */ 131 fpid = waitpid (pe.pe_other_pid, &status, 0); 132 if (fpid == -1) 133 perror_with_name (("waitpid")); 134 135 if (ptrace (PT_GET_PROCESS_STATE, fpid, 136 (caddr_t)&pe, sizeof pe) == -1) 137 perror_with_name (("ptrace")); 138 139 gdb_assert (pe.pe_report_event == PTRACE_FORK); 140 gdb_assert (pe.pe_other_pid == pid); 141 if (fpid == ptid_get_pid (inferior_ptid)) 142 { 143 ourstatus->value.related_pid = pe.pe_other_pid; 144 return pid_to_ptid (fpid); 145 } 146 147 return pid_to_ptid (pid); 148 } 149 150 ptid = ptid_build (pid, pe.pe_tid, 0); 151 if (!in_thread_list (ptid)) 152 { 153 /* HACK: Twiddle INFERIOR_PTID such that the initial thread 154 of a process isn't recognized as a new thread. */ 155 if (ptid_get_lwp (inferior_ptid) == 0) 156 inferior_ptid = ptid; 157 add_thread (ptid); 158 } 159 } 160 161 store_waitstatus (ourstatus, status); 162 return ptid; 163 } 164