1 /* Native-dependent code for OpenBSD. 2 3 Copyright (C) 2012-2016 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 3 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, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "gdbthread.h" 22 #include "inferior.h" 23 #include "target.h" 24 25 #include <sys/types.h> 26 #include <sys/ptrace.h> 27 #include "gdb_wait.h" 28 29 #include "inf-child.h" 30 #include "obsd-nat.h" 31 32 /* OpenBSD 5.2 and later include rthreads which uses a thread model 33 that maps userland threads directly onto kernel threads in a 1:1 34 fashion. */ 35 36 #ifdef PT_GET_THREAD_FIRST 37 38 static char * 39 obsd_pid_to_str (struct target_ops *ops, ptid_t ptid) 40 { 41 if (ptid_get_lwp (ptid) != 0) 42 { 43 static char buf[64]; 44 45 xsnprintf (buf, sizeof buf, "thread %ld", ptid_get_lwp (ptid)); 46 return buf; 47 } 48 49 return normal_pid_to_str (ptid); 50 } 51 52 static void 53 obsd_update_thread_list (struct target_ops *ops) 54 { 55 pid_t pid = ptid_get_pid (inferior_ptid); 56 struct ptrace_thread_state pts; 57 58 prune_threads (); 59 60 if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) 61 perror_with_name (("ptrace")); 62 63 while (pts.pts_tid != -1) 64 { 65 ptid_t ptid = ptid_build (pid, pts.pts_tid, 0); 66 67 if (!in_thread_list (ptid)) 68 { 69 if (ptid_get_lwp (inferior_ptid) == 0) 70 thread_change_ptid (inferior_ptid, ptid); 71 else 72 add_thread (ptid); 73 } 74 75 if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) 76 perror_with_name (("ptrace")); 77 } 78 } 79 80 static ptid_t 81 obsd_wait (struct target_ops *ops, 82 ptid_t ptid, struct target_waitstatus *ourstatus, int options) 83 { 84 pid_t pid; 85 int status, save_errno; 86 87 do 88 { 89 set_sigint_trap (); 90 91 do 92 { 93 pid = waitpid (ptid_get_pid (ptid), &status, 0); 94 save_errno = errno; 95 } 96 while (pid == -1 && errno == EINTR); 97 98 clear_sigint_trap (); 99 100 if (pid == -1) 101 { 102 fprintf_unfiltered (gdb_stderr, 103 _("Child process unexpectedly missing: %s.\n"), 104 safe_strerror (save_errno)); 105 106 /* Claim it exited with unknown signal. */ 107 ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 108 ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; 109 return inferior_ptid; 110 } 111 112 /* Ignore terminated detached child processes. */ 113 if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) 114 pid = -1; 115 } 116 while (pid == -1); 117 118 ptid = pid_to_ptid (pid); 119 120 if (WIFSTOPPED (status)) 121 { 122 ptrace_state_t pe; 123 pid_t fpid; 124 125 if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) 126 perror_with_name (("ptrace")); 127 128 switch (pe.pe_report_event) 129 { 130 case PTRACE_FORK: 131 ourstatus->kind = TARGET_WAITKIND_FORKED; 132 ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); 133 134 /* Make sure the other end of the fork is stopped too. */ 135 fpid = waitpid (pe.pe_other_pid, &status, 0); 136 if (fpid == -1) 137 perror_with_name (("waitpid")); 138 139 if (ptrace (PT_GET_PROCESS_STATE, fpid, 140 (caddr_t)&pe, sizeof pe) == -1) 141 perror_with_name (("ptrace")); 142 143 gdb_assert (pe.pe_report_event == PTRACE_FORK); 144 gdb_assert (pe.pe_other_pid == pid); 145 if (fpid == ptid_get_pid (inferior_ptid)) 146 { 147 ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); 148 return pid_to_ptid (fpid); 149 } 150 151 return pid_to_ptid (pid); 152 } 153 154 ptid = ptid_build (pid, pe.pe_tid, 0); 155 if (!in_thread_list (ptid)) 156 { 157 if (ptid_get_lwp (inferior_ptid) == 0) 158 thread_change_ptid (inferior_ptid, ptid); 159 else 160 add_thread (ptid); 161 } 162 } 163 164 store_waitstatus (ourstatus, status); 165 return ptid; 166 } 167 168 void 169 obsd_add_target (struct target_ops *t) 170 { 171 /* Override some methods to support threads. */ 172 t->to_pid_to_str = obsd_pid_to_str; 173 t->to_update_thread_list = obsd_update_thread_list; 174 t->to_wait = obsd_wait; 175 add_target (t); 176 } 177 178 #else 179 180 void 181 obsd_add_target (struct target_ops *t) 182 { 183 add_target (t); 184 } 185 186 #endif /* PT_GET_THREAD_FIRST */ 187