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