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; 5428926c57SJohn Baldwin static dbbe_trace_thread_f db_trace_thread_wrapper; 5537224cd3SMarcel Moolenaar 5628926c57SJohn Baldwin KDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trace_thread_wrapper, 5728926c57SJohn Baldwin db_trap); 5837224cd3SMarcel Moolenaar 59c98a2727SRoger Pau Monné /* 60c98a2727SRoger Pau Monné * Symbols can be loaded by specifying the exact addresses of 61c98a2727SRoger Pau Monné * the symtab and strtab in memory. This is used when loaded from 62c98a2727SRoger Pau Monné * boot loaders different than the native one (like Xen). 63c98a2727SRoger Pau Monné */ 64c98a2727SRoger Pau Monné vm_offset_t ksymtab, kstrtab, ksymtab_size; 6537224cd3SMarcel Moolenaar 66cd508278SPedro F. Giffuni bool 6737224cd3SMarcel Moolenaar X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line, 6837224cd3SMarcel Moolenaar db_expr_t off) 6937224cd3SMarcel Moolenaar { 702b490bc7SPedro F. Giffuni return (false); 7137224cd3SMarcel Moolenaar } 7237224cd3SMarcel Moolenaar 7337224cd3SMarcel Moolenaar c_db_sym_t 7437224cd3SMarcel Moolenaar X_db_lookup(db_symtab_t *symtab, const char *symbol) 7537224cd3SMarcel Moolenaar { 7637224cd3SMarcel Moolenaar c_linker_sym_t lsym; 7737224cd3SMarcel Moolenaar Elf_Sym *sym; 7837224cd3SMarcel Moolenaar 7937224cd3SMarcel Moolenaar if (symtab->private == NULL) { 8037224cd3SMarcel Moolenaar return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym)) 8137224cd3SMarcel Moolenaar ? lsym : NULL)); 8237224cd3SMarcel Moolenaar } else { 8337224cd3SMarcel Moolenaar sym = (Elf_Sym *)symtab->start; 8437224cd3SMarcel Moolenaar while ((char *)sym < symtab->end) { 8537224cd3SMarcel Moolenaar if (sym->st_name != 0 && 8637224cd3SMarcel Moolenaar !strcmp(symtab->private + sym->st_name, symbol)) 8737224cd3SMarcel Moolenaar return ((c_db_sym_t)sym); 8837224cd3SMarcel Moolenaar sym++; 8937224cd3SMarcel Moolenaar } 9037224cd3SMarcel Moolenaar } 9137224cd3SMarcel Moolenaar return (NULL); 9237224cd3SMarcel Moolenaar } 9337224cd3SMarcel Moolenaar 9437224cd3SMarcel Moolenaar c_db_sym_t 9537224cd3SMarcel Moolenaar X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat, 9637224cd3SMarcel Moolenaar db_expr_t *diffp) 9737224cd3SMarcel Moolenaar { 9837224cd3SMarcel Moolenaar c_linker_sym_t lsym; 9937224cd3SMarcel Moolenaar Elf_Sym *sym, *match; 10037224cd3SMarcel Moolenaar unsigned long diff; 10137224cd3SMarcel Moolenaar 10237224cd3SMarcel Moolenaar if (symtab->private == NULL) { 10337224cd3SMarcel Moolenaar if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) { 10437224cd3SMarcel Moolenaar *diffp = (db_expr_t)diff; 10537224cd3SMarcel Moolenaar return ((c_db_sym_t)lsym); 10637224cd3SMarcel Moolenaar } 10737224cd3SMarcel Moolenaar return (NULL); 10837224cd3SMarcel Moolenaar } 10937224cd3SMarcel Moolenaar 11037224cd3SMarcel Moolenaar diff = ~0UL; 11137224cd3SMarcel Moolenaar match = NULL; 11237224cd3SMarcel Moolenaar for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) { 113e31a60b4SMark Johnston if (sym->st_name == 0 || sym->st_shndx == SHN_UNDEF) 11437224cd3SMarcel Moolenaar continue; 11537224cd3SMarcel Moolenaar if (off < sym->st_value) 11637224cd3SMarcel Moolenaar continue; 11737224cd3SMarcel Moolenaar if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT && 11837224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) != STT_FUNC && 11937224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) 12037224cd3SMarcel Moolenaar continue; 12137224cd3SMarcel Moolenaar if ((off - sym->st_value) > diff) 12237224cd3SMarcel Moolenaar continue; 12337224cd3SMarcel Moolenaar if ((off - sym->st_value) < diff) { 12437224cd3SMarcel Moolenaar diff = off - sym->st_value; 12537224cd3SMarcel Moolenaar match = sym; 12637224cd3SMarcel Moolenaar } else { 12737224cd3SMarcel Moolenaar if (match == NULL) 12837224cd3SMarcel Moolenaar match = sym; 12937224cd3SMarcel Moolenaar else if (ELF_ST_BIND(match->st_info) == STB_LOCAL && 13037224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 13137224cd3SMarcel Moolenaar match = sym; 13237224cd3SMarcel Moolenaar } 13337224cd3SMarcel Moolenaar if (diff == 0) { 13437224cd3SMarcel Moolenaar if (strat == DB_STGY_PROC && 13537224cd3SMarcel Moolenaar ELF_ST_TYPE(sym->st_info) == STT_FUNC && 13637224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 13737224cd3SMarcel Moolenaar break; 13837224cd3SMarcel Moolenaar if (strat == DB_STGY_ANY && 13937224cd3SMarcel Moolenaar ELF_ST_BIND(sym->st_info) != STB_LOCAL) 14037224cd3SMarcel Moolenaar break; 14137224cd3SMarcel Moolenaar } 14237224cd3SMarcel Moolenaar } 14337224cd3SMarcel Moolenaar 14437224cd3SMarcel Moolenaar *diffp = (match == NULL) ? off : diff; 14537224cd3SMarcel Moolenaar return ((c_db_sym_t)match); 14637224cd3SMarcel Moolenaar } 14737224cd3SMarcel Moolenaar 148cd508278SPedro F. Giffuni bool 14937224cd3SMarcel Moolenaar X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp, 15037224cd3SMarcel Moolenaar char **argp) 15137224cd3SMarcel Moolenaar { 1522b490bc7SPedro F. Giffuni return (false); 15337224cd3SMarcel Moolenaar } 15437224cd3SMarcel Moolenaar 15537224cd3SMarcel Moolenaar void 15637224cd3SMarcel Moolenaar X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep, 15737224cd3SMarcel Moolenaar db_expr_t *valp) 15837224cd3SMarcel Moolenaar { 15937224cd3SMarcel Moolenaar linker_symval_t lval; 16037224cd3SMarcel Moolenaar 16137224cd3SMarcel Moolenaar if (symtab->private == NULL) { 16237224cd3SMarcel Moolenaar linker_ddb_symbol_values((c_linker_sym_t)sym, &lval); 16337224cd3SMarcel Moolenaar if (namep != NULL) 16437224cd3SMarcel Moolenaar *namep = (const char*)lval.name; 16537224cd3SMarcel Moolenaar if (valp != NULL) 16637224cd3SMarcel Moolenaar *valp = (db_expr_t)lval.value; 16737224cd3SMarcel Moolenaar } else { 16837224cd3SMarcel Moolenaar if (namep != NULL) 16937224cd3SMarcel Moolenaar *namep = (const char *)symtab->private + 17037224cd3SMarcel Moolenaar ((const Elf_Sym *)sym)->st_name; 17137224cd3SMarcel Moolenaar if (valp != NULL) 17237224cd3SMarcel Moolenaar *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value; 17337224cd3SMarcel Moolenaar } 17437224cd3SMarcel Moolenaar } 17537224cd3SMarcel Moolenaar 176c98a2727SRoger Pau Monné int 177c98a2727SRoger Pau Monné db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end) 178c98a2727SRoger Pau Monné { 179c98a2727SRoger Pau Monné Elf_Size strsz; 180c98a2727SRoger Pau Monné 181c98a2727SRoger Pau Monné if (ksym_end > ksym_start && ksym_start != 0) { 182c98a2727SRoger Pau Monné ksymtab = ksym_start; 183c98a2727SRoger Pau Monné ksymtab_size = *(Elf_Size*)ksymtab; 184c98a2727SRoger Pau Monné ksymtab += sizeof(Elf_Size); 185c98a2727SRoger Pau Monné kstrtab = ksymtab + ksymtab_size; 186c98a2727SRoger Pau Monné strsz = *(Elf_Size*)kstrtab; 187c98a2727SRoger Pau Monné kstrtab += sizeof(Elf_Size); 188c98a2727SRoger Pau Monné if (kstrtab + strsz > ksym_end) { 189c98a2727SRoger Pau Monné /* Sizes doesn't match, unset everything. */ 190c98a2727SRoger Pau Monné ksymtab = ksymtab_size = kstrtab = 0; 191c98a2727SRoger Pau Monné } 192c98a2727SRoger Pau Monné } 193c98a2727SRoger Pau Monné 194c98a2727SRoger Pau Monné if (ksymtab == 0 || ksymtab_size == 0 || kstrtab == 0) 195c98a2727SRoger Pau Monné return (-1); 196c98a2727SRoger Pau Monné 197c98a2727SRoger Pau Monné return (0); 198c98a2727SRoger Pau Monné } 199c98a2727SRoger Pau Monné 20037224cd3SMarcel Moolenaar static int 20137224cd3SMarcel Moolenaar db_init(void) 20237224cd3SMarcel Moolenaar { 20337224cd3SMarcel Moolenaar 20493d4804bSJohn Baldwin db_command_init(); 205c98a2727SRoger Pau Monné 206c98a2727SRoger Pau Monné if (ksymtab != 0 && kstrtab != 0 && ksymtab_size != 0) { 207c98a2727SRoger Pau Monné db_add_symbol_table((char *)ksymtab, 208c98a2727SRoger Pau Monné (char *)(ksymtab + ksymtab_size), "elf", (char *)kstrtab); 20937224cd3SMarcel Moolenaar } 21037224cd3SMarcel Moolenaar db_add_symbol_table(NULL, NULL, "kld", NULL); 21137224cd3SMarcel Moolenaar return (1); /* We're the default debugger. */ 21237224cd3SMarcel Moolenaar } 21337224cd3SMarcel Moolenaar 21437224cd3SMarcel Moolenaar static int 21537224cd3SMarcel Moolenaar db_trap(int type, int code) 21637224cd3SMarcel Moolenaar { 21737224cd3SMarcel Moolenaar jmp_buf jb; 21837224cd3SMarcel Moolenaar void *prev_jb; 219cd508278SPedro F. Giffuni bool bkpt, watchpt; 220c9b0cc3bSRobert Watson const char *why; 22137224cd3SMarcel Moolenaar 22237224cd3SMarcel Moolenaar /* 22337224cd3SMarcel Moolenaar * Don't handle the trap if the console is unavailable (i.e. it 22437224cd3SMarcel Moolenaar * is in graphics mode). 22537224cd3SMarcel Moolenaar */ 22637224cd3SMarcel Moolenaar if (cnunavailable()) 22737224cd3SMarcel Moolenaar return (0); 22837224cd3SMarcel Moolenaar 229*5c48342fSBruce Evans if (db_stop_at_pc(type, code, &bkpt, &watchpt)) { 23037224cd3SMarcel Moolenaar if (db_inst_count) { 23137224cd3SMarcel Moolenaar db_printf("After %d instructions (%d loads, %d stores),\n", 23237224cd3SMarcel Moolenaar db_inst_count, db_load_count, db_store_count); 23337224cd3SMarcel Moolenaar } 23437224cd3SMarcel Moolenaar prev_jb = kdb_jmpbuf(jb); 23537224cd3SMarcel Moolenaar if (setjmp(jb) == 0) { 23637224cd3SMarcel Moolenaar db_dot = PC_REGS(); 23737224cd3SMarcel Moolenaar db_print_thread(); 23837224cd3SMarcel Moolenaar if (bkpt) 23937224cd3SMarcel Moolenaar db_printf("Breakpoint at\t"); 24037224cd3SMarcel Moolenaar else if (watchpt) 24137224cd3SMarcel Moolenaar db_printf("Watchpoint at\t"); 24237224cd3SMarcel Moolenaar else 24337224cd3SMarcel Moolenaar db_printf("Stopped at\t"); 24437224cd3SMarcel Moolenaar db_print_loc_and_inst(db_dot); 24537224cd3SMarcel Moolenaar } 246c9b0cc3bSRobert Watson why = kdb_why; 247c9b0cc3bSRobert Watson db_script_kdbenter(why != KDB_WHY_UNSET ? why : "unknown"); 24837224cd3SMarcel Moolenaar db_command_loop(); 24937224cd3SMarcel Moolenaar (void)kdb_jmpbuf(prev_jb); 25037224cd3SMarcel Moolenaar } 25137224cd3SMarcel Moolenaar 25237224cd3SMarcel Moolenaar db_restart_at_pc(watchpt); 25337224cd3SMarcel Moolenaar 25437224cd3SMarcel Moolenaar return (1); 25537224cd3SMarcel Moolenaar } 256a0396f27SKonstantin Belousov 257a0396f27SKonstantin Belousov static void 258a0396f27SKonstantin Belousov db_trace_self_wrapper(void) 259a0396f27SKonstantin Belousov { 260a0396f27SKonstantin Belousov jmp_buf jb; 261a0396f27SKonstantin Belousov void *prev_jb; 262a0396f27SKonstantin Belousov 263a0396f27SKonstantin Belousov prev_jb = kdb_jmpbuf(jb); 264a0396f27SKonstantin Belousov if (setjmp(jb) == 0) 265a0396f27SKonstantin Belousov db_trace_self(); 266a0396f27SKonstantin Belousov (void)kdb_jmpbuf(prev_jb); 267a0396f27SKonstantin Belousov } 26828926c57SJohn Baldwin 26928926c57SJohn Baldwin static void 27028926c57SJohn Baldwin db_trace_thread_wrapper(struct thread *td) 27128926c57SJohn Baldwin { 27228926c57SJohn Baldwin jmp_buf jb; 27328926c57SJohn Baldwin void *prev_jb; 27428926c57SJohn Baldwin 27528926c57SJohn Baldwin prev_jb = kdb_jmpbuf(jb); 27628926c57SJohn Baldwin if (setjmp(jb) == 0) 27728926c57SJohn Baldwin db_trace_thread(td, -1); 27828926c57SJohn Baldwin (void)kdb_jmpbuf(prev_jb); 27928926c57SJohn Baldwin } 280