diff options
Diffstat (limited to 'sys/ddb')
-rw-r--r-- | sys/ddb/db_access.c | 14 | ||||
-rw-r--r-- | sys/ddb/db_break.c | 43 | ||||
-rw-r--r-- | sys/ddb/db_command.c | 57 | ||||
-rw-r--r-- | sys/ddb/db_main.c | 226 | ||||
-rw-r--r-- | sys/ddb/db_output.c | 5 | ||||
-rw-r--r-- | sys/ddb/db_print.c | 38 | ||||
-rw-r--r-- | sys/ddb/db_ps.c | 26 | ||||
-rw-r--r-- | sys/ddb/db_run.c | 66 | ||||
-rw-r--r-- | sys/ddb/db_thread.c | 105 | ||||
-rw-r--r-- | sys/ddb/db_variables.c | 121 | ||||
-rw-r--r-- | sys/ddb/db_variables.h | 3 | ||||
-rw-r--r-- | sys/ddb/ddb.h | 42 |
12 files changed, 455 insertions, 291 deletions
diff --git a/sys/ddb/db_access.c b/sys/ddb/db_access.c index 15545de..d8224ad 100644 --- a/sys/ddb/db_access.c +++ b/sys/ddb/db_access.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/kdb.h> #include <ddb/ddb.h> #include <ddb/db_access.h> @@ -58,7 +59,11 @@ db_get_value(addr, size, is_signed) register db_expr_t value; register int i; - db_read_bytes(addr, size, data); + if (db_read_bytes(addr, size, data) != 0) { + db_printf("*** error reading from address %llx ***\n", + (long long)addr); + kdb_reenter(); + } value = 0; #if BYTE_MSF @@ -96,6 +101,9 @@ db_put_value(addr, size, value) value >>= 8; } - db_write_bytes(addr, size, data); + if (db_write_bytes(addr, size, data) != 0) { + db_printf("*** error writing to address %llx ***\n", + (long long)addr); + kdb_reenter(); + } } - diff --git a/sys/ddb/db_break.c b/sys/ddb/db_break.c index 577e338..78f4f4f 100644 --- a/sys/ddb/db_break.c +++ b/sys/ddb/db_break.c @@ -367,46 +367,3 @@ db_map_addr(addr) #endif return kernel_map; } - -#ifdef ALT_BREAK_TO_DEBUGGER -/* - * Solaris implements a new BREAK which is initiated by a character sequence - * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the - * Remote Console. - * - * Note that this function may be called from almost anywhere, with interrupts - * disabled and with unknown locks held, so it must not access data other than - * its arguments. Its up to the caller to ensure that the state variable is - * consistent. - */ - -#define KEY_CR 13 /* CR '\r' */ -#define KEY_TILDE 126 /* ~ */ -#define KEY_CRTLB 2 /* ^B */ - -int -db_alt_break(int data, int *state) -{ - int brk = 0; - - switch (data) { - case KEY_CR: - *state = KEY_TILDE; - break; - case KEY_TILDE: - if (*state == KEY_TILDE) - *state = KEY_CRTLB; - else - *state = 0; - break; - case KEY_CRTLB: - if (*state == KEY_CRTLB) - brk = 1; - /* FALLTHROUGH */ - default: - *state = 0; - break; - } - return (brk); -} -#endif diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index 70b3556..954a0d3 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/linker_set.h> #include <sys/lock.h> +#include <sys/kdb.h> #include <sys/mutex.h> #include <sys/proc.h> #include <sys/reboot.h> @@ -58,7 +59,6 @@ __FBSDID("$FreeBSD$"); */ boolean_t db_cmd_loop_done; db_addr_t db_dot; -jmp_buf db_jmpbuf; db_addr_t db_last_addr; db_addr_t db_prev; db_addr_t db_next; @@ -67,7 +67,6 @@ SET_DECLARE(db_cmd_set, struct command); SET_DECLARE(db_show_cmd_set, struct command); static db_cmdfcn_t db_fncall; -static db_cmdfcn_t db_gdb; static db_cmdfcn_t db_kill; static db_cmdfcn_t db_reset; static db_cmdfcn_t db_watchdog; @@ -375,9 +374,6 @@ db_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end) */ static struct command db_show_all_cmds[] = { -#if 0 - { "threads", db_show_all_threads, 0, 0 }, -#endif { "procs", db_ps, 0, 0 }, { (char *)0 } }; @@ -386,10 +382,7 @@ static struct command db_show_cmds[] = { { "all", 0, 0, db_show_all_cmds }, { "registers", db_show_regs, 0, 0 }, { "breaks", db_listbreak_cmd, 0, 0 }, - { "thread", db_show_one_thread, 0, 0 }, -#if 0 - { "port", ipc_port_print, 0, 0 }, -#endif + { "threads", db_show_threads, 0, 0 }, { (char *)0, } }; @@ -421,29 +414,15 @@ static struct command db_command_table[] = { { "call", db_fncall, CS_OWN, 0 }, { "show", 0, 0, db_show_cmds }, { "ps", db_ps, 0, 0 }, - { "gdb", db_gdb, 0, 0 }, { "reset", db_reset, 0, 0 }, { "kill", db_kill, CS_OWN, 0 }, { "watchdog", db_watchdog, 0, 0 }, + { "thread", db_set_thread, CS_OWN, 0 }, { (char *)0, } }; static struct command *db_last_command = 0; -#if 0 -void -db_help_cmd() -{ - struct command *cmd = db_command_table; - - while (cmd->name != 0) { - db_printf("%-12s", cmd->name); - db_end_line(); - cmd++; - } -} -#endif - /* * At least one non-optional command must be implemented using * DB_COMMAND() so that db_cmd_set gets created. Here is one. @@ -464,8 +443,6 @@ db_command_loop() db_cmd_loop_done = 0; while (!db_cmd_loop_done) { - - (void) setjmp(db_jmpbuf); if (db_print_position() != 0) db_printf("\n"); @@ -484,7 +461,7 @@ db_error(s) if (s) db_printf("%s", s); db_flush_lex(); - longjmp(db_jmpbuf, 1); + kdb_reenter(); } @@ -553,32 +530,6 @@ db_fncall(dummy1, dummy2, dummy3, dummy4) db_printf("%#lr\n", (long)retval); } -/* Enter GDB remote protocol debugger on the next trap. */ - -void *gdb_arg = NULL; -cn_getc_t *gdb_getc; -cn_putc_t *gdb_putc; - -static void -db_gdb (dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; -{ - - if (gdb_arg == NULL) { - db_printf("No gdb port enabled. Set flag 0x80 on desired port\n"); - db_printf("in your configuration file (currently sio only).\n"); - return; - } - boothowto ^= RB_GDB; - - db_printf("Next trap will enter %s\n", - boothowto & RB_GDB ? "GDB remote protocol mode" - : "DDB debugger"); -} - static void db_kill(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; diff --git a/sys/ddb/db_main.c b/sys/ddb/db_main.c new file mode 100644 index 0000000..32dd347 --- /dev/null +++ b/sys/ddb/db_main.c @@ -0,0 +1,226 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/cons.h> +#include <sys/linker.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/reboot.h> + +#include <machine/kdb.h> +#include <machine/pcb.h> +#include <machine/setjmp.h> + +#include <ddb/ddb.h> +#include <ddb/db_command.h> +#include <ddb/db_sym.h> + +static dbbe_init_f db_init; +static dbbe_trap_f db_trap; + +KDB_BACKEND(ddb, db_init, db_trace_self, db_trap); + +vm_offset_t ksym_start, ksym_end; + +boolean_t +X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line, + db_expr_t off) +{ + return (FALSE); +} + +c_db_sym_t +X_db_lookup(db_symtab_t *symtab, const char *symbol) +{ + c_linker_sym_t lsym; + Elf_Sym *sym; + + if (symtab->private == NULL) { + return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym)) + ? lsym : NULL)); + } else { + sym = (Elf_Sym *)symtab->start; + while ((char *)sym < symtab->end) { + if (sym->st_name != 0 && + !strcmp(symtab->private + sym->st_name, symbol)) + return ((c_db_sym_t)sym); + sym++; + } + } + return (NULL); +} + +c_db_sym_t +X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat, + db_expr_t *diffp) +{ + c_linker_sym_t lsym; + Elf_Sym *sym, *match; + unsigned long diff; + + if (symtab->private == NULL) { + if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) { + *diffp = (db_expr_t)diff; + return ((c_db_sym_t)lsym); + } + return (NULL); + } + + diff = ~0UL; + match = NULL; + for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) { + if (sym->st_name == 0) + continue; + if (off < sym->st_value) + continue; + if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT && + ELF_ST_TYPE(sym->st_info) != STT_FUNC && + ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) + continue; + if ((off - sym->st_value) > diff) + continue; + if ((off - sym->st_value) < diff) { + diff = off - sym->st_value; + match = sym; + } else { + if (match == NULL) + match = sym; + else if (ELF_ST_BIND(match->st_info) == STB_LOCAL && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + match = sym; + } + if (diff == 0) { + if (strat == DB_STGY_PROC && + ELF_ST_TYPE(sym->st_info) == STT_FUNC && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + break; + if (strat == DB_STGY_ANY && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + break; + } + } + + *diffp = (match == NULL) ? off : diff; + return ((c_db_sym_t)match); +} + +boolean_t +X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp, + char **argp) +{ + return (FALSE); +} + +void +X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep, + db_expr_t *valp) +{ + linker_symval_t lval; + + if (symtab->private == NULL) { + linker_ddb_symbol_values((c_linker_sym_t)sym, &lval); + if (namep != NULL) + *namep = (const char*)lval.name; + if (valp != NULL) + *valp = (db_expr_t)lval.value; + } else { + if (namep != NULL) + *namep = (const char *)symtab->private + + ((const Elf_Sym *)sym)->st_name; + if (valp != NULL) + *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value; + } +} + +static int +db_init(void) +{ + uintptr_t symtab, strtab; + Elf_Size tabsz, strsz; + + if (ksym_end > ksym_start && ksym_start != 0) { + symtab = ksym_start; + tabsz = *((Elf_Size*)symtab)++; + strtab = symtab + tabsz; + strsz = *((Elf_Size*)strtab)++; + if (strtab + strsz <= ksym_end) { + db_add_symbol_table((char *)symtab, + (char *)(symtab + tabsz), "elf", (char *)strtab); + } + } + db_add_symbol_table(NULL, NULL, "kld", NULL); + return (1); /* We're the default debugger. */ +} + +static int +db_trap(int type, int code) +{ + jmp_buf jb; + void *prev_jb; + boolean_t bkpt, watchpt; + + /* + * Don't handle the trap if the console is unavailable (i.e. it + * is in graphics mode). + */ + if (cnunavailable()) + return (0); + + bkpt = IS_BREAKPOINT_TRAP(type, code); + watchpt = IS_WATCHPOINT_TRAP(type, code); + + if (db_stop_at_pc(&bkpt)) { + if (db_inst_count) { + db_printf("After %d instructions (%d loads, %d stores),\n", + db_inst_count, db_load_count, db_store_count); + } + prev_jb = kdb_jmpbuf(jb); + if (setjmp(jb) == 0) { + db_dot = PC_REGS(); + db_print_thread(); + if (bkpt) + db_printf("Breakpoint at\t"); + else if (watchpt) + db_printf("Watchpoint at\t"); + else + db_printf("Stopped at\t"); + db_print_loc_and_inst(db_dot); + } + db_command_loop(); + (void)kdb_jmpbuf(prev_jb); + } + + db_restart_at_pc(watchpt); + + return (1); +} diff --git a/sys/ddb/db_output.c b/sys/ddb/db_output.c index 464d9162..ff2734c 100644 --- a/sys/ddb/db_output.c +++ b/sys/ddb/db_output.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/cons.h> +#include <sys/kdb.h> #include <sys/kernel.h> #include <sys/sysctl.h> @@ -112,9 +113,9 @@ db_putchar(c, arg) * If not in the debugger or the user requests it, output data to * both the console and the message buffer. */ - if (!db_active || ddb_use_printf) { + if (!kdb_active || ddb_use_printf) { printf("%c", c); - if (!db_active) + if (!kdb_active) return; if (c == '\r' || c == '\n') db_check_interrupt(); diff --git a/sys/ddb/db_print.c b/sys/ddb/db_print.c index 60282ad..b173c8c 100644 --- a/sys/ddb/db_print.c +++ b/sys/ddb/db_print.c @@ -37,33 +37,33 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/kdb.h> + +#include <machine/pcb.h> #include <ddb/ddb.h> #include <ddb/db_variables.h> #include <ddb/db_sym.h> void -db_show_regs(dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; +db_show_regs(db_expr_t _1, boolean_t _2, db_expr_t _3, char *_4) { - register struct db_variable *regp; - db_expr_t value, offset; - const char * name; + struct db_variable *regp; + db_expr_t value, offset; + const char *name; for (regp = db_regs; regp < db_eregs; regp++) { - db_read_variable(regp, &value); - db_printf("%-12s%#10lr", regp->name, (unsigned long)value); - db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); - if (name != NULL && offset <= (unsigned long)db_maxoff && - offset != value) { - db_printf("\t%s", name); - if (offset != 0) - db_printf("+%+#lr", (long)offset); - } - db_printf("\n"); + if (!db_read_variable(regp, &value)) + continue; + db_printf("%-12s%#10lr", regp->name, (unsigned long)value); + db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); + if (name != NULL && offset <= (unsigned long)db_maxoff && + offset != value) { + db_printf("\t%s", name); + if (offset != 0) + db_printf("+%+#lr", (long)offset); + } + db_printf("\n"); } - db_print_loc_and_inst(PC_REGS(DDB_REGS)); + db_print_loc_and_inst(PC_REGS()); } diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c index f146cb3..47d4c7d 100644 --- a/sys/ddb/db_ps.c +++ b/sys/ddb/db_ps.c @@ -166,29 +166,3 @@ dumpthread(volatile struct proc *p, volatile struct thread *td) } else db_printf(" %s\n", p->p_comm); } - - -#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) -void -db_show_one_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif) -{ - struct proc *p; - struct thread *td; - - if (!have_addr) - td = curthread; - else if (!INKERNEL(addr)) { - printf("bad thread address"); - return; - } else - td = (struct thread *)addr; - /* quick sanity check */ - if ((p = td->td_proc) != td->td_ksegrp->kg_proc) - return; - printf("Proc %p ",p); - dumpthread(p, td); -#ifdef __i386__ - db_stack_thread((db_expr_t)td, 1, count, modif); -#endif -} diff --git a/sys/ddb/db_run.c b/sys/ddb/db_run.c index 79b148a..ab589d3 100644 --- a/sys/ddb/db_run.c +++ b/sys/ddb/db_run.c @@ -36,6 +36,10 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/kdb.h> + +#include <machine/kdb.h> +#include <machine/pcb.h> #include <vm/vm.h> @@ -61,14 +65,10 @@ int db_load_count; int db_store_count; #ifndef db_set_single_step -extern void db_set_single_step(db_regs_t *regs); +void db_set_single_step(void); #endif #ifndef db_clear_single_step -extern void db_clear_single_step(db_regs_t *regs); -#endif - -#ifdef notused -static void db_single_step(db_regs_t *regs); +void db_clear_single_step(void); #endif boolean_t @@ -78,10 +78,10 @@ db_stop_at_pc(is_breakpoint) register db_addr_t pc; register db_breakpoint_t bkpt; - db_clear_single_step(DDB_REGS); + db_clear_single_step(); db_clear_breakpoints(); db_clear_watchpoints(); - pc = PC_REGS(DDB_REGS); + pc = PC_REGS(); #ifdef FIXUP_PC_AFTER_BREAK if (*is_breakpoint) { @@ -90,7 +90,7 @@ db_stop_at_pc(is_breakpoint) * machine requires it. */ FIXUP_PC_AFTER_BREAK - pc = PC_REGS(DDB_REGS); + pc = PC_REGS(); } #endif @@ -171,7 +171,7 @@ void db_restart_at_pc(watchpt) boolean_t watchpt; { - register db_addr_t pc = PC_REGS(DDB_REGS); + register db_addr_t pc = PC_REGS(); if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) || @@ -205,28 +205,16 @@ db_restart_at_pc(watchpt) * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; - db_set_single_step(DDB_REGS); + db_set_single_step(); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { - db_set_single_step(DDB_REGS); + db_set_single_step(); } } -#ifdef notused -static void -db_single_step(regs) - db_regs_t *regs; -{ - if (db_run_mode == STEP_CONTINUE) { - db_run_mode = STEP_INVISIBLE; - db_set_single_step(regs); - } -} -#endif - #ifdef SOFTWARE_SSTEP /* * Software implementation of single-stepping. @@ -261,11 +249,10 @@ db_breakpoint_t db_not_taken_bkpt = 0; db_breakpoint_t db_taken_bkpt = 0; void -db_set_single_step(regs) - register db_regs_t *regs; +db_set_single_step(void) { - db_addr_t pc = PC_REGS(regs), brpc; - unsigned inst; + db_addr_t pc = PC_REGS(), brpc; + unsigned inst; /* * User was stopped at pc, e.g. the instruction @@ -273,28 +260,27 @@ db_set_single_step(regs) */ inst = db_get_value(pc, sizeof(int), FALSE); if (inst_branch(inst) || inst_call(inst)) { - brpc = branch_taken(inst, pc, regs); - if (brpc != pc) { /* self-branches are hopeless */ - db_taken_bkpt = db_set_temp_breakpoint(brpc); - } - pc = next_instr_address(pc,1); + brpc = branch_taken(inst, pc); + if (brpc != pc) { /* self-branches are hopeless */ + db_taken_bkpt = db_set_temp_breakpoint(brpc); + } + pc = next_instr_address(pc, 1); } - pc = next_instr_address(pc,0); + pc = next_instr_address(pc, 0); db_not_taken_bkpt = db_set_temp_breakpoint(pc); } void -db_clear_single_step(regs) - db_regs_t *regs; +db_clear_single_step(void) { if (db_not_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_not_taken_bkpt); - db_not_taken_bkpt = 0; + db_delete_temp_breakpoint(db_not_taken_bkpt); + db_not_taken_bkpt = 0; } if (db_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_taken_bkpt); - db_taken_bkpt = 0; + db_delete_temp_breakpoint(db_taken_bkpt); + db_taken_bkpt = 0; } } diff --git a/sys/ddb/db_thread.c b/sys/ddb/db_thread.c new file mode 100644 index 0000000..b58f0b0 --- /dev/null +++ b/sys/ddb/db_thread.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kdb.h> +#include <sys/proc.h> + +#include <machine/pcb.h> + +#include <ddb/ddb.h> +#include <ddb/db_command.h> +#include <ddb/db_sym.h> + +void +db_print_thread(void) +{ + db_printf("[thread %ld]\n", (long)kdb_thread->td_tid); +} + +void +db_set_thread(db_expr_t tid, boolean_t hastid, db_expr_t cnt, char *mod) +{ + struct thread *thr; + db_expr_t radix; + int err; + + /* + * We parse our own arguments. We don't like the default radix. + */ + radix = db_radix; + db_radix = 10; + hastid = db_expression(&tid); + db_radix = radix; + db_skip_to_eol(); + + if (hastid) { + thr = kdb_thr_lookup(tid); + if (thr != NULL) { + err = kdb_thr_select(thr); + if (err != 0) { + db_printf("unable to switch to thread %ld\n", + (long)thr->td_tid); + return; + } + db_dot = PC_REGS(); + } else { + db_printf("%d: invalid thread\n", (int)tid); + return; + } + } + + db_print_thread(); + db_print_loc_and_inst(PC_REGS()); +} + +void +db_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod) +{ + jmp_buf jb; + void *prev_jb; + struct thread *thr; + int pager_quit; + + db_setup_paging(db_simple_pager, &pager_quit, DB_LINES_PER_PAGE); + + pager_quit = 0; + thr = kdb_thr_first(); + while (!pager_quit && thr != NULL) { + db_printf(" %6ld (%p) ", (long)thr->td_tid, thr); + prev_jb = kdb_jmpbuf(jb); + if (setjmp(jb) == 0) { + if (db_trace_thread(thr, 1) != 0) + db_printf("***\n"); + } + kdb_jmpbuf(prev_jb); + thr = kdb_thr_next(thr); + } +} diff --git a/sys/ddb/db_variables.c b/sys/ddb/db_variables.c index 1b28376..cf8e2e7 100644 --- a/sys/ddb/db_variables.c +++ b/sys/ddb/db_variables.c @@ -39,11 +39,6 @@ __FBSDID("$FreeBSD$"); #include <ddb/db_variables.h> static int db_find_variable(struct db_variable **varp); -static void db_write_variable(struct db_variable *, db_expr_t *); - -#ifdef notused -static int db_set_variable(db_expr_t value); -#endif static struct db_variable db_vars[] = { { "radix", &db_radix, FCN_NULL }, @@ -51,123 +46,107 @@ static struct db_variable db_vars[] = { { "maxwidth", &db_max_width, FCN_NULL }, { "tabstops", &db_tab_stop_width, FCN_NULL }, }; -static struct db_variable *db_evars = - db_vars + sizeof(db_vars)/sizeof(db_vars[0]); +static struct db_variable *db_evars = + db_vars + sizeof(db_vars)/sizeof(db_vars[0]); static int -db_find_variable(varp) - struct db_variable **varp; +db_find_variable(struct db_variable **varp) { - int t; struct db_variable *vp; + int t; t = db_read_token(); if (t == tIDENT) { - for (vp = db_vars; vp < db_evars; vp++) { - if (!strcmp(db_tok_string, vp->name)) { - *varp = vp; - return (1); + for (vp = db_vars; vp < db_evars; vp++) { + if (!strcmp(db_tok_string, vp->name)) { + *varp = vp; + return (1); + } } - } - for (vp = db_regs; vp < db_eregs; vp++) { - if (!strcmp(db_tok_string, vp->name)) { - *varp = vp; - return (1); + for (vp = db_regs; vp < db_eregs; vp++) { + if (!strcmp(db_tok_string, vp->name)) { + *varp = vp; + return (1); + } } - } } db_error("Unknown variable\n"); return (0); } int -db_get_variable(valuep) - db_expr_t *valuep; +db_get_variable(db_expr_t *valuep) { struct db_variable *vp; if (!db_find_variable(&vp)) - return (0); - - db_read_variable(vp, valuep); + return (0); - return (1); + return (db_read_variable(vp, valuep)); } -#ifdef notused -static int -db_set_variable(value) - db_expr_t value; +int +db_set_variable(db_expr_t value) { struct db_variable *vp; if (!db_find_variable(&vp)) - return (0); + return (0); - db_write_variable(vp, &value); - - return (1); + return (db_write_variable(vp, value)); } -#endif -void -db_read_variable(vp, valuep) - struct db_variable *vp; - db_expr_t *valuep; +int +db_read_variable(struct db_variable *vp, db_expr_t *valuep) { - db_varfcn_t *func = vp->fcn; + db_varfcn_t *func = vp->fcn; - if (func == FCN_NULL) - *valuep = *(vp->valuep); - else - (*func)(vp, valuep, DB_VAR_GET); + if (func == FCN_NULL) { + *valuep = *(vp->valuep); + return (1); + } + return ((*func)(vp, valuep, DB_VAR_GET)); } -static void -db_write_variable(vp, valuep) - struct db_variable *vp; - db_expr_t *valuep; +int +db_write_variable(struct db_variable *vp, db_expr_t value) { - db_varfcn_t *func = vp->fcn; + db_varfcn_t *func = vp->fcn; - if (func == FCN_NULL) - *(vp->valuep) = *valuep; - else - (*func)(vp, valuep, DB_VAR_SET); + if (func == FCN_NULL) { + *(vp->valuep) = value; + return (1); + } + return ((*func)(vp, &value, DB_VAR_SET)); } void -db_set_cmd(dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; +db_set_cmd(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4) { - db_expr_t value; struct db_variable *vp; - int t; + db_expr_t value; + int t; t = db_read_token(); if (t != tDOLLAR) { - db_error("Unknown variable\n"); - return; + db_error("Unknown variable\n"); + return; } if (!db_find_variable(&vp)) { - db_error("Unknown variable\n"); - return; + db_error("Unknown variable\n"); + return; } t = db_read_token(); if (t != tEQ) - db_unread_token(t); + db_unread_token(t); if (!db_expression(&value)) { - db_error("No value\n"); - return; - } - if (db_read_token() != tEOL) { - db_error("?\n"); + db_error("No value\n"); + return; } + if (db_read_token() != tEOL) + db_error("?\n"); - db_write_variable(vp, &value); + db_write_variable(vp, value); } diff --git a/sys/ddb/db_variables.h b/sys/ddb/db_variables.h index 6c05118..7f7a463 100644 --- a/sys/ddb/db_variables.h +++ b/sys/ddb/db_variables.h @@ -52,6 +52,7 @@ struct db_variable { extern struct db_variable db_regs[]; /* machine registers */ extern struct db_variable *db_eregs; -void db_read_variable(struct db_variable *, db_expr_t *); +int db_read_variable(struct db_variable *, db_expr_t *); +int db_write_variable(struct db_variable *, db_expr_t); #endif /* _!DDB_DB_VARIABLES_H_ */ diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h index 1ef452c..c1ffff9 100644 --- a/sys/ddb/ddb.h +++ b/sys/ddb/ddb.h @@ -69,9 +69,7 @@ func_name(addr, have_addr, count, modif) \ db_expr_t count; \ char *modif; -extern char *esym; extern db_expr_t db_maxoff; -extern int db_active; extern int db_indent; extern int db_inst_count; extern int db_load_count; @@ -81,11 +79,9 @@ extern db_expr_t db_radix; extern db_expr_t db_max_width; extern db_expr_t db_tab_stop_width; +struct thread; struct vm_map; -#ifdef ALT_BREAK_TO_DEBUGGER -int db_alt_break(int, int *); -#endif void db_check_interrupt(void); void db_clear_watchpoints(void); db_addr_t db_disasm(db_addr_t loc, boolean_t altfmt); @@ -98,24 +94,23 @@ struct vm_map *db_map_addr(vm_offset_t); boolean_t db_map_current(struct vm_map *); boolean_t db_map_equal(struct vm_map *, struct vm_map *); void db_print_loc_and_inst(db_addr_t loc); +void db_print_thread(void); void db_printf(const char *fmt, ...) __printflike(1, 2); -void db_read_bytes(vm_offset_t addr, size_t size, char *data); +int db_read_bytes(vm_offset_t addr, size_t size, char *data); /* machine-dependent */ int db_readline(char *lstart, int lsize); void db_restart_at_pc(boolean_t watchpt); +int db_set_variable(db_expr_t value); void db_set_watchpoints(void); void db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines); void db_skip_to_eol(void); boolean_t db_stop_at_pc(boolean_t *is_breakpoint); #define db_strcpy strcpy -void db_trap(int type, int code); +void db_trace_self(void); +int db_trace_thread(struct thread *, int); int db_value_of_name(const char *name, db_expr_t *valuep); -void db_write_bytes(vm_offset_t addr, size_t size, char *data); - /* machine-dependent */ -void db_stack_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif); -void kdb_init(void); +int db_write_bytes(vm_offset_t addr, size_t size, char *data); db_cmdfcn_t db_breakpoint_cmd; db_cmdfcn_t db_continue_cmd; @@ -129,27 +124,18 @@ db_cmdfcn_t db_print_cmd; db_cmdfcn_t db_ps; db_cmdfcn_t db_search_cmd; db_cmdfcn_t db_set_cmd; +db_cmdfcn_t db_set_thread; db_cmdfcn_t db_show_regs; +db_cmdfcn_t db_show_threads; db_cmdfcn_t db_single_step_cmd; db_cmdfcn_t db_stack_trace_cmd; db_cmdfcn_t db_trace_until_call_cmd; db_cmdfcn_t db_trace_until_matching_cmd; db_cmdfcn_t db_watchpoint_cmd; db_cmdfcn_t db_write_cmd; -db_cmdfcn_t db_show_one_thread; - -#if 0 -db_cmdfcn_t db_help_cmd; -db_cmdfcn_t db_show_all_threads; -db_cmdfcn_t ipc_port_print; -db_cmdfcn_t vm_page_print; -#endif db_page_calloutfcn_t db_simple_pager; -/* Scare the user with backtrace of curthread to console. */ -void db_print_backtrace(void); - /* * Command table. */ @@ -164,14 +150,4 @@ struct command { struct command *more; /* another level of command */ }; -/* XXX: UGLY hack */ -#ifdef CN_DEAD -/* - * Routines to support GDB on an sio port. - */ -extern void *gdb_arg; -extern cn_getc_t *gdb_getc; -extern cn_putc_t *gdb_putc; -#endif - #endif /* !_DDB_DDB_H_ */ |