xref: /freebsd/sys/ddb/db_thread.c (revision d605beaaa8ed9a27a640c51547f1c776347a0d66)
1dd3cb568SWarner Losh /*-
237224cd3SMarcel Moolenaar  * Copyright (c) 2004 Marcel Moolenaar
337224cd3SMarcel Moolenaar  * All rights reserved.
437224cd3SMarcel Moolenaar  *
537224cd3SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
637224cd3SMarcel Moolenaar  * modification, are permitted provided that the following conditions
737224cd3SMarcel Moolenaar  * are met:
837224cd3SMarcel Moolenaar  *
937224cd3SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
1037224cd3SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
1137224cd3SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
1237224cd3SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
1337224cd3SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
1437224cd3SMarcel Moolenaar  *
1537224cd3SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1637224cd3SMarcel Moolenaar  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1737224cd3SMarcel Moolenaar  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1837224cd3SMarcel Moolenaar  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1937224cd3SMarcel Moolenaar  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2037224cd3SMarcel Moolenaar  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2137224cd3SMarcel Moolenaar  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2237224cd3SMarcel Moolenaar  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2337224cd3SMarcel Moolenaar  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2437224cd3SMarcel Moolenaar  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2537224cd3SMarcel Moolenaar  */
2637224cd3SMarcel Moolenaar 
2737224cd3SMarcel Moolenaar #include <sys/cdefs.h>
2837224cd3SMarcel Moolenaar __FBSDID("$FreeBSD$");
2937224cd3SMarcel Moolenaar 
3037224cd3SMarcel Moolenaar #include <sys/param.h>
3137224cd3SMarcel Moolenaar #include <sys/systm.h>
3237224cd3SMarcel Moolenaar #include <sys/kdb.h>
3337224cd3SMarcel Moolenaar #include <sys/proc.h>
3437224cd3SMarcel Moolenaar 
3537224cd3SMarcel Moolenaar #include <machine/pcb.h>
3637224cd3SMarcel Moolenaar 
3737224cd3SMarcel Moolenaar #include <ddb/ddb.h>
3837224cd3SMarcel Moolenaar #include <ddb/db_command.h>
3937224cd3SMarcel Moolenaar #include <ddb/db_sym.h>
4037224cd3SMarcel Moolenaar 
41d605beaaSJohn Baldwin static db_expr_t hex2dec(db_expr_t expr);
42d605beaaSJohn Baldwin 
4337224cd3SMarcel Moolenaar void
4437224cd3SMarcel Moolenaar db_print_thread(void)
4537224cd3SMarcel Moolenaar {
462afce774SRobert Watson 	pid_t pid;
472afce774SRobert Watson 
482afce774SRobert Watson 	pid = -1;
492afce774SRobert Watson 	if (kdb_thread->td_proc != NULL)
502afce774SRobert Watson 		pid = kdb_thread->td_proc->p_pid;
512afce774SRobert Watson 	db_printf("[thread pid %d tid %ld ]\n", pid, (long)kdb_thread->td_tid);
5237224cd3SMarcel Moolenaar }
5337224cd3SMarcel Moolenaar 
5437224cd3SMarcel Moolenaar void
5537224cd3SMarcel Moolenaar db_set_thread(db_expr_t tid, boolean_t hastid, db_expr_t cnt, char *mod)
5637224cd3SMarcel Moolenaar {
5737224cd3SMarcel Moolenaar 	struct thread *thr;
5837224cd3SMarcel Moolenaar 	db_expr_t radix;
5937224cd3SMarcel Moolenaar 	int err;
6037224cd3SMarcel Moolenaar 
6137224cd3SMarcel Moolenaar 	/*
6237224cd3SMarcel Moolenaar 	 * We parse our own arguments. We don't like the default radix.
6337224cd3SMarcel Moolenaar 	 */
6437224cd3SMarcel Moolenaar 	radix = db_radix;
6537224cd3SMarcel Moolenaar 	db_radix = 10;
6637224cd3SMarcel Moolenaar 	hastid = db_expression(&tid);
6737224cd3SMarcel Moolenaar 	db_radix = radix;
6837224cd3SMarcel Moolenaar 	db_skip_to_eol();
6937224cd3SMarcel Moolenaar 
7037224cd3SMarcel Moolenaar 	if (hastid) {
7137224cd3SMarcel Moolenaar 		thr = kdb_thr_lookup(tid);
7237224cd3SMarcel Moolenaar 		if (thr != NULL) {
7337224cd3SMarcel Moolenaar 			err = kdb_thr_select(thr);
7437224cd3SMarcel Moolenaar 			if (err != 0) {
7537224cd3SMarcel Moolenaar 				db_printf("unable to switch to thread %ld\n",
7637224cd3SMarcel Moolenaar 				    (long)thr->td_tid);
7737224cd3SMarcel Moolenaar 				return;
7837224cd3SMarcel Moolenaar 			}
7937224cd3SMarcel Moolenaar 			db_dot = PC_REGS();
8037224cd3SMarcel Moolenaar 		} else {
8137224cd3SMarcel Moolenaar 			db_printf("%d: invalid thread\n", (int)tid);
8237224cd3SMarcel Moolenaar 			return;
8337224cd3SMarcel Moolenaar 		}
8437224cd3SMarcel Moolenaar 	}
8537224cd3SMarcel Moolenaar 
8637224cd3SMarcel Moolenaar 	db_print_thread();
8737224cd3SMarcel Moolenaar 	db_print_loc_and_inst(PC_REGS());
8837224cd3SMarcel Moolenaar }
8937224cd3SMarcel Moolenaar 
9037224cd3SMarcel Moolenaar void
9137224cd3SMarcel Moolenaar db_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod)
9237224cd3SMarcel Moolenaar {
9337224cd3SMarcel Moolenaar 	jmp_buf jb;
9437224cd3SMarcel Moolenaar 	void *prev_jb;
9537224cd3SMarcel Moolenaar 	struct thread *thr;
9637224cd3SMarcel Moolenaar 	int pager_quit;
9737224cd3SMarcel Moolenaar 
98d39d4a6eSJohn Baldwin 	db_setup_paging(db_simple_pager, &pager_quit, db_lines_per_page);
9937224cd3SMarcel Moolenaar 
10037224cd3SMarcel Moolenaar 	pager_quit = 0;
10137224cd3SMarcel Moolenaar 	thr = kdb_thr_first();
10237224cd3SMarcel Moolenaar 	while (!pager_quit && thr != NULL) {
10337224cd3SMarcel Moolenaar 		db_printf("  %6ld (%p)  ", (long)thr->td_tid, thr);
10437224cd3SMarcel Moolenaar 		prev_jb = kdb_jmpbuf(jb);
10537224cd3SMarcel Moolenaar 		if (setjmp(jb) == 0) {
10637224cd3SMarcel Moolenaar 			if (db_trace_thread(thr, 1) != 0)
10737224cd3SMarcel Moolenaar 				db_printf("***\n");
10837224cd3SMarcel Moolenaar 		}
10937224cd3SMarcel Moolenaar 		kdb_jmpbuf(prev_jb);
11037224cd3SMarcel Moolenaar 		thr = kdb_thr_next(thr);
11137224cd3SMarcel Moolenaar 	}
11237224cd3SMarcel Moolenaar }
113d605beaaSJohn Baldwin 
114d605beaaSJohn Baldwin /*
115d605beaaSJohn Baldwin  * Take the parsed expression value from the command line that was parsed
116d605beaaSJohn Baldwin  * as a hexadecimal value and convert it as if the expression was parsed
117d605beaaSJohn Baldwin  * as a decimal value.  Returns -1 if the expression was not a valid
118d605beaaSJohn Baldwin  * decimal value.
119d605beaaSJohn Baldwin  */
120d605beaaSJohn Baldwin static db_expr_t
121d605beaaSJohn Baldwin hex2dec(db_expr_t expr)
122d605beaaSJohn Baldwin {
123d605beaaSJohn Baldwin 	uintptr_t x, y;
124d605beaaSJohn Baldwin 	db_expr_t val;
125d605beaaSJohn Baldwin 
126d605beaaSJohn Baldwin 	y = 1;
127d605beaaSJohn Baldwin 	val = 0;
128d605beaaSJohn Baldwin 	x = expr;
129d605beaaSJohn Baldwin 	while (x != 0) {
130d605beaaSJohn Baldwin 		if (x % 16 > 9)
131d605beaaSJohn Baldwin 			return (-1);
132d605beaaSJohn Baldwin 		val += (x % 16) * (y);
133d605beaaSJohn Baldwin 		x >>= 4;
134d605beaaSJohn Baldwin 		y *= 10;
135d605beaaSJohn Baldwin 	}
136d605beaaSJohn Baldwin 	return (val);
137d605beaaSJohn Baldwin }
138d605beaaSJohn Baldwin 
139d605beaaSJohn Baldwin /*
140d605beaaSJohn Baldwin  * Lookup a thread based on a db expression address.  We assume that the
141d605beaaSJohn Baldwin  * address was parsed in hexadecimal.  We reparse the address in decimal
142d605beaaSJohn Baldwin  * first and try to treat it as a thread ID to find an associated thread.
143d605beaaSJohn Baldwin  * If that fails and check_pid is true, we terat the decimal value as a
144d605beaaSJohn Baldwin  * PID.  If that matches a process, we return the first thread in that
145d605beaaSJohn Baldwin  * process.  Otherwise, we treat the addr as a pointer to a thread.
146d605beaaSJohn Baldwin  */
147d605beaaSJohn Baldwin struct thread *
148d605beaaSJohn Baldwin db_lookup_thread(db_expr_t addr, boolean_t check_pid)
149d605beaaSJohn Baldwin {
150d605beaaSJohn Baldwin 	struct thread *td;
151d605beaaSJohn Baldwin 	db_expr_t decaddr;
152d605beaaSJohn Baldwin 	struct proc *p;
153d605beaaSJohn Baldwin 
154d605beaaSJohn Baldwin 	/*
155d605beaaSJohn Baldwin 	 * If the parsed address was not a valid decimal expression,
156d605beaaSJohn Baldwin 	 * assume it is a thread pointer.
157d605beaaSJohn Baldwin 	 */
158d605beaaSJohn Baldwin 	decaddr = hex2dec(addr);
159d605beaaSJohn Baldwin 	if (decaddr == -1)
160d605beaaSJohn Baldwin 		return ((struct thread *)addr);
161d605beaaSJohn Baldwin 
162d605beaaSJohn Baldwin 	td = kdb_thr_lookup(decaddr);
163d605beaaSJohn Baldwin 	if (td != NULL)
164d605beaaSJohn Baldwin 		return (td);
165d605beaaSJohn Baldwin 	if (check_pid) {
166d605beaaSJohn Baldwin 		LIST_FOREACH(p, &allproc, p_list) {
167d605beaaSJohn Baldwin 			if (p->p_pid == decaddr)
168d605beaaSJohn Baldwin 				return (FIRST_THREAD_IN_PROC(p));
169d605beaaSJohn Baldwin 		}
170d605beaaSJohn Baldwin 		LIST_FOREACH(p, &zombproc, p_list) {
171d605beaaSJohn Baldwin 			if (p->p_pid == decaddr)
172d605beaaSJohn Baldwin 				return (FIRST_THREAD_IN_PROC(p));
173d605beaaSJohn Baldwin 		}
174d605beaaSJohn Baldwin 	}
175d605beaaSJohn Baldwin 	return ((struct thread *)addr);
176d605beaaSJohn Baldwin }
177d605beaaSJohn Baldwin 
178d605beaaSJohn Baldwin /*
179d605beaaSJohn Baldwin  * Lookup a process based on a db expression address.  We assume that the
180d605beaaSJohn Baldwin  * address was parsed in hexadecimal.  We reparse the address in decimal
181d605beaaSJohn Baldwin  * first and try to treat it as a PID to find an associated process.
182d605beaaSJohn Baldwin  * If that fails we treat the addr as a pointer to a process.
183d605beaaSJohn Baldwin  */
184d605beaaSJohn Baldwin struct proc *
185d605beaaSJohn Baldwin db_lookup_proc(db_expr_t addr)
186d605beaaSJohn Baldwin {
187d605beaaSJohn Baldwin 	db_expr_t decaddr;
188d605beaaSJohn Baldwin 	struct proc *p;
189d605beaaSJohn Baldwin 
190d605beaaSJohn Baldwin 	decaddr = hex2dec(addr);
191d605beaaSJohn Baldwin 	if (decaddr != -1) {
192d605beaaSJohn Baldwin 		LIST_FOREACH(p, &allproc, p_list) {
193d605beaaSJohn Baldwin 			if (p->p_pid == decaddr)
194d605beaaSJohn Baldwin 				return (p);
195d605beaaSJohn Baldwin 		}
196d605beaaSJohn Baldwin 		LIST_FOREACH(p, &zombproc, p_list) {
197d605beaaSJohn Baldwin 			if (p->p_pid == decaddr)
198d605beaaSJohn Baldwin 				return (p);
199d605beaaSJohn Baldwin 		}
200d605beaaSJohn Baldwin 	}
201d605beaaSJohn Baldwin 	return ((struct proc *)addr);
202d605beaaSJohn Baldwin }
203