1139747Simp/*- 2131952Smarcel * Mach Operating System 3131952Smarcel * Copyright (c) 1991,1990 Carnegie Mellon University 4131952Smarcel * All Rights Reserved. 5131952Smarcel * 6131952Smarcel * Permission to use, copy, modify and distribute this software and its 7131952Smarcel * documentation is hereby granted, provided that both the copyright 8131952Smarcel * notice and this permission notice appear in all copies of the 9131952Smarcel * software, derivative works or modified versions, and any portions 10131952Smarcel * thereof, and that both notices appear in supporting documentation. 11131952Smarcel * 12131952Smarcel * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13131952Smarcel * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14131952Smarcel * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15131952Smarcel * 16131952Smarcel * Carnegie Mellon requests users of this software to return to 17131952Smarcel * 18131952Smarcel * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19131952Smarcel * School of Computer Science 20131952Smarcel * Carnegie Mellon University 21131952Smarcel * Pittsburgh PA 15213-3890 22131952Smarcel * 23131952Smarcel * any improvements or extensions that they make and grant Carnegie the 24131952Smarcel * rights to redistribute these changes. 25131952Smarcel */ 26131952Smarcel 27131952Smarcel#include <sys/cdefs.h> 28131952Smarcel__FBSDID("$FreeBSD$"); 29131952Smarcel 30131952Smarcel#include <sys/param.h> 31131952Smarcel#include <sys/systm.h> 32131952Smarcel#include <sys/cons.h> 33131952Smarcel#include <sys/linker.h> 34131952Smarcel#include <sys/kdb.h> 35131952Smarcel#include <sys/kernel.h> 36131952Smarcel#include <sys/pcpu.h> 37131952Smarcel#include <sys/proc.h> 38131952Smarcel#include <sys/reboot.h> 39174910Srwatson#include <sys/sysctl.h> 40131952Smarcel 41131952Smarcel#include <machine/kdb.h> 42131952Smarcel#include <machine/pcb.h> 43131952Smarcel#include <machine/setjmp.h> 44131952Smarcel 45131952Smarcel#include <ddb/ddb.h> 46131952Smarcel#include <ddb/db_command.h> 47131952Smarcel#include <ddb/db_sym.h> 48131952Smarcel 49174910SrwatsonSYSCTL_NODE(_debug, OID_AUTO, ddb, CTLFLAG_RW, 0, "DDB settings"); 50174910Srwatson 51131952Smarcelstatic dbbe_init_f db_init; 52131952Smarcelstatic dbbe_trap_f db_trap; 53164029Skibstatic dbbe_trace_f db_trace_self_wrapper; 54234196Sjhbstatic dbbe_trace_thread_f db_trace_thread_wrapper; 55131952Smarcel 56234196SjhbKDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trace_thread_wrapper, 57234196Sjhb db_trap); 58131952Smarcel 59131952Smarcelvm_offset_t ksym_start, ksym_end; 60131952Smarcel 61131952Smarcelboolean_t 62131952SmarcelX_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line, 63131952Smarcel db_expr_t off) 64131952Smarcel{ 65131952Smarcel return (FALSE); 66131952Smarcel} 67131952Smarcel 68131952Smarcelc_db_sym_t 69131952SmarcelX_db_lookup(db_symtab_t *symtab, const char *symbol) 70131952Smarcel{ 71131952Smarcel c_linker_sym_t lsym; 72131952Smarcel Elf_Sym *sym; 73131952Smarcel 74131952Smarcel if (symtab->private == NULL) { 75131952Smarcel return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym)) 76131952Smarcel ? lsym : NULL)); 77131952Smarcel } else { 78131952Smarcel sym = (Elf_Sym *)symtab->start; 79131952Smarcel while ((char *)sym < symtab->end) { 80131952Smarcel if (sym->st_name != 0 && 81131952Smarcel !strcmp(symtab->private + sym->st_name, symbol)) 82131952Smarcel return ((c_db_sym_t)sym); 83131952Smarcel sym++; 84131952Smarcel } 85131952Smarcel } 86131952Smarcel return (NULL); 87131952Smarcel} 88131952Smarcel 89131952Smarcelc_db_sym_t 90131952SmarcelX_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat, 91131952Smarcel db_expr_t *diffp) 92131952Smarcel{ 93131952Smarcel c_linker_sym_t lsym; 94131952Smarcel Elf_Sym *sym, *match; 95131952Smarcel unsigned long diff; 96131952Smarcel 97131952Smarcel if (symtab->private == NULL) { 98131952Smarcel if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) { 99131952Smarcel *diffp = (db_expr_t)diff; 100131952Smarcel return ((c_db_sym_t)lsym); 101131952Smarcel } 102131952Smarcel return (NULL); 103131952Smarcel } 104131952Smarcel 105131952Smarcel diff = ~0UL; 106131952Smarcel match = NULL; 107131952Smarcel for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) { 108131952Smarcel if (sym->st_name == 0) 109131952Smarcel continue; 110131952Smarcel if (off < sym->st_value) 111131952Smarcel continue; 112131952Smarcel if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT && 113131952Smarcel ELF_ST_TYPE(sym->st_info) != STT_FUNC && 114131952Smarcel ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) 115131952Smarcel continue; 116131952Smarcel if ((off - sym->st_value) > diff) 117131952Smarcel continue; 118131952Smarcel if ((off - sym->st_value) < diff) { 119131952Smarcel diff = off - sym->st_value; 120131952Smarcel match = sym; 121131952Smarcel } else { 122131952Smarcel if (match == NULL) 123131952Smarcel match = sym; 124131952Smarcel else if (ELF_ST_BIND(match->st_info) == STB_LOCAL && 125131952Smarcel ELF_ST_BIND(sym->st_info) != STB_LOCAL) 126131952Smarcel match = sym; 127131952Smarcel } 128131952Smarcel if (diff == 0) { 129131952Smarcel if (strat == DB_STGY_PROC && 130131952Smarcel ELF_ST_TYPE(sym->st_info) == STT_FUNC && 131131952Smarcel ELF_ST_BIND(sym->st_info) != STB_LOCAL) 132131952Smarcel break; 133131952Smarcel if (strat == DB_STGY_ANY && 134131952Smarcel ELF_ST_BIND(sym->st_info) != STB_LOCAL) 135131952Smarcel break; 136131952Smarcel } 137131952Smarcel } 138131952Smarcel 139131952Smarcel *diffp = (match == NULL) ? off : diff; 140131952Smarcel return ((c_db_sym_t)match); 141131952Smarcel} 142131952Smarcel 143131952Smarcelboolean_t 144131952SmarcelX_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp, 145131952Smarcel char **argp) 146131952Smarcel{ 147131952Smarcel return (FALSE); 148131952Smarcel} 149131952Smarcel 150131952Smarcelvoid 151131952SmarcelX_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep, 152131952Smarcel db_expr_t *valp) 153131952Smarcel{ 154131952Smarcel linker_symval_t lval; 155131952Smarcel 156131952Smarcel if (symtab->private == NULL) { 157131952Smarcel linker_ddb_symbol_values((c_linker_sym_t)sym, &lval); 158131952Smarcel if (namep != NULL) 159131952Smarcel *namep = (const char*)lval.name; 160131952Smarcel if (valp != NULL) 161131952Smarcel *valp = (db_expr_t)lval.value; 162131952Smarcel } else { 163131952Smarcel if (namep != NULL) 164131952Smarcel *namep = (const char *)symtab->private + 165131952Smarcel ((const Elf_Sym *)sym)->st_name; 166131952Smarcel if (valp != NULL) 167131952Smarcel *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value; 168131952Smarcel } 169131952Smarcel} 170131952Smarcel 171131952Smarcelstatic int 172131952Smarceldb_init(void) 173131952Smarcel{ 174131952Smarcel uintptr_t symtab, strtab; 175131952Smarcel Elf_Size tabsz, strsz; 176131952Smarcel 177183360Sjhb db_command_init(); 178131952Smarcel if (ksym_end > ksym_start && ksym_start != 0) { 179131952Smarcel symtab = ksym_start; 180132771Skan tabsz = *((Elf_Size*)symtab); 181132791Skan symtab += sizeof(Elf_Size); 182131952Smarcel strtab = symtab + tabsz; 183132771Skan strsz = *((Elf_Size*)strtab); 184132791Skan strtab += sizeof(Elf_Size); 185131952Smarcel if (strtab + strsz <= ksym_end) { 186131952Smarcel db_add_symbol_table((char *)symtab, 187131952Smarcel (char *)(symtab + tabsz), "elf", (char *)strtab); 188131952Smarcel } 189131952Smarcel } 190131952Smarcel db_add_symbol_table(NULL, NULL, "kld", NULL); 191131952Smarcel return (1); /* We're the default debugger. */ 192131952Smarcel} 193131952Smarcel 194131952Smarcelstatic int 195131952Smarceldb_trap(int type, int code) 196131952Smarcel{ 197131952Smarcel jmp_buf jb; 198131952Smarcel void *prev_jb; 199131952Smarcel boolean_t bkpt, watchpt; 200174914Srwatson const char *why; 201131952Smarcel 202131952Smarcel /* 203131952Smarcel * Don't handle the trap if the console is unavailable (i.e. it 204131952Smarcel * is in graphics mode). 205131952Smarcel */ 206131952Smarcel if (cnunavailable()) 207131952Smarcel return (0); 208131952Smarcel 209131952Smarcel bkpt = IS_BREAKPOINT_TRAP(type, code); 210131952Smarcel watchpt = IS_WATCHPOINT_TRAP(type, code); 211131952Smarcel 212131952Smarcel if (db_stop_at_pc(&bkpt)) { 213131952Smarcel if (db_inst_count) { 214131952Smarcel db_printf("After %d instructions (%d loads, %d stores),\n", 215131952Smarcel db_inst_count, db_load_count, db_store_count); 216131952Smarcel } 217131952Smarcel prev_jb = kdb_jmpbuf(jb); 218131952Smarcel if (setjmp(jb) == 0) { 219131952Smarcel db_dot = PC_REGS(); 220131952Smarcel db_print_thread(); 221131952Smarcel if (bkpt) 222131952Smarcel db_printf("Breakpoint at\t"); 223131952Smarcel else if (watchpt) 224131952Smarcel db_printf("Watchpoint at\t"); 225131952Smarcel else 226131952Smarcel db_printf("Stopped at\t"); 227131952Smarcel db_print_loc_and_inst(db_dot); 228131952Smarcel } 229174914Srwatson why = kdb_why; 230174914Srwatson db_script_kdbenter(why != KDB_WHY_UNSET ? why : "unknown"); 231131952Smarcel db_command_loop(); 232131952Smarcel (void)kdb_jmpbuf(prev_jb); 233131952Smarcel } 234131952Smarcel 235131952Smarcel db_restart_at_pc(watchpt); 236131952Smarcel 237131952Smarcel return (1); 238131952Smarcel} 239164029Skib 240164029Skibstatic void 241164029Skibdb_trace_self_wrapper(void) 242164029Skib{ 243164029Skib jmp_buf jb; 244164029Skib void *prev_jb; 245164029Skib 246164029Skib prev_jb = kdb_jmpbuf(jb); 247164029Skib if (setjmp(jb) == 0) 248164029Skib db_trace_self(); 249164029Skib (void)kdb_jmpbuf(prev_jb); 250164029Skib} 251234196Sjhb 252234196Sjhbstatic void 253234196Sjhbdb_trace_thread_wrapper(struct thread *td) 254234196Sjhb{ 255234196Sjhb jmp_buf jb; 256234196Sjhb void *prev_jb; 257234196Sjhb 258234196Sjhb prev_jb = kdb_jmpbuf(jb); 259234196Sjhb if (setjmp(jb) == 0) 260234196Sjhb db_trace_thread(td, -1); 261234196Sjhb (void)kdb_jmpbuf(prev_jb); 262234196Sjhb} 263