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