subr_kdb.c revision 131903
1/*
2 * Copyright (c) 2004 The FreeBSD Project
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/kern/subr_kdb.c 131903 2004-07-10 18:40:12Z marcel $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kdb.h>
33#include <sys/kernel.h>
34#include <sys/malloc.h>
35#include <sys/pcpu.h>
36#include <sys/proc.h>
37#include <sys/smp.h>
38#include <sys/sysctl.h>
39
40#include <machine/kdb.h>
41#include <machine/pcb.h>
42
43int kdb_active = 0;
44void *kdb_jmpbufp = NULL;
45struct kdb_dbbe *kdb_dbbe = NULL;
46struct pcb kdb_pcb;
47struct pcb *kdb_thrctx = NULL;
48struct thread *kdb_thread = NULL;
49struct trapframe *kdb_frame = NULL;
50
51KDB_BACKEND(null, NULL, NULL, NULL);
52SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
53
54static int kdb_sysctl_available(SYSCTL_HANDLER_ARGS);
55static int kdb_sysctl_current(SYSCTL_HANDLER_ARGS);
56static int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS);
57
58SYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes");
59
60SYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, 0, 0,
61    kdb_sysctl_available, "A", "list of available KDB backends");
62
63SYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
64    kdb_sysctl_current, "A", "currently selected KDB backend");
65
66SYSCTL_PROC(_debug_kdb, OID_AUTO, enter, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
67    kdb_sysctl_enter, "I", "set to enter the debugger");
68
69static int
70kdb_sysctl_available(SYSCTL_HANDLER_ARGS)
71{
72	struct kdb_dbbe *be, **iter;
73	char *avail, *p;
74	ssize_t len, sz;
75	int error;
76
77	sz = 0;
78	SET_FOREACH(iter, kdb_dbbe_set) {
79		be = *iter;
80		if (be->dbbe_active == 0)
81			sz += strlen(be->dbbe_name) + 1;
82	}
83	sz++;
84	avail = malloc(sz, M_TEMP, M_WAITOK);
85	p = avail;
86	SET_FOREACH(iter, kdb_dbbe_set) {
87		be = *iter;
88		if (be->dbbe_active == 0) {
89			len = snprintf(p, sz, "%s ", be->dbbe_name);
90			p += len;
91			sz -= len;
92		}
93	}
94	KASSERT(sz >= 0, ("%s", __func__));
95	error = sysctl_handle_string(oidp, avail, 0, req);
96	free(avail, M_TEMP);
97	return (error);
98}
99
100static int
101kdb_sysctl_current(SYSCTL_HANDLER_ARGS)
102{
103	char buf[16];
104	struct kdb_dbbe *be, **iter;
105	int error;
106
107	strncpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
108	buf[sizeof(buf) - 1] = '\0';
109	error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
110	if (error != 0 || req->newptr == NULL)
111		return (error);
112	if (kdb_active)
113		return (EBUSY);
114	SET_FOREACH(iter, kdb_dbbe_set) {
115		be = *iter;
116		if (be->dbbe_active == 0 && strcmp(be->dbbe_name, buf) == 0) {
117			kdb_dbbe = be;
118			return (0);
119		}
120	}
121	return (EINVAL);
122}
123
124static int
125kdb_sysctl_enter(SYSCTL_HANDLER_ARGS)
126{
127	int error, i;
128
129	error = sysctl_wire_old_buffer(req, sizeof(int));
130	if (error == 0) {
131		i = 0;
132		error = sysctl_handle_int(oidp, &i, 0, req);
133	}
134	if (error != 0 || req->newptr == NULL)
135		return (error);
136	if (kdb_active)
137		return (EBUSY);
138	kdb_enter("sysctl debug.kdb.enter");
139	return (0);
140}
141
142/*
143 * Solaris implements a new BREAK which is initiated by a character sequence
144 * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the
145 * Remote Console.
146 *
147 * Note that this function may be called from almost anywhere, with interrupts
148 * disabled and with unknown locks held, so it must not access data other than
149 * its arguments.  Its up to the caller to ensure that the state variable is
150 * consistent.
151 */
152
153#define	KEY_CR		13	/* CR '\r' */
154#define	KEY_TILDE	126	/* ~ */
155#define	KEY_CRTLB	2	/* ^B */
156
157int
158kdb_alt_break(int key, int *state)
159{
160	int brk;
161
162	brk = 0;
163	switch (key) {
164	case KEY_CR:
165		*state = KEY_TILDE;
166		break;
167	case KEY_TILDE:
168		*state = (*state == KEY_TILDE) ? KEY_CRTLB : 0;
169		break;
170	case KEY_CRTLB:
171		if (*state == KEY_CRTLB)
172			brk = 1;
173		/* FALLTHROUGH */
174	default:
175		*state = 0;
176		break;
177	}
178	return (brk);
179}
180
181/*
182 * Print a backtrace of the calling thread. The backtrace is generated by
183 * the selected debugger, provided it supports backtraces. If no debugger
184 * is selected or the current debugger does not support backtraces, this
185 * function silently returns.
186 */
187
188void
189kdb_backtrace()
190{
191
192	if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) {
193		printf("KDB: stack backtrace:\n");
194		kdb_dbbe->dbbe_trace();
195	}
196}
197
198/*
199 * Enter the currently selected debugger. If a message has been provided,
200 * it is printed first. If the debugger does not support the enter method,
201 * it is entered by using breakpoint(), which enters the debugger through
202 * kdb_trap().
203 */
204
205void
206kdb_enter(const char *msg)
207{
208
209	if (kdb_dbbe != NULL && kdb_active == 0) {
210		if (msg != NULL)
211			printf("KDB: enter: %s\n", msg);
212		breakpoint();
213	}
214}
215
216/*
217 * Initialize the kernel debugger interface.
218 */
219
220void
221kdb_init()
222{
223	struct kdb_dbbe *be, **iter;
224	int cur_pri, pri;
225
226	kdb_active = 0;
227	kdb_dbbe = NULL;
228	cur_pri = -1;
229	SET_FOREACH(iter, kdb_dbbe_set) {
230		be = *iter;
231		pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1;
232		be->dbbe_active = (pri >= 0) ? 0 : -1;
233		if (pri > cur_pri) {
234			cur_pri = pri;
235			kdb_dbbe = be;
236		}
237	}
238	if (kdb_dbbe != NULL) {
239		printf("KDB: debugger backends:");
240		SET_FOREACH(iter, kdb_dbbe_set) {
241			be = *iter;
242			if (be->dbbe_active == 0)
243				printf(" %s", be->dbbe_name);
244		}
245		printf("\n");
246		printf("KDB: current backend: %s\n",
247		    kdb_dbbe->dbbe_name);
248	}
249}
250
251/*
252 * Handle contexts.
253 */
254
255void *
256kdb_jmpbuf(jmp_buf new)
257{
258	void *old;
259
260	old = kdb_jmpbufp;
261	kdb_jmpbufp = new;
262	return (old);
263}
264
265void
266kdb_reenter(void)
267{
268
269	if (!kdb_active || kdb_jmpbufp == NULL)
270		return;
271
272	longjmp(kdb_jmpbufp, 1);
273	/* NOTREACHED */
274}
275
276/*
277 * Thread related support functions.
278 */
279
280struct pcb *
281kdb_thr_ctx(struct thread *thr)
282{
283	return ((thr == curthread) ? &kdb_pcb : thr->td_pcb);
284}
285
286struct thread *
287kdb_thr_first(void)
288{
289	struct proc *p;
290	struct thread *thr;
291
292	p = LIST_FIRST(&allproc);
293	while (p != NULL) {
294		if (p->p_sflag & PS_INMEM) {
295			thr = FIRST_THREAD_IN_PROC(p);
296			if (thr != NULL)
297				return (thr);
298		}
299		p = LIST_NEXT(p, p_list);
300	}
301	return (NULL);
302}
303
304struct thread *
305kdb_thr_lookup(pid_t tid)
306{
307	struct thread *thr;
308
309	thr = kdb_thr_first();
310	while (thr != NULL && thr->td_tid != tid)
311		thr = kdb_thr_next(thr);
312	return (thr);
313}
314
315struct thread *
316kdb_thr_next(struct thread *thr)
317{
318	struct proc *p;
319
320	p = thr->td_proc;
321	thr = TAILQ_NEXT(thr, td_plist);
322	do {
323		if (thr != NULL)
324			return (thr);
325		p = LIST_NEXT(p, p_list);
326		if (p != NULL && (p->p_sflag & PS_INMEM))
327			thr = FIRST_THREAD_IN_PROC(p);
328	} while (p != NULL);
329	return (NULL);
330}
331
332int
333kdb_thr_select(struct thread *thr)
334{
335	if (thr == NULL)
336		return (EINVAL);
337	kdb_thread = thr;
338	kdb_thrctx = kdb_thr_ctx(thr);
339	return (0);
340}
341
342/*
343 * Enter the debugger due to a trap.
344 */
345
346int
347kdb_trap(int type, int code, struct trapframe *tf)
348{
349	int handled;
350
351	if (kdb_dbbe == NULL || kdb_dbbe->dbbe_trap == NULL)
352		return (0);
353
354	/* We reenter the debugger through kdb_reenter(). */
355	if (kdb_active)
356		return (0);
357
358	makectx(tf, &kdb_pcb);
359
360	critical_enter();
361
362	kdb_active++;
363	kdb_frame = tf;
364	kdb_thr_select(curthread);
365
366#ifdef SMP
367	stop_cpus(PCPU_GET(other_cpus));
368#endif
369
370	/* Let MD code do its thing first... */
371	kdb_cpu_trap(type, code);
372
373	handled = kdb_dbbe->dbbe_trap(type, code);
374
375#ifdef SMP
376	restart_cpus(stopped_cpus);
377#endif
378
379	kdb_active--;
380
381	critical_exit();
382
383	return (handled);
384}
385