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