1 1.16 skrll /* $NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $ */ 2 1.1 ad 3 1.1 ad /*- 4 1.10 ad * Copyright (c) 2009, 2020 The NetBSD Foundation, Inc. 5 1.1 ad * All rights reserved. 6 1.1 ad * 7 1.1 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 ad * by Andrew Doran. 9 1.1 ad * 10 1.1 ad * Redistribution and use in source and binary forms, with or without 11 1.1 ad * modification, are permitted provided that the following conditions 12 1.1 ad * are met: 13 1.1 ad * 1. Redistributions of source code must retain the above copyright 14 1.1 ad * notice, this list of conditions and the following disclaimer. 15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ad * notice, this list of conditions and the following disclaimer in the 17 1.1 ad * documentation and/or other materials provided with the distribution. 18 1.1 ad * 19 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ad */ 31 1.1 ad 32 1.1 ad /* 33 1.1 ad * Copyright (c) 1982, 1986, 1989, 1991, 1993 34 1.1 ad * The Regents of the University of California. All rights reserved. 35 1.1 ad * 36 1.1 ad * Redistribution and use in source and binary forms, with or without 37 1.1 ad * modification, are permitted provided that the following conditions 38 1.1 ad * are met: 39 1.1 ad * 1. Redistributions of source code must retain the above copyright 40 1.1 ad * notice, this list of conditions and the following disclaimer. 41 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 ad * notice, this list of conditions and the following disclaimer in the 43 1.1 ad * documentation and/or other materials provided with the distribution. 44 1.1 ad * 3. Neither the name of the University nor the names of its contributors 45 1.1 ad * may be used to endorse or promote products derived from this software 46 1.1 ad * without specific prior written permission. 47 1.1 ad * 48 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 ad * SUCH DAMAGE. 59 1.1 ad * 60 1.1 ad * from: kern_proc.c 8.4 (Berkeley) 1/4/94 61 1.1 ad */ 62 1.1 ad 63 1.1 ad #include <sys/cdefs.h> 64 1.16 skrll __KERNEL_RCSID(0, "$NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $"); 65 1.3 mrg 66 1.3 mrg #ifndef _KERNEL 67 1.3 mrg #include <stdbool.h> 68 1.3 mrg #endif 69 1.1 ad 70 1.1 ad #include <sys/param.h> 71 1.1 ad #include <sys/cpu.h> 72 1.1 ad #include <sys/proc.h> 73 1.3 mrg #ifdef _KERNEL /* XXX */ 74 1.1 ad #include <sys/kauth.h> 75 1.3 mrg #endif 76 1.1 ad 77 1.2 mrg #include <ddb/ddb.h> 78 1.2 mrg 79 1.1 ad proc_t * 80 1.1 ad db_proc_first(void) 81 1.1 ad { 82 1.1 ad 83 1.1 ad return db_read_ptr("allproc"); 84 1.1 ad } 85 1.1 ad 86 1.1 ad proc_t * 87 1.1 ad db_proc_next(proc_t *p) 88 1.1 ad { 89 1.1 ad 90 1.1 ad db_read_bytes((db_addr_t)&p->p_list.le_next, sizeof(p), (char *)&p); 91 1.1 ad return p; 92 1.1 ad } 93 1.1 ad 94 1.1 ad proc_t * 95 1.1 ad db_proc_find(pid_t pid) 96 1.1 ad { 97 1.1 ad proc_t *p; 98 1.1 ad pid_t tp; 99 1.1 ad 100 1.1 ad for (p = db_proc_first(); p != NULL; p = db_proc_next(p)) { 101 1.1 ad db_read_bytes((db_addr_t)&p->p_pid, sizeof(tp), 102 1.1 ad (char *)&tp); 103 1.1 ad if (tp == pid) { 104 1.1 ad return p; 105 1.1 ad } 106 1.1 ad } 107 1.1 ad return NULL; 108 1.1 ad } 109 1.1 ad 110 1.7 maxv static void 111 1.7 maxv db_read_string(const char *src, size_t len, char *dst) 112 1.7 maxv { 113 1.7 maxv size_t i; 114 1.7 maxv 115 1.7 maxv for (i = 0; i < len; i++) { 116 1.7 maxv db_read_bytes((db_addr_t)&src[i], 1, &dst[i]); 117 1.8 maxv if (dst[i] == '\0') 118 1.7 maxv break; 119 1.7 maxv } 120 1.7 maxv } 121 1.7 maxv 122 1.1 ad void 123 1.1 ad db_show_all_procs(db_expr_t addr, bool haddr, db_expr_t count, 124 1.1 ad const char *modif) 125 1.1 ad { 126 1.1 ad static struct pgrp pgrp; 127 1.1 ad static proc_t p; 128 1.1 ad static lwp_t l; 129 1.1 ad const char *mode, *ename; 130 1.1 ad proc_t *pp; 131 1.1 ad lwp_t *lp; 132 1.1 ad char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1]; 133 1.1 ad bool run; 134 1.1 ad int cpuno; 135 1.1 ad 136 1.1 ad if (modif[0] == 0) 137 1.1 ad mode = "l"; /* default == lwp mode */ 138 1.1 ad else 139 1.1 ad mode = strchr("mawln", modif[0]); 140 1.1 ad 141 1.1 ad if (mode == NULL || *mode == 'm') { 142 1.1 ad db_printf("usage: show all procs [/a] [/l] [/n] [/w]\n"); 143 1.1 ad db_printf("\t/a == show process address info\n"); 144 1.4 christos db_printf("\t/l == show LWP info [default]\n"); 145 1.4 christos db_printf("\t/n == show normal process info\n"); 146 1.1 ad db_printf("\t/w == show process wait/emul info\n"); 147 1.1 ad return; 148 1.1 ad } 149 1.1 ad 150 1.1 ad switch (*mode) { 151 1.1 ad case 'a': 152 1.14 simonb db_printf("PID %-16s %18s %18s %18s\n", 153 1.1 ad "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP"); 154 1.1 ad break; 155 1.1 ad case 'l': 156 1.16 skrll db_printf("PID %5s S %3s %9s %18s %18s %-8s\n", 157 1.1 ad "LID", "CPU", "FLAGS", "STRUCT LWP *", "NAME", "WAIT"); 158 1.1 ad break; 159 1.1 ad case 'n': 160 1.1 ad db_printf("PID %8s %8s %10s S %7s %4s %16s %7s\n", 161 1.1 ad "PPID", "PGRP", "UID", "FLAGS", "LWPS", "COMMAND", "WAIT"); 162 1.1 ad break; 163 1.1 ad case 'w': 164 1.16 skrll db_printf("PID %5s %16s %8s %4s %-16s %s\n", 165 1.1 ad "LID", "COMMAND", "EMUL", "PRI", "WAIT-MSG", 166 1.1 ad "WAIT-CHANNEL"); 167 1.1 ad break; 168 1.1 ad } 169 1.1 ad 170 1.1 ad for (pp = db_proc_first(); pp != NULL; pp = db_proc_next(pp)) { 171 1.1 ad db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p); 172 1.1 ad if (p.p_stat == 0) { 173 1.1 ad continue; 174 1.1 ad } 175 1.1 ad lp = p.p_lwps.lh_first; 176 1.1 ad if (lp != NULL) { 177 1.1 ad db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); 178 1.1 ad } 179 1.1 ad db_printf("%-5d", p.p_pid); 180 1.1 ad 181 1.1 ad switch (*mode) { 182 1.1 ad case 'a': 183 1.14 simonb db_printf(" %-16.16s %18lx %18lx %18lx\n", 184 1.1 ad p.p_comm, (long)pp, 185 1.1 ad (long)(lp != NULL ? l.l_addr : 0), 186 1.1 ad (long)p.p_vmspace); 187 1.1 ad break; 188 1.1 ad case 'l': 189 1.1 ad while (lp != NULL) { 190 1.1 ad if (l.l_name != NULL) { 191 1.7 maxv db_read_string(l.l_name, 192 1.1 ad MAXCOMLEN, db_nbuf); 193 1.7 maxv db_nbuf[MAXCOMLEN] = '\0'; 194 1.1 ad } else { 195 1.1 ad strlcpy(db_nbuf, p.p_comm, 196 1.1 ad sizeof(db_nbuf)); 197 1.1 ad } 198 1.1 ad run = (l.l_stat == LSONPROC || 199 1.10 ad (l.l_pflag & LP_RUNNING) != 0); 200 1.1 ad if (l.l_cpu != NULL) { 201 1.1 ad db_read_bytes((db_addr_t) 202 1.1 ad &l.l_cpu->ci_data.cpu_index, 203 1.1 ad sizeof(cpuno), (char *)&cpuno); 204 1.1 ad } else 205 1.1 ad cpuno = -1; 206 1.1 ad if (l.l_wchan && l.l_wmesg) { 207 1.7 maxv db_read_string(l.l_wmesg, 208 1.7 maxv sizeof(wbuf), wbuf); 209 1.7 maxv wbuf[MAXCOMLEN] = '\0'; 210 1.1 ad } else { 211 1.1 ad wbuf[0] = '\0'; 212 1.1 ad } 213 1.16 skrll db_printf("%c%5d %d %3d %9x %18lx %18s %-8s\n", 214 1.1 ad (run ? '>' : ' '), l.l_lid, 215 1.1 ad l.l_stat, cpuno, l.l_flag, (long)lp, 216 1.1 ad db_nbuf, wbuf); 217 1.1 ad lp = LIST_NEXT((&l), l_sibling); 218 1.1 ad if (lp != NULL) { 219 1.1 ad db_printf("%-5d", p.p_pid); 220 1.1 ad db_read_bytes((db_addr_t)lp, sizeof(l), 221 1.1 ad (char *)&l); 222 1.1 ad } 223 1.1 ad } 224 1.1 ad break; 225 1.1 ad case 'n': 226 1.1 ad db_read_bytes((db_addr_t)p.p_pgrp, sizeof(pgrp), 227 1.1 ad (char *)&pgrp); 228 1.1 ad if (lp != NULL && l.l_wchan && l.l_wmesg) { 229 1.7 maxv db_read_string(l.l_wmesg, 230 1.7 maxv sizeof(wbuf), wbuf); 231 1.7 maxv wbuf[MAXCOMLEN] = '\0'; 232 1.1 ad } else { 233 1.1 ad wbuf[0] = '\0'; 234 1.1 ad } 235 1.1 ad db_printf("%8d %8d %10d %d %#7x %4d %16s %7.7s\n", 236 1.11 hikaru p.p_pptr != NULL ? p.p_pptr->p_pid : -1, pgrp.pg_id, 237 1.1 ad #ifdef _KERNEL 238 1.1 ad kauth_cred_getuid(p.p_cred), 239 1.1 ad #else 240 1.1 ad /* XXX CRASH(8) */ 666, 241 1.13 skrll #endif 242 1.1 ad p.p_stat, p.p_flag, 243 1.1 ad p.p_nlwps, p.p_comm, 244 1.1 ad (p.p_nlwps != 1) ? "*" : wbuf); 245 1.1 ad break; 246 1.1 ad 247 1.1 ad case 'w': 248 1.1 ad while (lp != NULL) { 249 1.1 ad if (l.l_wchan && l.l_wmesg) { 250 1.7 maxv db_read_string(l.l_wmesg, 251 1.7 maxv sizeof(wbuf), wbuf); 252 1.7 maxv wbuf[MAXCOMLEN] = '\0'; 253 1.1 ad } else { 254 1.1 ad wbuf[0] = '\0'; 255 1.1 ad } 256 1.6 jym run = (l.l_stat == LSONPROC || 257 1.10 ad (l.l_pflag & LP_RUNNING) != 0); 258 1.1 ad db_read_bytes((db_addr_t)&p.p_emul->e_name, 259 1.1 ad sizeof(ename), (char *)&ename); 260 1.7 maxv 261 1.7 maxv db_read_string(ename, sizeof(db_nbuf), db_nbuf); 262 1.7 maxv db_nbuf[MAXCOMLEN] = '\0'; 263 1.7 maxv 264 1.1 ad db_printf( 265 1.16 skrll "%c%5d %16s %8s %4d %-16s %-18lx\n", 266 1.6 jym (run ? '>' : ' '), l.l_lid, 267 1.6 jym p.p_comm, db_nbuf, 268 1.1 ad l.l_priority, wbuf, (long)l.l_wchan); 269 1.1 ad lp = LIST_NEXT((&l), l_sibling); 270 1.1 ad if (lp != NULL) { 271 1.1 ad db_printf("%-5d", p.p_pid); 272 1.1 ad db_read_bytes((db_addr_t)lp, sizeof(l), 273 1.1 ad (char *)&l); 274 1.1 ad } 275 1.1 ad } 276 1.1 ad break; 277 1.1 ad } 278 1.1 ad } 279 1.1 ad } 280 1.1 ad 281 1.4 christos void 282 1.4 christos db_show_proc(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 283 1.4 christos { 284 1.4 christos static proc_t p; 285 1.4 christos static lwp_t l; 286 1.4 christos const char *mode; 287 1.4 christos proc_t *pp; 288 1.4 christos lwp_t *lp; 289 1.4 christos char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1]; 290 1.4 christos bool run; 291 1.4 christos int cpuno; 292 1.4 christos 293 1.4 christos if (modif[0] == 0) 294 1.4 christos mode = "p"; /* default == by pid */ 295 1.4 christos else 296 1.4 christos mode = strchr("ap", modif[0]); 297 1.4 christos 298 1.4 christos if (mode == NULL || !haddr) { 299 1.4 christos db_printf("usage: show proc [/a] [/p] address|pid\n"); 300 1.4 christos db_printf("\t/a == argument is an address of any lwp\n"); 301 1.4 christos db_printf("\t/p == argument is a pid [default]\n"); 302 1.4 christos return; 303 1.4 christos } 304 1.4 christos 305 1.4 christos switch (*mode) { 306 1.4 christos case 'a': 307 1.5 nakayama lp = (lwp_t *)(uintptr_t)addr; 308 1.4 christos db_printf("lwp_t %lx\n", (long)lp); 309 1.4 christos db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); 310 1.4 christos pp = l.l_proc; 311 1.4 christos break; 312 1.4 christos default: 313 1.4 christos case 'p': 314 1.4 christos pp = db_proc_find((pid_t)addr); 315 1.4 christos lp = NULL; 316 1.4 christos break; 317 1.4 christos } 318 1.4 christos 319 1.4 christos if (pp == NULL) { 320 1.4 christos db_printf("bad address\n"); 321 1.4 christos return; 322 1.4 christos } 323 1.4 christos 324 1.4 christos db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p); 325 1.4 christos if (lp == NULL) 326 1.4 christos lp = p.p_lwps.lh_first; 327 1.4 christos 328 1.4 christos db_printf("%s: pid %d proc %lx vmspace/map %lx flags %x\n", 329 1.4 christos p.p_comm, p.p_pid, (long)pp, (long)p.p_vmspace, p.p_flag); 330 1.4 christos 331 1.4 christos while (lp != NULL) { 332 1.4 christos db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); 333 1.4 christos 334 1.4 christos run = (l.l_stat == LSONPROC || 335 1.10 ad (l.l_pflag & LP_RUNNING) != 0); 336 1.4 christos 337 1.4 christos db_printf("%slwp %d", (run ? "> " : " "), l.l_lid); 338 1.4 christos if (l.l_name != NULL) { 339 1.7 maxv db_read_string(l.l_name, MAXCOMLEN, db_nbuf); 340 1.7 maxv db_nbuf[MAXCOMLEN] = '\0'; 341 1.4 christos db_printf(" [%s]", db_nbuf); 342 1.4 christos } 343 1.4 christos db_printf(" %lx pcb %lx\n", (long)lp, (long)l.l_addr); 344 1.4 christos 345 1.4 christos if (l.l_cpu != NULL) { 346 1.4 christos db_read_bytes((db_addr_t) 347 1.4 christos &l.l_cpu->ci_data.cpu_index, 348 1.4 christos sizeof(cpuno), (char *)&cpuno); 349 1.4 christos } else 350 1.4 christos cpuno = -1; 351 1.12 mlelstv db_printf(" stat %d flags %x cpu %d pri %d ref %d\n", 352 1.12 mlelstv l.l_stat, l.l_flag, cpuno, l.l_priority, l.l_refcnt); 353 1.4 christos 354 1.4 christos if (l.l_wchan && l.l_wmesg) { 355 1.7 maxv db_read_string(l.l_wmesg, MAXCOMLEN, wbuf); 356 1.7 maxv wbuf[MAXCOMLEN] = '\0'; 357 1.4 christos db_printf(" wmesg %s wchan %lx\n", 358 1.4 christos wbuf, (long)l.l_wchan); 359 1.4 christos } 360 1.4 christos 361 1.4 christos lp = LIST_NEXT(&l, l_sibling); 362 1.4 christos } 363 1.4 christos } 364