1139747Simp/*-
2131952Smarcel * Copyright (c) 2004 Marcel Moolenaar
3131952Smarcel * All rights reserved.
4131952Smarcel *
5131952Smarcel * Redistribution and use in source and binary forms, with or without
6131952Smarcel * modification, are permitted provided that the following conditions
7131952Smarcel * are met:
8131952Smarcel *
9131952Smarcel * 1. Redistributions of source code must retain the above copyright
10131952Smarcel *    notice, this list of conditions and the following disclaimer.
11131952Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12131952Smarcel *    notice, this list of conditions and the following disclaimer in the
13131952Smarcel *    documentation and/or other materials provided with the distribution.
14131952Smarcel *
15131952Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16131952Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17131952Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18131952Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19131952Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20131952Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21131952Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22131952Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23131952Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24131952Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25131952Smarcel */
26131952Smarcel
27131952Smarcel#include <sys/cdefs.h>
28131952Smarcel__FBSDID("$FreeBSD$");
29131952Smarcel
30131952Smarcel#include <sys/param.h>
31131952Smarcel#include <sys/systm.h>
32131952Smarcel#include <sys/kdb.h>
33131952Smarcel#include <sys/proc.h>
34131952Smarcel
35131952Smarcel#include <machine/pcb.h>
36131952Smarcel
37131952Smarcel#include <ddb/ddb.h>
38131952Smarcel#include <ddb/db_command.h>
39131952Smarcel#include <ddb/db_sym.h>
40131952Smarcel
41131952Smarcelvoid
42131952Smarceldb_print_thread(void)
43131952Smarcel{
44138037Srwatson	pid_t pid;
45138037Srwatson
46138037Srwatson	pid = -1;
47138037Srwatson	if (kdb_thread->td_proc != NULL)
48138037Srwatson		pid = kdb_thread->td_proc->p_pid;
49203804Srpaulo	db_printf("[ thread pid %d tid %ld ]\n", pid, (long)kdb_thread->td_tid);
50131952Smarcel}
51131952Smarcel
52131952Smarcelvoid
53131952Smarceldb_set_thread(db_expr_t tid, boolean_t hastid, db_expr_t cnt, char *mod)
54131952Smarcel{
55131952Smarcel	struct thread *thr;
56131952Smarcel	db_expr_t radix;
57131952Smarcel	int err;
58131952Smarcel
59131952Smarcel	/*
60131952Smarcel	 * We parse our own arguments. We don't like the default radix.
61131952Smarcel	 */
62131952Smarcel	radix = db_radix;
63131952Smarcel	db_radix = 10;
64131952Smarcel	hastid = db_expression(&tid);
65131952Smarcel	db_radix = radix;
66131952Smarcel	db_skip_to_eol();
67131952Smarcel
68131952Smarcel	if (hastid) {
69131952Smarcel		thr = kdb_thr_lookup(tid);
70131952Smarcel		if (thr != NULL) {
71131952Smarcel			err = kdb_thr_select(thr);
72131952Smarcel			if (err != 0) {
73131952Smarcel				db_printf("unable to switch to thread %ld\n",
74131952Smarcel				    (long)thr->td_tid);
75131952Smarcel				return;
76131952Smarcel			}
77131952Smarcel			db_dot = PC_REGS();
78131952Smarcel		} else {
79131952Smarcel			db_printf("%d: invalid thread\n", (int)tid);
80131952Smarcel			return;
81131952Smarcel		}
82131952Smarcel	}
83131952Smarcel
84131952Smarcel	db_print_thread();
85131952Smarcel	db_print_loc_and_inst(PC_REGS());
86131952Smarcel}
87131952Smarcel
88131952Smarcelvoid
89131952Smarceldb_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod)
90131952Smarcel{
91131952Smarcel	jmp_buf jb;
92131952Smarcel	void *prev_jb;
93131952Smarcel	struct thread *thr;
94131952Smarcel
95131952Smarcel	thr = kdb_thr_first();
96160312Sjhb	while (!db_pager_quit && thr != NULL) {
97228568Skib		db_printf("  %6ld (%p) (stack %p)  ", (long)thr->td_tid, thr,
98228568Skib		    (void *)thr->td_kstack);
99131952Smarcel		prev_jb = kdb_jmpbuf(jb);
100131952Smarcel		if (setjmp(jb) == 0) {
101131952Smarcel			if (db_trace_thread(thr, 1) != 0)
102131952Smarcel				db_printf("***\n");
103131952Smarcel		}
104131952Smarcel		kdb_jmpbuf(prev_jb);
105131952Smarcel		thr = kdb_thr_next(thr);
106131952Smarcel	}
107131952Smarcel}
108158029Sjhb
109158029Sjhb/*
110158029Sjhb * Lookup a thread based on a db expression address.  We assume that the
111158029Sjhb * address was parsed in hexadecimal.  We reparse the address in decimal
112158029Sjhb * first and try to treat it as a thread ID to find an associated thread.
113228376Skib * If that fails and check_pid is true, we treat the decimal value as a
114158029Sjhb * PID.  If that matches a process, we return the first thread in that
115158029Sjhb * process.  Otherwise, we treat the addr as a pointer to a thread.
116158029Sjhb */
117158029Sjhbstruct thread *
118158029Sjhbdb_lookup_thread(db_expr_t addr, boolean_t check_pid)
119158029Sjhb{
120158029Sjhb	struct thread *td;
121158029Sjhb	db_expr_t decaddr;
122158029Sjhb	struct proc *p;
123158029Sjhb
124158029Sjhb	/*
125158029Sjhb	 * If the parsed address was not a valid decimal expression,
126158029Sjhb	 * assume it is a thread pointer.
127158029Sjhb	 */
128208509Sbz	decaddr = db_hex2dec(addr);
129158029Sjhb	if (decaddr == -1)
130158029Sjhb		return ((struct thread *)addr);
131158029Sjhb
132158029Sjhb	td = kdb_thr_lookup(decaddr);
133158029Sjhb	if (td != NULL)
134158029Sjhb		return (td);
135158029Sjhb	if (check_pid) {
136166074Sdelphij		FOREACH_PROC_IN_SYSTEM(p) {
137158029Sjhb			if (p->p_pid == decaddr)
138158029Sjhb				return (FIRST_THREAD_IN_PROC(p));
139158029Sjhb		}
140158029Sjhb		LIST_FOREACH(p, &zombproc, p_list) {
141158029Sjhb			if (p->p_pid == decaddr)
142158029Sjhb				return (FIRST_THREAD_IN_PROC(p));
143158029Sjhb		}
144158029Sjhb	}
145158029Sjhb	return ((struct thread *)addr);
146158029Sjhb}
147158029Sjhb
148158029Sjhb/*
149158029Sjhb * Lookup a process based on a db expression address.  We assume that the
150158029Sjhb * address was parsed in hexadecimal.  We reparse the address in decimal
151158029Sjhb * first and try to treat it as a PID to find an associated process.
152158029Sjhb * If that fails we treat the addr as a pointer to a process.
153158029Sjhb */
154158029Sjhbstruct proc *
155158029Sjhbdb_lookup_proc(db_expr_t addr)
156158029Sjhb{
157158029Sjhb	db_expr_t decaddr;
158158029Sjhb	struct proc *p;
159158029Sjhb
160208509Sbz	decaddr = db_hex2dec(addr);
161158029Sjhb	if (decaddr != -1) {
162166074Sdelphij		FOREACH_PROC_IN_SYSTEM(p) {
163158029Sjhb			if (p->p_pid == decaddr)
164158029Sjhb				return (p);
165158029Sjhb		}
166158029Sjhb		LIST_FOREACH(p, &zombproc, p_list) {
167158029Sjhb			if (p->p_pid == decaddr)
168158029Sjhb				return (p);
169158029Sjhb		}
170158029Sjhb	}
171158029Sjhb	return ((struct proc *)addr);
172158029Sjhb}
173