1/* Internal interfaces for the NetBSD code. 2 3 Copyright (C) 2006-2023 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 "gdbsupport/common-defs.h" 21#include "nat/netbsd-nat.h" 22#include "gdbsupport/common-debug.h" 23 24#include <sys/types.h> 25#include <sys/ptrace.h> 26#include <sys/sysctl.h> 27 28#include <cstring> 29 30#include "gdbsupport/function-view.h" 31 32namespace netbsd_nat 33{ 34 35/* See netbsd-nat.h. */ 36 37const char * 38pid_to_exec_file (pid_t pid) 39{ 40 static char buf[PATH_MAX]; 41 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME}; 42 size_t buflen = sizeof (buf); 43 if (::sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0) != 0) 44 return NULL; 45 return buf; 46} 47 48/* Generic thread (LWP) lister within a specified PID. The CALLBACK 49 parameters is a C++ function that is called for each detected thread. 50 When the CALLBACK function returns true, the iteration is interrupted. 51 52 This function assumes internally that the queried process is stopped 53 and the number of threads does not change between two sysctl () calls. */ 54 55static bool 56netbsd_thread_lister (const pid_t pid, 57 gdb::function_view<bool (const struct kinfo_lwp *)> 58 callback) 59{ 60 int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0}; 61 size_t size; 62 63 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) 64 perror_with_name (("sysctl")); 65 66 mib[4] = size / sizeof (size_t); 67 68 gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl 69 ((struct kinfo_lwp *) xcalloc (size, 1)); 70 71 if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1 72 || size == 0) 73 perror_with_name (("sysctl")); 74 75 for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++) 76 { 77 struct kinfo_lwp *l = &kl[i]; 78 79 /* Return true if the specified thread is alive. */ 80 auto lwp_alive 81 = [] (struct kinfo_lwp *lwp) 82 { 83 switch (lwp->l_stat) 84 { 85 case LSSLEEP: 86 case LSRUN: 87 case LSONPROC: 88 case LSSTOP: 89 case LSSUSPENDED: 90 return true; 91 default: 92 return false; 93 } 94 }; 95 96 /* Ignore embryonic or demised threads. */ 97 if (!lwp_alive (l)) 98 continue; 99 100 if (callback (l)) 101 return true; 102 } 103 104 return false; 105} 106 107/* See netbsd-nat.h. */ 108 109bool 110thread_alive (ptid_t ptid) 111{ 112 pid_t pid = ptid.pid (); 113 lwpid_t lwp = ptid.lwp (); 114 115 auto fn 116 = [=] (const struct kinfo_lwp *kl) 117 { 118 return kl->l_lid == lwp; 119 }; 120 121 return netbsd_thread_lister (pid, fn); 122} 123 124/* See netbsd-nat.h. */ 125 126const char * 127thread_name (ptid_t ptid) 128{ 129 pid_t pid = ptid.pid (); 130 lwpid_t lwp = ptid.lwp (); 131 132 static char buf[KI_LNAMELEN] = {}; 133 134 auto fn 135 = [=] (const struct kinfo_lwp *kl) 136 { 137 if (kl->l_lid == lwp) 138 { 139 xsnprintf (buf, sizeof buf, "%s", kl->l_name); 140 return true; 141 } 142 return false; 143 }; 144 145 if (netbsd_thread_lister (pid, fn)) 146 return buf; 147 else 148 return NULL; 149} 150 151/* See netbsd-nat.h. */ 152 153void 154for_each_thread (pid_t pid, gdb::function_view<void (ptid_t)> callback) 155{ 156 auto fn 157 = [=, &callback] (const struct kinfo_lwp *kl) 158 { 159 ptid_t ptid = ptid_t (pid, kl->l_lid, 0); 160 callback (ptid); 161 return false; 162 }; 163 164 netbsd_thread_lister (pid, fn); 165} 166 167/* See netbsd-nat.h. */ 168 169void 170enable_proc_events (pid_t pid) 171{ 172 int events; 173 174 if (ptrace (PT_GET_EVENT_MASK, pid, &events, sizeof (events)) == -1) 175 perror_with_name (("ptrace")); 176 177 events |= PTRACE_LWP_CREATE; 178 events |= PTRACE_LWP_EXIT; 179 180 if (ptrace (PT_SET_EVENT_MASK, pid, &events, sizeof (events)) == -1) 181 perror_with_name (("ptrace")); 182} 183 184/* See netbsd-nat.h. */ 185 186int 187qxfer_siginfo (pid_t pid, const char *annex, unsigned char *readbuf, 188 unsigned const char *writebuf, CORE_ADDR offset, int len) 189{ 190 ptrace_siginfo_t psi; 191 192 if (offset > sizeof (siginfo_t)) 193 return -1; 194 195 if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1) 196 return -1; 197 198 if (offset + len > sizeof (siginfo_t)) 199 len = sizeof (siginfo_t) - offset; 200 201 if (readbuf != NULL) 202 memcpy (readbuf, ((gdb_byte *) &psi.psi_siginfo) + offset, len); 203 else 204 { 205 memcpy (((gdb_byte *) &psi.psi_siginfo) + offset, writebuf, len); 206 207 if (ptrace (PT_SET_SIGINFO, pid, &psi, sizeof (psi)) == -1) 208 return -1; 209 } 210 return len; 211} 212 213/* See netbsd-nat.h. */ 214 215int 216write_memory (pid_t pid, unsigned const char *writebuf, CORE_ADDR offset, 217 size_t len, size_t *xfered_len) 218{ 219 struct ptrace_io_desc io; 220 io.piod_op = PIOD_WRITE_D; 221 io.piod_len = len; 222 223 size_t bytes_written = 0; 224 225 /* Zero length write always succeeds. */ 226 if (len > 0) 227 { 228 do 229 { 230 io.piod_addr = (void *)(writebuf + bytes_written); 231 io.piod_offs = (void *)(offset + bytes_written); 232 233 errno = 0; 234 int rv = ptrace (PT_IO, pid, &io, 0); 235 if (rv == -1) 236 { 237 gdb_assert (errno != 0); 238 return errno; 239 } 240 if (io.piod_len == 0) 241 break; 242 243 bytes_written += io.piod_len; 244 io.piod_len = len - bytes_written; 245 } 246 while (bytes_written < len); 247 } 248 249 if (xfered_len != nullptr) 250 *xfered_len = bytes_written; 251 252 return 0; 253} 254 255/* See netbsd-nat.h. */ 256 257int 258read_memory (pid_t pid, unsigned char *readbuf, CORE_ADDR offset, 259 size_t len, size_t *xfered_len) 260{ 261 struct ptrace_io_desc io; 262 io.piod_op = PIOD_READ_D; 263 io.piod_len = len; 264 265 size_t bytes_read = 0; 266 267 /* Zero length read always succeeds. */ 268 if (len > 0) 269 { 270 do 271 { 272 io.piod_offs = (void *)(offset + bytes_read); 273 io.piod_addr = readbuf + bytes_read; 274 275 int rv = ptrace (PT_IO, pid, &io, 0); 276 if (rv == -1) 277 return errno; 278 if (io.piod_len == 0) 279 break; 280 281 bytes_read += io.piod_len; 282 io.piod_len = len - bytes_read; 283 } 284 while (bytes_read < len); 285 } 286 287 if (xfered_len != nullptr) 288 *xfered_len = bytes_read; 289 290 return 0; 291} 292 293} 294