subr_kdb.c revision 131903
1131903Smarcel/* 2131903Smarcel * Copyright (c) 2004 The FreeBSD Project 3131903Smarcel * All rights reserved. 4131903Smarcel * 5131903Smarcel * Redistribution and use in source and binary forms, with or without 6131903Smarcel * modification, are permitted provided that the following conditions 7131903Smarcel * are met: 8131903Smarcel * 9131903Smarcel * 1. Redistributions of source code must retain the above copyright 10131903Smarcel * notice, this list of conditions and the following disclaimer. 11131903Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12131903Smarcel * notice, this list of conditions and the following disclaimer in the 13131903Smarcel * documentation and/or other materials provided with the distribution. 14131903Smarcel * 15131903Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16131903Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17131903Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18131903Smarcel * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19131903Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20131903Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21131903Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22131903Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23131903Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24131903Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25131903Smarcel */ 26131903Smarcel 27131903Smarcel#include <sys/cdefs.h> 28131903Smarcel__FBSDID("$FreeBSD: head/sys/kern/subr_kdb.c 131903 2004-07-10 18:40:12Z marcel $"); 29131903Smarcel 30131903Smarcel#include <sys/param.h> 31131903Smarcel#include <sys/systm.h> 32131903Smarcel#include <sys/kdb.h> 33131903Smarcel#include <sys/kernel.h> 34131903Smarcel#include <sys/malloc.h> 35131903Smarcel#include <sys/pcpu.h> 36131903Smarcel#include <sys/proc.h> 37131903Smarcel#include <sys/smp.h> 38131903Smarcel#include <sys/sysctl.h> 39131903Smarcel 40131903Smarcel#include <machine/kdb.h> 41131903Smarcel#include <machine/pcb.h> 42131903Smarcel 43131903Smarcelint kdb_active = 0; 44131903Smarcelvoid *kdb_jmpbufp = NULL; 45131903Smarcelstruct kdb_dbbe *kdb_dbbe = NULL; 46131903Smarcelstruct pcb kdb_pcb; 47131903Smarcelstruct pcb *kdb_thrctx = NULL; 48131903Smarcelstruct thread *kdb_thread = NULL; 49131903Smarcelstruct trapframe *kdb_frame = NULL; 50131903Smarcel 51131903SmarcelKDB_BACKEND(null, NULL, NULL, NULL); 52131903SmarcelSET_DECLARE(kdb_dbbe_set, struct kdb_dbbe); 53131903Smarcel 54131903Smarcelstatic int kdb_sysctl_available(SYSCTL_HANDLER_ARGS); 55131903Smarcelstatic int kdb_sysctl_current(SYSCTL_HANDLER_ARGS); 56131903Smarcelstatic int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS); 57131903Smarcel 58131903SmarcelSYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes"); 59131903Smarcel 60131903SmarcelSYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, 61131903Smarcel kdb_sysctl_available, "A", "list of available KDB backends"); 62131903Smarcel 63131903SmarcelSYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, 64131903Smarcel kdb_sysctl_current, "A", "currently selected KDB backend"); 65131903Smarcel 66131903SmarcelSYSCTL_PROC(_debug_kdb, OID_AUTO, enter, CTLTYPE_INT | CTLFLAG_RW, 0, 0, 67131903Smarcel kdb_sysctl_enter, "I", "set to enter the debugger"); 68131903Smarcel 69131903Smarcelstatic int 70131903Smarcelkdb_sysctl_available(SYSCTL_HANDLER_ARGS) 71131903Smarcel{ 72131903Smarcel struct kdb_dbbe *be, **iter; 73131903Smarcel char *avail, *p; 74131903Smarcel ssize_t len, sz; 75131903Smarcel int error; 76131903Smarcel 77131903Smarcel sz = 0; 78131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 79131903Smarcel be = *iter; 80131903Smarcel if (be->dbbe_active == 0) 81131903Smarcel sz += strlen(be->dbbe_name) + 1; 82131903Smarcel } 83131903Smarcel sz++; 84131903Smarcel avail = malloc(sz, M_TEMP, M_WAITOK); 85131903Smarcel p = avail; 86131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 87131903Smarcel be = *iter; 88131903Smarcel if (be->dbbe_active == 0) { 89131903Smarcel len = snprintf(p, sz, "%s ", be->dbbe_name); 90131903Smarcel p += len; 91131903Smarcel sz -= len; 92131903Smarcel } 93131903Smarcel } 94131903Smarcel KASSERT(sz >= 0, ("%s", __func__)); 95131903Smarcel error = sysctl_handle_string(oidp, avail, 0, req); 96131903Smarcel free(avail, M_TEMP); 97131903Smarcel return (error); 98131903Smarcel} 99131903Smarcel 100131903Smarcelstatic int 101131903Smarcelkdb_sysctl_current(SYSCTL_HANDLER_ARGS) 102131903Smarcel{ 103131903Smarcel char buf[16]; 104131903Smarcel struct kdb_dbbe *be, **iter; 105131903Smarcel int error; 106131903Smarcel 107131903Smarcel strncpy(buf, kdb_dbbe->dbbe_name, sizeof(buf)); 108131903Smarcel buf[sizeof(buf) - 1] = '\0'; 109131903Smarcel error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 110131903Smarcel if (error != 0 || req->newptr == NULL) 111131903Smarcel return (error); 112131903Smarcel if (kdb_active) 113131903Smarcel return (EBUSY); 114131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 115131903Smarcel be = *iter; 116131903Smarcel if (be->dbbe_active == 0 && strcmp(be->dbbe_name, buf) == 0) { 117131903Smarcel kdb_dbbe = be; 118131903Smarcel return (0); 119131903Smarcel } 120131903Smarcel } 121131903Smarcel return (EINVAL); 122131903Smarcel} 123131903Smarcel 124131903Smarcelstatic int 125131903Smarcelkdb_sysctl_enter(SYSCTL_HANDLER_ARGS) 126131903Smarcel{ 127131903Smarcel int error, i; 128131903Smarcel 129131903Smarcel error = sysctl_wire_old_buffer(req, sizeof(int)); 130131903Smarcel if (error == 0) { 131131903Smarcel i = 0; 132131903Smarcel error = sysctl_handle_int(oidp, &i, 0, req); 133131903Smarcel } 134131903Smarcel if (error != 0 || req->newptr == NULL) 135131903Smarcel return (error); 136131903Smarcel if (kdb_active) 137131903Smarcel return (EBUSY); 138131903Smarcel kdb_enter("sysctl debug.kdb.enter"); 139131903Smarcel return (0); 140131903Smarcel} 141131903Smarcel 142131903Smarcel/* 143131903Smarcel * Solaris implements a new BREAK which is initiated by a character sequence 144131903Smarcel * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the 145131903Smarcel * Remote Console. 146131903Smarcel * 147131903Smarcel * Note that this function may be called from almost anywhere, with interrupts 148131903Smarcel * disabled and with unknown locks held, so it must not access data other than 149131903Smarcel * its arguments. Its up to the caller to ensure that the state variable is 150131903Smarcel * consistent. 151131903Smarcel */ 152131903Smarcel 153131903Smarcel#define KEY_CR 13 /* CR '\r' */ 154131903Smarcel#define KEY_TILDE 126 /* ~ */ 155131903Smarcel#define KEY_CRTLB 2 /* ^B */ 156131903Smarcel 157131903Smarcelint 158131903Smarcelkdb_alt_break(int key, int *state) 159131903Smarcel{ 160131903Smarcel int brk; 161131903Smarcel 162131903Smarcel brk = 0; 163131903Smarcel switch (key) { 164131903Smarcel case KEY_CR: 165131903Smarcel *state = KEY_TILDE; 166131903Smarcel break; 167131903Smarcel case KEY_TILDE: 168131903Smarcel *state = (*state == KEY_TILDE) ? KEY_CRTLB : 0; 169131903Smarcel break; 170131903Smarcel case KEY_CRTLB: 171131903Smarcel if (*state == KEY_CRTLB) 172131903Smarcel brk = 1; 173131903Smarcel /* FALLTHROUGH */ 174131903Smarcel default: 175131903Smarcel *state = 0; 176131903Smarcel break; 177131903Smarcel } 178131903Smarcel return (brk); 179131903Smarcel} 180131903Smarcel 181131903Smarcel/* 182131903Smarcel * Print a backtrace of the calling thread. The backtrace is generated by 183131903Smarcel * the selected debugger, provided it supports backtraces. If no debugger 184131903Smarcel * is selected or the current debugger does not support backtraces, this 185131903Smarcel * function silently returns. 186131903Smarcel */ 187131903Smarcel 188131903Smarcelvoid 189131903Smarcelkdb_backtrace() 190131903Smarcel{ 191131903Smarcel 192131903Smarcel if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) { 193131903Smarcel printf("KDB: stack backtrace:\n"); 194131903Smarcel kdb_dbbe->dbbe_trace(); 195131903Smarcel } 196131903Smarcel} 197131903Smarcel 198131903Smarcel/* 199131903Smarcel * Enter the currently selected debugger. If a message has been provided, 200131903Smarcel * it is printed first. If the debugger does not support the enter method, 201131903Smarcel * it is entered by using breakpoint(), which enters the debugger through 202131903Smarcel * kdb_trap(). 203131903Smarcel */ 204131903Smarcel 205131903Smarcelvoid 206131903Smarcelkdb_enter(const char *msg) 207131903Smarcel{ 208131903Smarcel 209131903Smarcel if (kdb_dbbe != NULL && kdb_active == 0) { 210131903Smarcel if (msg != NULL) 211131903Smarcel printf("KDB: enter: %s\n", msg); 212131903Smarcel breakpoint(); 213131903Smarcel } 214131903Smarcel} 215131903Smarcel 216131903Smarcel/* 217131903Smarcel * Initialize the kernel debugger interface. 218131903Smarcel */ 219131903Smarcel 220131903Smarcelvoid 221131903Smarcelkdb_init() 222131903Smarcel{ 223131903Smarcel struct kdb_dbbe *be, **iter; 224131903Smarcel int cur_pri, pri; 225131903Smarcel 226131903Smarcel kdb_active = 0; 227131903Smarcel kdb_dbbe = NULL; 228131903Smarcel cur_pri = -1; 229131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 230131903Smarcel be = *iter; 231131903Smarcel pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1; 232131903Smarcel be->dbbe_active = (pri >= 0) ? 0 : -1; 233131903Smarcel if (pri > cur_pri) { 234131903Smarcel cur_pri = pri; 235131903Smarcel kdb_dbbe = be; 236131903Smarcel } 237131903Smarcel } 238131903Smarcel if (kdb_dbbe != NULL) { 239131903Smarcel printf("KDB: debugger backends:"); 240131903Smarcel SET_FOREACH(iter, kdb_dbbe_set) { 241131903Smarcel be = *iter; 242131903Smarcel if (be->dbbe_active == 0) 243131903Smarcel printf(" %s", be->dbbe_name); 244131903Smarcel } 245131903Smarcel printf("\n"); 246131903Smarcel printf("KDB: current backend: %s\n", 247131903Smarcel kdb_dbbe->dbbe_name); 248131903Smarcel } 249131903Smarcel} 250131903Smarcel 251131903Smarcel/* 252131903Smarcel * Handle contexts. 253131903Smarcel */ 254131903Smarcel 255131903Smarcelvoid * 256131903Smarcelkdb_jmpbuf(jmp_buf new) 257131903Smarcel{ 258131903Smarcel void *old; 259131903Smarcel 260131903Smarcel old = kdb_jmpbufp; 261131903Smarcel kdb_jmpbufp = new; 262131903Smarcel return (old); 263131903Smarcel} 264131903Smarcel 265131903Smarcelvoid 266131903Smarcelkdb_reenter(void) 267131903Smarcel{ 268131903Smarcel 269131903Smarcel if (!kdb_active || kdb_jmpbufp == NULL) 270131903Smarcel return; 271131903Smarcel 272131903Smarcel longjmp(kdb_jmpbufp, 1); 273131903Smarcel /* NOTREACHED */ 274131903Smarcel} 275131903Smarcel 276131903Smarcel/* 277131903Smarcel * Thread related support functions. 278131903Smarcel */ 279131903Smarcel 280131903Smarcelstruct pcb * 281131903Smarcelkdb_thr_ctx(struct thread *thr) 282131903Smarcel{ 283131903Smarcel return ((thr == curthread) ? &kdb_pcb : thr->td_pcb); 284131903Smarcel} 285131903Smarcel 286131903Smarcelstruct thread * 287131903Smarcelkdb_thr_first(void) 288131903Smarcel{ 289131903Smarcel struct proc *p; 290131903Smarcel struct thread *thr; 291131903Smarcel 292131903Smarcel p = LIST_FIRST(&allproc); 293131903Smarcel while (p != NULL) { 294131903Smarcel if (p->p_sflag & PS_INMEM) { 295131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 296131903Smarcel if (thr != NULL) 297131903Smarcel return (thr); 298131903Smarcel } 299131903Smarcel p = LIST_NEXT(p, p_list); 300131903Smarcel } 301131903Smarcel return (NULL); 302131903Smarcel} 303131903Smarcel 304131903Smarcelstruct thread * 305131903Smarcelkdb_thr_lookup(pid_t tid) 306131903Smarcel{ 307131903Smarcel struct thread *thr; 308131903Smarcel 309131903Smarcel thr = kdb_thr_first(); 310131903Smarcel while (thr != NULL && thr->td_tid != tid) 311131903Smarcel thr = kdb_thr_next(thr); 312131903Smarcel return (thr); 313131903Smarcel} 314131903Smarcel 315131903Smarcelstruct thread * 316131903Smarcelkdb_thr_next(struct thread *thr) 317131903Smarcel{ 318131903Smarcel struct proc *p; 319131903Smarcel 320131903Smarcel p = thr->td_proc; 321131903Smarcel thr = TAILQ_NEXT(thr, td_plist); 322131903Smarcel do { 323131903Smarcel if (thr != NULL) 324131903Smarcel return (thr); 325131903Smarcel p = LIST_NEXT(p, p_list); 326131903Smarcel if (p != NULL && (p->p_sflag & PS_INMEM)) 327131903Smarcel thr = FIRST_THREAD_IN_PROC(p); 328131903Smarcel } while (p != NULL); 329131903Smarcel return (NULL); 330131903Smarcel} 331131903Smarcel 332131903Smarcelint 333131903Smarcelkdb_thr_select(struct thread *thr) 334131903Smarcel{ 335131903Smarcel if (thr == NULL) 336131903Smarcel return (EINVAL); 337131903Smarcel kdb_thread = thr; 338131903Smarcel kdb_thrctx = kdb_thr_ctx(thr); 339131903Smarcel return (0); 340131903Smarcel} 341131903Smarcel 342131903Smarcel/* 343131903Smarcel * Enter the debugger due to a trap. 344131903Smarcel */ 345131903Smarcel 346131903Smarcelint 347131903Smarcelkdb_trap(int type, int code, struct trapframe *tf) 348131903Smarcel{ 349131903Smarcel int handled; 350131903Smarcel 351131903Smarcel if (kdb_dbbe == NULL || kdb_dbbe->dbbe_trap == NULL) 352131903Smarcel return (0); 353131903Smarcel 354131903Smarcel /* We reenter the debugger through kdb_reenter(). */ 355131903Smarcel if (kdb_active) 356131903Smarcel return (0); 357131903Smarcel 358131903Smarcel makectx(tf, &kdb_pcb); 359131903Smarcel 360131903Smarcel critical_enter(); 361131903Smarcel 362131903Smarcel kdb_active++; 363131903Smarcel kdb_frame = tf; 364131903Smarcel kdb_thr_select(curthread); 365131903Smarcel 366131903Smarcel#ifdef SMP 367131903Smarcel stop_cpus(PCPU_GET(other_cpus)); 368131903Smarcel#endif 369131903Smarcel 370131903Smarcel /* Let MD code do its thing first... */ 371131903Smarcel kdb_cpu_trap(type, code); 372131903Smarcel 373131903Smarcel handled = kdb_dbbe->dbbe_trap(type, code); 374131903Smarcel 375131903Smarcel#ifdef SMP 376131903Smarcel restart_cpus(stopped_cpus); 377131903Smarcel#endif 378131903Smarcel 379131903Smarcel kdb_active--; 380131903Smarcel 381131903Smarcel critical_exit(); 382131903Smarcel 383131903Smarcel return (handled); 384131903Smarcel} 385