1dd3cb568SWarner Losh /*- 237224cd3SMarcel Moolenaar * Mach Operating System 337224cd3SMarcel Moolenaar * Copyright (c) 1991,1990 Carnegie Mellon University 437224cd3SMarcel Moolenaar * All Rights Reserved. 537224cd3SMarcel Moolenaar * 637224cd3SMarcel Moolenaar * Permission to use, copy, modify and distribute this software and its 737224cd3SMarcel Moolenaar * documentation is hereby granted, provided that both the copyright 837224cd3SMarcel Moolenaar * notice and this permission notice appear in all copies of the 937224cd3SMarcel Moolenaar * software, derivative works or modified versions, and any portions 1037224cd3SMarcel Moolenaar * thereof, and that both notices appear in supporting documentation. 1137224cd3SMarcel Moolenaar * 1237224cd3SMarcel Moolenaar * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 1337224cd3SMarcel Moolenaar * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 1437224cd3SMarcel Moolenaar * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1537224cd3SMarcel Moolenaar * 1637224cd3SMarcel Moolenaar * Carnegie Mellon requests users of this software to return to 1737224cd3SMarcel Moolenaar * 1837224cd3SMarcel Moolenaar * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 1937224cd3SMarcel Moolenaar * School of Computer Science 2037224cd3SMarcel Moolenaar * Carnegie Mellon University 2137224cd3SMarcel Moolenaar * Pittsburgh PA 15213-3890 2237224cd3SMarcel Moolenaar * 2337224cd3SMarcel Moolenaar * any improvements or extensions that they make and grant Carnegie the 2437224cd3SMarcel Moolenaar * rights to redistribute these changes. 2537224cd3SMarcel Moolenaar */ 2637224cd3SMarcel Moolenaar 2737224cd3SMarcel Moolenaar #include <sys/cdefs.h> 2837224cd3SMarcel Moolenaar __FBSDID("$FreeBSD$"); 2937224cd3SMarcel Moolenaar 3037224cd3SMarcel Moolenaar #include <sys/param.h> 3137224cd3SMarcel Moolenaar #include <sys/systm.h> 3237224cd3SMarcel Moolenaar #include <sys/cons.h> 3337224cd3SMarcel Moolenaar #include <sys/linker.h> 3437224cd3SMarcel Moolenaar #include <sys/kdb.h> 3537224cd3SMarcel Moolenaar #include <sys/kernel.h> 3637224cd3SMarcel Moolenaar #include <sys/pcpu.h> 3737224cd3SMarcel Moolenaar #include <sys/proc.h> 3837224cd3SMarcel Moolenaar #include <sys/reboot.h> 39086fec57SRobert Watson #include <sys/sysctl.h> 4037224cd3SMarcel Moolenaar 4137224cd3SMarcel Moolenaar #include <machine/kdb.h> 4237224cd3SMarcel Moolenaar #include <machine/pcb.h> 4337224cd3SMarcel Moolenaar #include <machine/setjmp.h> 4437224cd3SMarcel Moolenaar 4537224cd3SMarcel Moolenaar #include <ddb/ddb.h> 4637224cd3SMarcel Moolenaar #include <ddb/db_command.h> 4737224cd3SMarcel Moolenaar #include <ddb/db_sym.h> 4837224cd3SMarcel Moolenaar 49086fec57SRobert Watson SYSCTL_NODE(_debug, OID_AUTO, ddb, CTLFLAG_RW, 0, "DDB settings"); 50086fec57SRobert Watson 5137224cd3SMarcel Moolenaar static dbbe_init_f db_init; 5237224cd3SMarcel Moolenaar static dbbe_trap_f db_trap; 53a0396f27SKonstantin Belousov static dbbe_trace_f db_trace_self_wrapper; 5437224cd3SMarcel Moolenaar 55a0396f27SKonstantin Belousov KDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trap); 5637224cd3SMarcel Moolenaar 5737224cd3SMarcel Moolenaar vm_offset_t ksym_start, ksym_end; 5837224cd3SMarcel Moolenaar 5937224cd3SMarcel Moolenaar boolean_t 6037224cd3SMarcel Moolenaar X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line, 6137224cd3SMarcel Moolenaar db_expr_t off) 6237224cd3SMarcel Moolenaar { 6337224cd3SMarcel Moolenaar return (FALSE); 6437224cd3SMarcel Moolenaar } 6537224cd3SMarcel Moolenaar 6637224cd3SMarcel Moolenaar c_db_sym_t 6737224cd3SMarcel Moolenaar X_db_lookup(db_symtab_t *symtab, const char *symbol) 6837224cd3SMarcel Moolenaar { 6937224cd3SMarcel Moolenaar c_linker_sym_t lsym; 7037224cd3SMarcel Moolenaar Elf_Sym *sym; 7137224cd3SMarcel Moolenaar 7237224cd3SMarcel Moolenaar if (symtab->private == NULL) { 7337224cd3SMarcel Moolenaar return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym)) 7437224cd3SMarcel Moolenaar ? lsym : NULL)); 7537224cd3SMarcel Moolenaar } else { 7637224cd3SMarcel Moolenaar sym = (Elf_Sym *)symtab->start; 7737224cd3SMarcel Moolenaar while ((char *)sym < symtab->end) { 7837224cd3SMarcel Moolenaar if (sym->st_name != 0 && 7937224cd3SMarcel Moolenaar !strcmp(symtab->private + sym->st_name, symbol)) 8037224cd3SMarcel Moolenaar return ((c_db_sym_t)sym); 8137224cd3SMarcel Moolenaar sym++; 8237224cd3SMarcel Moolenaar } 8337224cd3SMarcel Moolenaar } 8437224cd3SMarcel Moolenaar return (NULL); 8537224cd3SMarcel Moolenaar } 8637224cd3SMarcel Moolenaar 8737224cd3SMarcel Moolenaar c_db_sym_t 8837224cd3SMarcel Moolenaar X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat, 8937224cd3SMarcel Moolenaar db_expr_t *diffp) 9037224cd3SMarcel Moolenaar { 9137224cd3SMarcel Moolenaar c_linker_sym_t lsym; 9237224cd3SMarcel Moolenaar Elf_Sym *sym, *match; 9337224cd3SMarcel Moolenaar unsigned long diff; 9437224cd3SMarcel Moolenaar 9537224cd3SMarcel Moolenaar if (symtab->private == NULL) { 9637224cd3SMarcel Moolenaar if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) { 9737224cd3SMarcel Moolenaar *diffp = (db_expr_t)diff; 9837224cd3SMarcel Moolenaar return ((c_db_sym_t)lsym); 9937224cd3SMarcel Moolenaar } 10037224cd3SMarcel Moolenaar return (NULL); 10137224cd3SMarcel Moolenaar } 10237224cd3SMarcel Moolenaar 10337224cd3SMarcel Moolenaar diff = ~0UL; 10437224cd3SMarcel Moolenaar match = NULL; 10537224cd3SMarcel Moolenaar for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) { 10637224cd3SMarcel Moolenaar if (sym->st_name == 0) 10737224cd3SMarcel Moolenaar continue; 10837224cd3SMarcel Moolenaar if (off < sym->st_value) 10937224cd3SMarcel Moolenaar continue; 11037224cd3SMarcel Moolenaar if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT && 11137224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) != STT_FUNC && 11237224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) 11337224cd3SMarcel Moolenaar continue; 11437224cd3SMarcel Moolenaar if ((off - sym->st_value) > diff) 11537224cd3SMarcel Moolenaar continue; 11637224cd3SMarcel Moolenaar if ((off - sym->st_value) < diff) { 11737224cd3SMarcel Moolenaar diff = off - sym->st_value; 11837224cd3SMarcel Moolenaar match = sym; 11937224cd3SMarcel Moolenaar } else { 12037224cd3SMarcel Moolenaar if (match == NULL) 12137224cd3SMarcel Moolenaar match = sym; 12237224cd3SMarcel Moolenaar else if (ELF_ST_BIND(match->st_info) == STB_LOCAL && 12337224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 12437224cd3SMarcel Moolenaar match = sym; 12537224cd3SMarcel Moolenaar } 12637224cd3SMarcel Moolenaar if (diff == 0) { 12737224cd3SMarcel Moolenaar if (strat == DB_STGY_PROC && 12837224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) == STT_FUNC && 12937224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 13037224cd3SMarcel Moolenaar break; 13137224cd3SMarcel Moolenaar if (strat == DB_STGY_ANY && 13237224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 13337224cd3SMarcel Moolenaar break; 13437224cd3SMarcel Moolenaar } 13537224cd3SMarcel Moolenaar } 13637224cd3SMarcel Moolenaar 13737224cd3SMarcel Moolenaar *diffp = (match == NULL) ? off : diff; 13837224cd3SMarcel Moolenaar return ((c_db_sym_t)match); 13937224cd3SMarcel Moolenaar } 14037224cd3SMarcel Moolenaar 14137224cd3SMarcel Moolenaar boolean_t 14237224cd3SMarcel Moolenaar X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp, 14337224cd3SMarcel Moolenaar char **argp) 14437224cd3SMarcel Moolenaar { 14537224cd3SMarcel Moolenaar return (FALSE); 14637224cd3SMarcel Moolenaar } 14737224cd3SMarcel Moolenaar 14837224cd3SMarcel Moolenaar void 14937224cd3SMarcel Moolenaar X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep, 15037224cd3SMarcel Moolenaar db_expr_t *valp) 15137224cd3SMarcel Moolenaar { 15237224cd3SMarcel Moolenaar linker_symval_t lval; 15337224cd3SMarcel Moolenaar 15437224cd3SMarcel Moolenaar if (symtab->private == NULL) { 15537224cd3SMarcel Moolenaar linker_ddb_symbol_values((c_linker_sym_t)sym, &lval); 15637224cd3SMarcel Moolenaar if (namep != NULL) 15737224cd3SMarcel Moolenaar *namep = (const char*)lval.name; 15837224cd3SMarcel Moolenaar if (valp != NULL) 15937224cd3SMarcel Moolenaar *valp = (db_expr_t)lval.value; 16037224cd3SMarcel Moolenaar } else { 16137224cd3SMarcel Moolenaar if (namep != NULL) 16237224cd3SMarcel Moolenaar *namep = (const char *)symtab->private + 16337224cd3SMarcel Moolenaar ((const Elf_Sym *)sym)->st_name; 16437224cd3SMarcel Moolenaar if (valp != NULL) 16537224cd3SMarcel Moolenaar *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value; 16637224cd3SMarcel Moolenaar } 16737224cd3SMarcel Moolenaar } 16837224cd3SMarcel Moolenaar 16937224cd3SMarcel Moolenaar static int 17037224cd3SMarcel Moolenaar db_init(void) 17137224cd3SMarcel Moolenaar { 17237224cd3SMarcel Moolenaar uintptr_t symtab, strtab; 17337224cd3SMarcel Moolenaar Elf_Size tabsz, strsz; 17437224cd3SMarcel Moolenaar 17593d4804bSJohn Baldwin db_command_init(); 17637224cd3SMarcel Moolenaar if (ksym_end > ksym_start && ksym_start != 0) { 17737224cd3SMarcel Moolenaar symtab = ksym_start; 178eec256deSAlexander Kabaev tabsz = *((Elf_Size*)symtab); 1790171fe42SAlexander Kabaev symtab += sizeof(Elf_Size); 18037224cd3SMarcel Moolenaar strtab = symtab + tabsz; 181eec256deSAlexander Kabaev strsz = *((Elf_Size*)strtab); 1820171fe42SAlexander Kabaev strtab += sizeof(Elf_Size); 18337224cd3SMarcel Moolenaar if (strtab + strsz <= ksym_end) { 18437224cd3SMarcel Moolenaar db_add_symbol_table((char *)symtab, 18537224cd3SMarcel Moolenaar (char *)(symtab + tabsz), "elf", (char *)strtab); 18637224cd3SMarcel Moolenaar } 18737224cd3SMarcel Moolenaar } 18837224cd3SMarcel Moolenaar db_add_symbol_table(NULL, NULL, "kld", NULL); 18937224cd3SMarcel Moolenaar return (1); /* We're the default debugger. */ 19037224cd3SMarcel Moolenaar } 19137224cd3SMarcel Moolenaar 19237224cd3SMarcel Moolenaar static int 19337224cd3SMarcel Moolenaar db_trap(int type, int code) 19437224cd3SMarcel Moolenaar { 19537224cd3SMarcel Moolenaar jmp_buf jb; 19637224cd3SMarcel Moolenaar void *prev_jb; 19737224cd3SMarcel Moolenaar boolean_t bkpt, watchpt; 198c9b0cc3bSRobert Watson const char *why; 19937224cd3SMarcel Moolenaar 20037224cd3SMarcel Moolenaar /* 20137224cd3SMarcel Moolenaar * Don't handle the trap if the console is unavailable (i.e. it 20237224cd3SMarcel Moolenaar * is in graphics mode). 20337224cd3SMarcel Moolenaar */ 20437224cd3SMarcel Moolenaar if (cnunavailable()) 20537224cd3SMarcel Moolenaar return (0); 20637224cd3SMarcel Moolenaar 20737224cd3SMarcel Moolenaar bkpt = IS_BREAKPOINT_TRAP(type, code); 20837224cd3SMarcel Moolenaar watchpt = IS_WATCHPOINT_TRAP(type, code); 20937224cd3SMarcel Moolenaar 21037224cd3SMarcel Moolenaar if (db_stop_at_pc(&bkpt)) { 21137224cd3SMarcel Moolenaar if (db_inst_count) { 21237224cd3SMarcel Moolenaar db_printf("After %d instructions (%d loads, %d stores),\n", 21337224cd3SMarcel Moolenaar db_inst_count, db_load_count, db_store_count); 21437224cd3SMarcel Moolenaar } 21537224cd3SMarcel Moolenaar prev_jb = kdb_jmpbuf(jb); 21637224cd3SMarcel Moolenaar if (setjmp(jb) == 0) { 21737224cd3SMarcel Moolenaar db_dot = PC_REGS(); 21837224cd3SMarcel Moolenaar db_print_thread(); 21937224cd3SMarcel Moolenaar if (bkpt) 22037224cd3SMarcel Moolenaar db_printf("Breakpoint at\t"); 22137224cd3SMarcel Moolenaar else if (watchpt) 22237224cd3SMarcel Moolenaar db_printf("Watchpoint at\t"); 22337224cd3SMarcel Moolenaar else 22437224cd3SMarcel Moolenaar db_printf("Stopped at\t"); 22537224cd3SMarcel Moolenaar db_print_loc_and_inst(db_dot); 22637224cd3SMarcel Moolenaar } 227c9b0cc3bSRobert Watson why = kdb_why; 228c9b0cc3bSRobert Watson db_script_kdbenter(why != KDB_WHY_UNSET ? why : "unknown"); 22937224cd3SMarcel Moolenaar db_command_loop(); 23037224cd3SMarcel Moolenaar (void)kdb_jmpbuf(prev_jb); 23137224cd3SMarcel Moolenaar } 23237224cd3SMarcel Moolenaar 23337224cd3SMarcel Moolenaar db_restart_at_pc(watchpt); 23437224cd3SMarcel Moolenaar 23537224cd3SMarcel Moolenaar return (1); 23637224cd3SMarcel Moolenaar } 237a0396f27SKonstantin Belousov 238a0396f27SKonstantin Belousov static void 239a0396f27SKonstantin Belousov db_trace_self_wrapper(void) 240a0396f27SKonstantin Belousov { 241a0396f27SKonstantin Belousov jmp_buf jb; 242a0396f27SKonstantin Belousov void *prev_jb; 243a0396f27SKonstantin Belousov 244a0396f27SKonstantin Belousov prev_jb = kdb_jmpbuf(jb); 245a0396f27SKonstantin Belousov if (setjmp(jb) == 0) 246a0396f27SKonstantin Belousov db_trace_self(); 247a0396f27SKonstantin Belousov (void)kdb_jmpbuf(prev_jb); 248a0396f27SKonstantin Belousov } 249