1/*- 2 * Copyright (c) 1993 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: stable/10/sys/ddb/db_ps.c 339858 2018-10-29 12:48:30Z avg $"); 32 33#include <sys/param.h> 34#include <sys/cons.h> 35#include <sys/jail.h> 36#include <sys/kdb.h> 37#include <sys/proc.h> 38#include <sys/sysent.h> 39#include <sys/systm.h> 40#include <sys/_kstack_cache.h> 41#include <vm/vm.h> 42#include <vm/vm_param.h> 43#include <vm/pmap.h> 44 45#include <ddb/ddb.h> 46 47#define PRINT_NONE 0 48#define PRINT_ARGS 1 49 50static void dumpthread(volatile struct proc *p, volatile struct thread *td, 51 int all); 52static int ps_mode; 53 54/* 55 * At least one non-optional show-command must be implemented using 56 * DB_SHOW_ALL_COMMAND() so that db_show_all_cmd_set gets created. 57 * Here is one. 58 */ 59DB_SHOW_ALL_COMMAND(procs, db_procs_cmd) 60{ 61 db_ps(addr, have_addr, count, modif); 62} 63 64static void 65dump_args(volatile struct proc *p) 66{ 67 char *args; 68 int i, len; 69 70 if (p->p_args == NULL) 71 return; 72 args = p->p_args->ar_args; 73 len = (int)p->p_args->ar_length; 74 for (i = 0; i < len; i++) { 75 if (args[i] == '\0') 76 db_printf(" "); 77 else 78 db_printf("%c", args[i]); 79 } 80} 81 82/* 83 * Layout: 84 * - column counts 85 * - header 86 * - single-threaded process 87 * - multi-threaded process 88 * - thread in a MT process 89 * 90 * 1 2 3 4 5 6 7 91 * 1234567890123456789012345678901234567890123456789012345678901234567890 92 * pid ppid pgrp uid state wmesg wchan cmd 93 * <pid> <ppi> <pgi> <uid> <stat> < wmesg > < wchan > <name> 94 * <pid> <ppi> <pgi> <uid> <stat> (threaded) <command> 95 * <tid > <stat> < wmesg > < wchan > <name> 96 * 97 * For machines with 64-bit pointers, we expand the wchan field 8 more 98 * characters. 99 */ 100void 101db_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 102{ 103 volatile struct proc *p, *pp; 104 volatile struct thread *td; 105 struct ucred *cred; 106 struct pgrp *pgrp; 107 char state[9]; 108 int np, rflag, sflag, dflag, lflag, wflag; 109 110 ps_mode = modif[0] == 'a' ? PRINT_ARGS : PRINT_NONE; 111 np = nprocs; 112 113 if (!LIST_EMPTY(&allproc)) 114 p = LIST_FIRST(&allproc); 115 else 116 p = &proc0; 117 118#ifdef __LP64__ 119 db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 120#else 121 db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 122#endif 123 while (--np >= 0 && !db_pager_quit) { 124 if (p == NULL) { 125 db_printf("oops, ran out of processes early!\n"); 126 break; 127 } 128 pp = p->p_pptr; 129 if (pp == NULL) 130 pp = p; 131 132 cred = p->p_ucred; 133 pgrp = p->p_pgrp; 134 db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid, 135 pgrp != NULL ? pgrp->pg_id : 0, 136 cred != NULL ? cred->cr_ruid : 0); 137 138 /* Determine our primary process state. */ 139 switch (p->p_state) { 140 case PRS_NORMAL: 141 if (P_SHOULDSTOP(p)) 142 state[0] = 'T'; 143 else { 144 /* 145 * One of D, L, R, S, W. For a 146 * multithreaded process we will use 147 * the state of the thread with the 148 * highest precedence. The 149 * precendence order from high to low 150 * is R, L, D, S, W. If no thread is 151 * in a sane state we use '?' for our 152 * primary state. 153 */ 154 rflag = sflag = dflag = lflag = wflag = 0; 155 FOREACH_THREAD_IN_PROC(p, td) { 156 if (td->td_state == TDS_RUNNING || 157 td->td_state == TDS_RUNQ || 158 td->td_state == TDS_CAN_RUN) 159 rflag++; 160 if (TD_ON_LOCK(td)) 161 lflag++; 162 if (TD_IS_SLEEPING(td)) { 163 if (!(td->td_flags & TDF_SINTR)) 164 dflag++; 165 else 166 sflag++; 167 } 168 if (TD_AWAITING_INTR(td)) 169 wflag++; 170 } 171 if (rflag) 172 state[0] = 'R'; 173 else if (lflag) 174 state[0] = 'L'; 175 else if (dflag) 176 state[0] = 'D'; 177 else if (sflag) 178 state[0] = 'S'; 179 else if (wflag) 180 state[0] = 'W'; 181 else 182 state[0] = '?'; 183 } 184 break; 185 case PRS_NEW: 186 state[0] = 'N'; 187 break; 188 case PRS_ZOMBIE: 189 state[0] = 'Z'; 190 break; 191 default: 192 state[0] = 'U'; 193 break; 194 } 195 state[1] = '\0'; 196 197 /* Additional process state flags. */ 198 if (!(p->p_flag & P_INMEM)) 199 strlcat(state, "W", sizeof(state)); 200 if (p->p_flag & P_TRACED) 201 strlcat(state, "X", sizeof(state)); 202 if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 203 strlcat(state, "E", sizeof(state)); 204 if (p->p_flag & P_PPWAIT) 205 strlcat(state, "V", sizeof(state)); 206 if (p->p_flag & P_SYSTEM || p->p_lock > 0) 207 strlcat(state, "L", sizeof(state)); 208 if (p->p_pgrp != NULL && p->p_session != NULL && 209 SESS_LEADER(p)) 210 strlcat(state, "s", sizeof(state)); 211 /* Cheated here and didn't compare pgid's. */ 212 if (p->p_flag & P_CONTROLT) 213 strlcat(state, "+", sizeof(state)); 214 if (cred != NULL && jailed(cred)) 215 strlcat(state, "J", sizeof(state)); 216 db_printf(" %-6.6s ", state); 217 if (p->p_flag & P_HADTHREADS) { 218#ifdef __LP64__ 219 db_printf(" (threaded) "); 220#else 221 db_printf(" (threaded) "); 222#endif 223 if (p->p_flag & P_SYSTEM) 224 db_printf("["); 225 db_printf("%s", p->p_comm); 226 if (p->p_flag & P_SYSTEM) 227 db_printf("]"); 228 if (ps_mode == PRINT_ARGS) { 229 db_printf(" "); 230 dump_args(p); 231 } 232 db_printf("\n"); 233 } 234 FOREACH_THREAD_IN_PROC(p, td) { 235 dumpthread(p, td, p->p_flag & P_HADTHREADS); 236 if (db_pager_quit) 237 break; 238 } 239 240 p = LIST_NEXT(p, p_list); 241 if (p == NULL && np > 0) 242 p = LIST_FIRST(&zombproc); 243 } 244} 245 246static void 247dumpthread(volatile struct proc *p, volatile struct thread *td, int all) 248{ 249 char state[9], wprefix; 250 const char *wmesg; 251 void *wchan; 252 253 if (all) { 254 db_printf("%6d ", td->td_tid); 255 switch (td->td_state) { 256 case TDS_RUNNING: 257 snprintf(state, sizeof(state), "Run"); 258 break; 259 case TDS_RUNQ: 260 snprintf(state, sizeof(state), "RunQ"); 261 break; 262 case TDS_CAN_RUN: 263 snprintf(state, sizeof(state), "CanRun"); 264 break; 265 case TDS_INACTIVE: 266 snprintf(state, sizeof(state), "Inactv"); 267 break; 268 case TDS_INHIBITED: 269 state[0] = '\0'; 270 if (TD_ON_LOCK(td)) 271 strlcat(state, "L", sizeof(state)); 272 if (TD_IS_SLEEPING(td)) { 273 if (td->td_flags & TDF_SINTR) 274 strlcat(state, "S", sizeof(state)); 275 else 276 strlcat(state, "D", sizeof(state)); 277 } 278 if (TD_IS_SWAPPED(td)) 279 strlcat(state, "W", sizeof(state)); 280 if (TD_AWAITING_INTR(td)) 281 strlcat(state, "I", sizeof(state)); 282 if (TD_IS_SUSPENDED(td)) 283 strlcat(state, "s", sizeof(state)); 284 if (state[0] != '\0') 285 break; 286 default: 287 snprintf(state, sizeof(state), "???"); 288 } 289 db_printf(" %-6.6s ", state); 290 } 291 wprefix = ' '; 292 if (TD_ON_LOCK(td)) { 293 wprefix = '*'; 294 wmesg = td->td_lockname; 295 wchan = td->td_blocked; 296 } else if (TD_ON_SLEEPQ(td)) { 297 wmesg = td->td_wmesg; 298 wchan = td->td_wchan; 299 } else if (TD_IS_RUNNING(td)) { 300 snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 301 wmesg = state; 302 wchan = NULL; 303 } else { 304 wmesg = ""; 305 wchan = NULL; 306 } 307 db_printf("%c%-8.8s ", wprefix, wmesg); 308 if (wchan == NULL) 309#ifdef __LP64__ 310 db_printf("%18s ", ""); 311#else 312 db_printf("%10s ", ""); 313#endif 314 else 315 db_printf("%p ", wchan); 316 if (p->p_flag & P_SYSTEM) 317 db_printf("["); 318 if (td->td_name[0] != '\0') 319 db_printf("%s", td->td_name); 320 else 321 db_printf("%s", td->td_proc->p_comm); 322 if (p->p_flag & P_SYSTEM) 323 db_printf("]"); 324 if (ps_mode == PRINT_ARGS && all == 0) { 325 db_printf(" "); 326 dump_args(p); 327 } 328 db_printf("\n"); 329} 330 331DB_SHOW_COMMAND(thread, db_show_thread) 332{ 333 struct thread *td; 334 struct lock_object *lock; 335 boolean_t comma; 336 337 /* Determine which thread to examine. */ 338 if (have_addr) 339 td = db_lookup_thread(addr, FALSE); 340 else 341 td = kdb_thread; 342 lock = (struct lock_object *)td->td_lock; 343 344 db_printf("Thread %d at %p:\n", td->td_tid, td); 345 db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc); 346 if (td->td_name[0] != '\0') 347 db_printf(" name: %s\n", td->td_name); 348 db_printf(" stack: %p-%p\n", (void *)td->td_kstack, 349 (void *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 1)); 350 db_printf(" flags: %#x ", td->td_flags); 351 db_printf(" pflags: %#x\n", td->td_pflags); 352 db_printf(" state: "); 353 switch (td->td_state) { 354 case TDS_INACTIVE: 355 db_printf("INACTIVE\n"); 356 break; 357 case TDS_CAN_RUN: 358 db_printf("CAN RUN\n"); 359 break; 360 case TDS_RUNQ: 361 db_printf("RUNQ\n"); 362 break; 363 case TDS_RUNNING: 364 db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 365 break; 366 case TDS_INHIBITED: 367 db_printf("INHIBITED: {"); 368 comma = FALSE; 369 if (TD_IS_SLEEPING(td)) { 370 db_printf("SLEEPING"); 371 comma = TRUE; 372 } 373 if (TD_IS_SUSPENDED(td)) { 374 if (comma) 375 db_printf(", "); 376 db_printf("SUSPENDED"); 377 comma = TRUE; 378 } 379 if (TD_IS_SWAPPED(td)) { 380 if (comma) 381 db_printf(", "); 382 db_printf("SWAPPED"); 383 comma = TRUE; 384 } 385 if (TD_ON_LOCK(td)) { 386 if (comma) 387 db_printf(", "); 388 db_printf("LOCK"); 389 comma = TRUE; 390 } 391 if (TD_AWAITING_INTR(td)) { 392 if (comma) 393 db_printf(", "); 394 db_printf("IWAIT"); 395 } 396 db_printf("}\n"); 397 break; 398 default: 399 db_printf("??? (%#x)\n", td->td_state); 400 break; 401 } 402 if (TD_ON_LOCK(td)) 403 db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 404 td->td_blocked); 405 if (TD_ON_SLEEPQ(td)) 406 db_printf( 407 " wmesg: %s wchan: %p sleeptimo %lx. %jx (curr %lx. %jx)\n", 408 td->td_wmesg, td->td_wchan, 409 (long)sbttobt(td->td_sleeptimo).sec, 410 (uintmax_t)sbttobt(td->td_sleeptimo).frac, 411 (long)sbttobt(sbinuptime()).sec, 412 (uintmax_t)sbttobt(sbinuptime()).frac); 413 db_printf(" priority: %d\n", td->td_priority); 414 db_printf(" container lock: %s (%p)\n", lock->lo_name, lock); 415} 416 417DB_SHOW_COMMAND(proc, db_show_proc) 418{ 419 struct thread *td; 420 struct proc *p; 421 int i; 422 423 /* Determine which process to examine. */ 424 if (have_addr) 425 p = db_lookup_proc(addr); 426 else 427 p = kdb_thread->td_proc; 428 429 db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 430 db_printf(" state: "); 431 switch (p->p_state) { 432 case PRS_NEW: 433 db_printf("NEW\n"); 434 break; 435 case PRS_NORMAL: 436 db_printf("NORMAL\n"); 437 break; 438 case PRS_ZOMBIE: 439 db_printf("ZOMBIE\n"); 440 break; 441 default: 442 db_printf("??? (%#x)\n", p->p_state); 443 } 444 if (p->p_ucred != NULL) { 445 db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 446 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 447 db_printf("%d", p->p_ucred->cr_groups[i]); 448 if (i < (p->p_ucred->cr_ngroups - 1)) 449 db_printf(", "); 450 } 451 db_printf("\n"); 452 } 453 if (p->p_pptr != NULL) 454 db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 455 p->p_pptr); 456 if (p->p_leader != NULL && p->p_leader != p) 457 db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 458 p->p_leader); 459 if (p->p_sysent != NULL) 460 db_printf(" ABI: %s\n", p->p_sysent->sv_name); 461 if (p->p_args != NULL) { 462 db_printf(" arguments: "); 463 dump_args(p); 464 db_printf("\n"); 465 } 466 db_printf(" threads: %d\n", p->p_numthreads); 467 FOREACH_THREAD_IN_PROC(p, td) { 468 dumpthread(p, td, 1); 469 if (db_pager_quit) 470 break; 471 } 472} 473 474void 475db_findstack_cmd(db_expr_t addr, boolean_t have_addr, 476 db_expr_t dummy3 __unused, char *dummy4 __unused) 477{ 478 struct proc *p; 479 struct thread *td; 480 struct kstack_cache_entry *ks_ce; 481 vm_offset_t saddr; 482 483 if (have_addr) 484 saddr = addr; 485 else { 486 db_printf("Usage: findstack <address>\n"); 487 return; 488 } 489 490 FOREACH_PROC_IN_SYSTEM(p) { 491 FOREACH_THREAD_IN_PROC(p, td) { 492 if (td->td_kstack <= saddr && saddr < td->td_kstack + 493 PAGE_SIZE * td->td_kstack_pages) { 494 db_printf("Thread %p\n", td); 495 return; 496 } 497 } 498 } 499 500 for (ks_ce = kstack_cache; ks_ce != NULL; 501 ks_ce = ks_ce->next_ks_entry) { 502 if ((vm_offset_t)ks_ce <= saddr && saddr < (vm_offset_t)ks_ce + 503 PAGE_SIZE * KSTACK_PAGES) { 504 db_printf("Cached stack %p\n", ks_ce); 505 return; 506 } 507 } 508} 509