12322Sdg/*- 22322Sdg * Copyright (c) 1993 The Regents of the University of California. 32322Sdg * All rights reserved. 42322Sdg * 52322Sdg * Redistribution and use in source and binary forms, with or without 62322Sdg * modification, are permitted provided that the following conditions 72322Sdg * are met: 82322Sdg * 1. Redistributions of source code must retain the above copyright 92322Sdg * notice, this list of conditions and the following disclaimer. 102322Sdg * 2. Redistributions in binary form must reproduce the above copyright 112322Sdg * notice, this list of conditions and the following disclaimer in the 122322Sdg * documentation and/or other materials provided with the distribution. 132322Sdg * 4. Neither the name of the University nor the names of its contributors 142322Sdg * may be used to endorse or promote products derived from this software 152322Sdg * without specific prior written permission. 162322Sdg * 172322Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 182322Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 192322Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 202322Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 212322Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 222322Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 232322Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 242322Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 252322Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 262322Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 272322Sdg * SUCH DAMAGE. 282322Sdg */ 29116176Sobrien 30116176Sobrien#include <sys/cdefs.h> 31116176Sobrien__FBSDID("$FreeBSD$"); 32116176Sobrien 332322Sdg#include <sys/param.h> 34158092Sjhb#include <sys/cons.h> 35158032Sjhb#include <sys/jail.h> 36158032Sjhb#include <sys/kdb.h> 372322Sdg#include <sys/proc.h> 38158032Sjhb#include <sys/sysent.h> 39158092Sjhb#include <sys/systm.h> 40228569Skib#include <sys/_kstack_cache.h> 41108338Sjulian#include <vm/vm.h> 42108338Sjulian#include <vm/vm_param.h> 43108338Sjulian#include <vm/pmap.h> 4412734Sbde 4512734Sbde#include <ddb/ddb.h> 4612734Sbde 47158032Sjhbstatic void dumpthread(volatile struct proc *p, volatile struct thread *td, 48158032Sjhb int all); 49177615Ssam/* 50177615Ssam * At least one non-optional show-command must be implemented using 51177615Ssam * DB_SHOW_ALL_COMMAND() so that db_show_all_cmd_set gets created. 52177615Ssam * Here is one. 53177615Ssam */ 54177615SsamDB_SHOW_ALL_COMMAND(procs, db_procs_cmd) 55177615Ssam{ 56177615Ssam db_ps(addr, have_addr, count, modif); 57177615Ssam} 58158032Sjhb 59158032Sjhb/* 60158032Sjhb * Layout: 61158032Sjhb * - column counts 62158032Sjhb * - header 63158032Sjhb * - single-threaded process 64158032Sjhb * - multi-threaded process 65158032Sjhb * - thread in a MT process 66158032Sjhb * 67158032Sjhb * 1 2 3 4 5 6 7 68158032Sjhb * 1234567890123456789012345678901234567890123456789012345678901234567890 69160893Sjhb * pid ppid pgrp uid state wmesg wchan cmd 70160893Sjhb * <pid> <ppi> <pgi> <uid> <stat> < wmesg > < wchan > <name> 71160893Sjhb * <pid> <ppi> <pgi> <uid> <stat> (threaded) <command> 72160893Sjhb * <tid > <stat> < wmesg > < wchan > <name> 73158032Sjhb * 74158032Sjhb * For machines with 64-bit pointers, we expand the wchan field 8 more 75158032Sjhb * characters. 76158032Sjhb */ 772322Sdgvoid 78158032Sjhbdb_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 7910349Sbde{ 8010128Sdg volatile struct proc *p, *pp; 8185207Sjhb volatile struct thread *td; 82158032Sjhb struct ucred *cred; 83158032Sjhb struct pgrp *pgrp; 84158032Sjhb char state[9]; 85160312Sjhb int np, rflag, sflag, dflag, lflag, wflag; 8610128Sdg 872322Sdg np = nprocs; 882322Sdg 8970527Sphk if (!LIST_EMPTY(&allproc)) 9070527Sphk p = LIST_FIRST(&allproc); 9110128Sdg else 9210128Sdg p = &proc0; 9310128Sdg 94158456Sjhb#ifdef __LP64__ 95160893Sjhb db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 96158032Sjhb#else 97160893Sjhb db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 98158032Sjhb#endif 99160312Sjhb while (--np >= 0 && !db_pager_quit) { 10016381Speter if (p == NULL) { 101158032Sjhb db_printf("oops, ran out of processes early!\n"); 10216381Speter break; 10316381Speter } 1042322Sdg pp = p->p_pptr; 10510128Sdg if (pp == NULL) 1062322Sdg pp = p; 10710128Sdg 108158032Sjhb cred = p->p_ucred; 109158032Sjhb pgrp = p->p_pgrp; 110160878Sjhb db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid, 111160878Sjhb pgrp != NULL ? pgrp->pg_id : 0, 112160878Sjhb cred != NULL ? cred->cr_ruid : 0); 11399072Sjulian 114158032Sjhb /* Determine our primary process state. */ 115158091Sjhb switch (p->p_state) { 11699072Sjulian case PRS_NORMAL: 11799072Sjulian if (P_SHOULDSTOP(p)) 118158032Sjhb state[0] = 'T'; 119158032Sjhb else { 120158032Sjhb /* 121158032Sjhb * One of D, L, R, S, W. For a 122158032Sjhb * multithreaded process we will use 123158032Sjhb * the state of the thread with the 124158032Sjhb * highest precedence. The 125158032Sjhb * precendence order from high to low 126158032Sjhb * is R, L, D, S, W. If no thread is 127158032Sjhb * in a sane state we use '?' for our 128158032Sjhb * primary state. 129158032Sjhb */ 130158032Sjhb rflag = sflag = dflag = lflag = wflag = 0; 131158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 132158032Sjhb if (td->td_state == TDS_RUNNING || 133158032Sjhb td->td_state == TDS_RUNQ || 134158032Sjhb td->td_state == TDS_CAN_RUN) 135158032Sjhb rflag++; 136158032Sjhb if (TD_ON_LOCK(td)) 137158032Sjhb lflag++; 138158032Sjhb if (TD_IS_SLEEPING(td)) { 139201794Strasz if (!(td->td_flags & TDF_SINTR)) 140158032Sjhb dflag++; 141158032Sjhb else 142158032Sjhb sflag++; 143158032Sjhb } 144158032Sjhb if (TD_AWAITING_INTR(td)) 145158032Sjhb wflag++; 146158032Sjhb } 147158032Sjhb if (rflag) 148158032Sjhb state[0] = 'R'; 149158032Sjhb else if (lflag) 150158032Sjhb state[0] = 'L'; 151158032Sjhb else if (dflag) 152158032Sjhb state[0] = 'D'; 153158032Sjhb else if (sflag) 154158032Sjhb state[0] = 'S'; 155158032Sjhb else if (wflag) 156158032Sjhb state[0] = 'W'; 157158032Sjhb else 158158032Sjhb state[0] = '?'; 159158032Sjhb } 16099072Sjulian break; 16199072Sjulian case PRS_NEW: 162158032Sjhb state[0] = 'N'; 16399072Sjulian break; 16499072Sjulian case PRS_ZOMBIE: 165158032Sjhb state[0] = 'Z'; 16699072Sjulian break; 16799072Sjulian default: 168158032Sjhb state[0] = 'U'; 16999072Sjulian break; 17099072Sjulian } 171158032Sjhb state[1] = '\0'; 172158032Sjhb 173158032Sjhb /* Additional process state flags. */ 174201794Strasz if (!(p->p_flag & P_INMEM)) 175158032Sjhb strlcat(state, "W", sizeof(state)); 176158032Sjhb if (p->p_flag & P_TRACED) 177158032Sjhb strlcat(state, "X", sizeof(state)); 178158032Sjhb if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 179158032Sjhb strlcat(state, "E", sizeof(state)); 180158032Sjhb if (p->p_flag & P_PPWAIT) 181158032Sjhb strlcat(state, "V", sizeof(state)); 182158032Sjhb if (p->p_flag & P_SYSTEM || p->p_lock > 0) 183158032Sjhb strlcat(state, "L", sizeof(state)); 184158032Sjhb if (p->p_session != NULL && SESS_LEADER(p)) 185158032Sjhb strlcat(state, "s", sizeof(state)); 186158032Sjhb /* Cheated here and didn't compare pgid's. */ 187158032Sjhb if (p->p_flag & P_CONTROLT) 188158032Sjhb strlcat(state, "+", sizeof(state)); 189158032Sjhb if (cred != NULL && jailed(cred)) 190158032Sjhb strlcat(state, "J", sizeof(state)); 191158032Sjhb db_printf(" %-6.6s ", state); 192197684Sjhb if (p->p_flag & P_HADTHREADS) { 193158456Sjhb#ifdef __LP64__ 194197684Sjhb db_printf(" (threaded) "); 195158032Sjhb#else 196197684Sjhb db_printf(" (threaded) "); 197158032Sjhb#endif 198197684Sjhb if (p->p_flag & P_SYSTEM) 199197684Sjhb db_printf("["); 200197684Sjhb db_printf("%s", p->p_comm); 201197684Sjhb if (p->p_flag & P_SYSTEM) 202197684Sjhb db_printf("]"); 203197684Sjhb db_printf("\n"); 204197684Sjhb } 205103216Sjulian FOREACH_THREAD_IN_PROC(p, td) { 206158032Sjhb dumpthread(p, td, p->p_flag & P_HADTHREADS); 207160312Sjhb if (db_pager_quit) 208118269Sjhb break; 2092322Sdg } 21094456Sjhb 21170527Sphk p = LIST_NEXT(p, p_list); 21210128Sdg if (p == NULL && np > 0) 21370527Sphk p = LIST_FIRST(&zombproc); 2142322Sdg } 2152322Sdg} 216115903Sjhb 217108338Sjulianstatic void 218158032Sjhbdumpthread(volatile struct proc *p, volatile struct thread *td, int all) 219108338Sjulian{ 220158032Sjhb char state[9], wprefix; 221158032Sjhb const char *wmesg; 222158032Sjhb void *wchan; 223158032Sjhb 224158032Sjhb if (all) { 225160878Sjhb db_printf("%6d ", td->td_tid); 226158032Sjhb switch (td->td_state) { 227158032Sjhb case TDS_RUNNING: 228158032Sjhb snprintf(state, sizeof(state), "Run"); 229158032Sjhb break; 230158032Sjhb case TDS_RUNQ: 231158032Sjhb snprintf(state, sizeof(state), "RunQ"); 232158032Sjhb break; 233158032Sjhb case TDS_CAN_RUN: 234158032Sjhb snprintf(state, sizeof(state), "CanRun"); 235158032Sjhb break; 236158032Sjhb case TDS_INACTIVE: 237158032Sjhb snprintf(state, sizeof(state), "Inactv"); 238158032Sjhb break; 239158032Sjhb case TDS_INHIBITED: 240158032Sjhb state[0] = '\0'; 241158032Sjhb if (TD_ON_LOCK(td)) 242158032Sjhb strlcat(state, "L", sizeof(state)); 243158032Sjhb if (TD_IS_SLEEPING(td)) { 244158032Sjhb if (td->td_flags & TDF_SINTR) 245158032Sjhb strlcat(state, "S", sizeof(state)); 246158032Sjhb else 247158032Sjhb strlcat(state, "D", sizeof(state)); 248158032Sjhb } 249158032Sjhb if (TD_IS_SWAPPED(td)) 250158032Sjhb strlcat(state, "W", sizeof(state)); 251158032Sjhb if (TD_AWAITING_INTR(td)) 252158032Sjhb strlcat(state, "I", sizeof(state)); 253158032Sjhb if (TD_IS_SUSPENDED(td)) 254158032Sjhb strlcat(state, "s", sizeof(state)); 255158032Sjhb if (state[0] != '\0') 256158032Sjhb break; 257158032Sjhb default: 258158032Sjhb snprintf(state, sizeof(state), "???"); 259158032Sjhb } 260158032Sjhb db_printf(" %-6.6s ", state); 261158032Sjhb } 262158032Sjhb wprefix = ' '; 263158032Sjhb if (TD_ON_LOCK(td)) { 264158032Sjhb wprefix = '*'; 265158032Sjhb wmesg = td->td_lockname; 266158032Sjhb wchan = td->td_blocked; 267158032Sjhb } else if (TD_ON_SLEEPQ(td)) { 268158032Sjhb wmesg = td->td_wmesg; 269158032Sjhb wchan = td->td_wchan; 270158032Sjhb } else if (TD_IS_RUNNING(td)) { 271158032Sjhb snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 272158032Sjhb wmesg = state; 273158032Sjhb wchan = NULL; 274158032Sjhb } else { 275158032Sjhb wmesg = ""; 276158032Sjhb wchan = NULL; 277158032Sjhb } 278158032Sjhb db_printf("%c%-8.8s ", wprefix, wmesg); 279158032Sjhb if (wchan == NULL) 280158456Sjhb#ifdef __LP64__ 281158032Sjhb db_printf("%18s ", ""); 282158032Sjhb#else 283158032Sjhb db_printf("%10s ", ""); 284158032Sjhb#endif 285158032Sjhb else 286158032Sjhb db_printf("%p ", wchan); 287158032Sjhb if (p->p_flag & P_SYSTEM) 288158032Sjhb db_printf("["); 289158032Sjhb if (td->td_name[0] != '\0') 290158032Sjhb db_printf("%s", td->td_name); 291158032Sjhb else 292158032Sjhb db_printf("%s", td->td_proc->p_comm); 293158032Sjhb if (p->p_flag & P_SYSTEM) 294158032Sjhb db_printf("]"); 295158032Sjhb db_printf("\n"); 296158032Sjhb} 297118228Sjhb 298158032SjhbDB_SHOW_COMMAND(thread, db_show_thread) 299158032Sjhb{ 300158032Sjhb struct thread *td; 301179861Sattilio struct lock_object *lock; 302158032Sjhb boolean_t comma; 303158032Sjhb 304158032Sjhb /* Determine which thread to examine. */ 305158032Sjhb if (have_addr) 306158032Sjhb td = db_lookup_thread(addr, FALSE); 307158032Sjhb else 308158032Sjhb td = kdb_thread; 309179861Sattilio lock = (struct lock_object *)td->td_lock; 310158032Sjhb 311158032Sjhb db_printf("Thread %d at %p:\n", td->td_tid, td); 312163709Sjb db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc); 313158032Sjhb if (td->td_name[0] != '\0') 314158032Sjhb db_printf(" name: %s\n", td->td_name); 315172705Smarcel db_printf(" stack: %p-%p\n", (void *)td->td_kstack, 316172705Smarcel (void *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 1)); 317158032Sjhb db_printf(" flags: %#x ", td->td_flags); 318158032Sjhb db_printf(" pflags: %#x\n", td->td_pflags); 319158032Sjhb db_printf(" state: "); 320108338Sjulian switch (td->td_state) { 321158032Sjhb case TDS_INACTIVE: 322158032Sjhb db_printf("INACTIVE\n"); 323158032Sjhb break; 324158032Sjhb case TDS_CAN_RUN: 325158032Sjhb db_printf("CAN RUN\n"); 326158032Sjhb break; 327158032Sjhb case TDS_RUNQ: 328158032Sjhb db_printf("RUNQ\n"); 329158032Sjhb break; 330158032Sjhb case TDS_RUNNING: 331158032Sjhb db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 332158032Sjhb break; 333108338Sjulian case TDS_INHIBITED: 334158032Sjhb db_printf("INHIBITED: {"); 335158032Sjhb comma = FALSE; 336108338Sjulian if (TD_IS_SLEEPING(td)) { 337158032Sjhb db_printf("SLEEPING"); 338158032Sjhb comma = TRUE; 339108338Sjulian } 340108338Sjulian if (TD_IS_SUSPENDED(td)) { 341158032Sjhb if (comma) 342158032Sjhb db_printf(", "); 343158032Sjhb db_printf("SUSPENDED"); 344158032Sjhb comma = TRUE; 345108338Sjulian } 346158032Sjhb if (TD_IS_SWAPPED(td)) { 347158032Sjhb if (comma) 348158032Sjhb db_printf(", "); 349158032Sjhb db_printf("SWAPPED"); 350158032Sjhb comma = TRUE; 351158032Sjhb } 352158032Sjhb if (TD_ON_LOCK(td)) { 353158032Sjhb if (comma) 354158032Sjhb db_printf(", "); 355158032Sjhb db_printf("LOCK"); 356158032Sjhb comma = TRUE; 357158032Sjhb } 358108338Sjulian if (TD_AWAITING_INTR(td)) { 359158032Sjhb if (comma) 360158032Sjhb db_printf(", "); 361158032Sjhb db_printf("IWAIT"); 362108338Sjulian } 363158032Sjhb db_printf("}\n"); 364108338Sjulian break; 365158032Sjhb default: 366158032Sjhb db_printf("??? (%#x)\n", td->td_state); 367108338Sjulian break; 368158032Sjhb } 369158032Sjhb if (TD_ON_LOCK(td)) 370158032Sjhb db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 371158032Sjhb td->td_blocked); 372158032Sjhb if (TD_ON_SLEEPQ(td)) 373158032Sjhb db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 374158032Sjhb td->td_wchan); 375158032Sjhb db_printf(" priority: %d\n", td->td_priority); 376179861Sattilio db_printf(" container lock: %s (%p)\n", lock->lo_name, lock); 377158032Sjhb} 378158032Sjhb 379158032SjhbDB_SHOW_COMMAND(proc, db_show_proc) 380158032Sjhb{ 381158032Sjhb struct thread *td; 382158032Sjhb struct proc *p; 383160312Sjhb int i; 384158032Sjhb 385158032Sjhb /* Determine which process to examine. */ 386158032Sjhb if (have_addr) 387158032Sjhb p = db_lookup_proc(addr); 388158032Sjhb else 389158032Sjhb p = kdb_thread->td_proc; 390158032Sjhb 391158032Sjhb db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 392158032Sjhb db_printf(" state: "); 393158032Sjhb switch (p->p_state) { 394158032Sjhb case PRS_NEW: 395158032Sjhb db_printf("NEW\n"); 396108338Sjulian break; 397158032Sjhb case PRS_NORMAL: 398158032Sjhb db_printf("NORMAL\n"); 399108338Sjulian break; 400158032Sjhb case PRS_ZOMBIE: 401158032Sjhb db_printf("ZOMBIE\n"); 402115904Sjhb break; 403108338Sjulian default: 404158032Sjhb db_printf("??? (%#x)\n", p->p_state); 405108338Sjulian } 406158032Sjhb if (p->p_ucred != NULL) { 407158032Sjhb db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 408158032Sjhb for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 409158032Sjhb db_printf("%d", p->p_ucred->cr_groups[i]); 410158032Sjhb if (i < (p->p_ucred->cr_ngroups - 1)) 411158032Sjhb db_printf(", "); 412158032Sjhb } 413108338Sjulian db_printf("\n"); 414158032Sjhb } 415158032Sjhb if (p->p_pptr != NULL) 416158032Sjhb db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 417158032Sjhb p->p_pptr); 418158032Sjhb if (p->p_leader != NULL && p->p_leader != p) 419158032Sjhb db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 420158032Sjhb p->p_leader); 421158032Sjhb if (p->p_sysent != NULL) 422158032Sjhb db_printf(" ABI: %s\n", p->p_sysent->sv_name); 423158032Sjhb if (p->p_args != NULL) 424158032Sjhb db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 425158032Sjhb p->p_args->ar_args); 426158032Sjhb db_printf(" threads: %d\n", p->p_numthreads); 427158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 428158032Sjhb dumpthread(p, td, 1); 429160312Sjhb if (db_pager_quit) 430158032Sjhb break; 431158032Sjhb } 432108338Sjulian} 433228569Skib 434228569Skibvoid 435228569Skibdb_findstack_cmd(db_expr_t addr, boolean_t have_addr, 436228569Skib db_expr_t dummy3 __unused, char *dummy4 __unused) 437228569Skib{ 438228569Skib struct proc *p; 439228569Skib struct thread *td; 440228569Skib struct kstack_cache_entry *ks_ce; 441228569Skib vm_offset_t saddr; 442228569Skib 443228569Skib if (have_addr) 444228569Skib saddr = addr; 445228569Skib else { 446228569Skib db_printf("Usage: findstack <address>\n"); 447228569Skib return; 448228569Skib } 449228569Skib 450228687Spluknet FOREACH_PROC_IN_SYSTEM(p) { 451228569Skib FOREACH_THREAD_IN_PROC(p, td) { 452228569Skib if (td->td_kstack <= saddr && saddr < td->td_kstack + 453228569Skib PAGE_SIZE * td->td_kstack_pages) { 454228569Skib db_printf("Thread %p\n", td); 455228569Skib return; 456228569Skib } 457228569Skib } 458228569Skib } 459228569Skib 460228569Skib for (ks_ce = kstack_cache; ks_ce != NULL; 461228569Skib ks_ce = ks_ce->next_ks_entry) { 462228569Skib if ((vm_offset_t)ks_ce <= saddr && saddr < (vm_offset_t)ks_ce + 463228569Skib PAGE_SIZE * KSTACK_PAGES) { 464228569Skib db_printf("Cached stack %p\n", ks_ce); 465228569Skib return; 466228569Skib } 467228569Skib } 468228569Skib} 469