summaryrefslogtreecommitdiffstats
path: root/sys/ddb
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ddb')
-rw-r--r--sys/ddb/db_access.c14
-rw-r--r--sys/ddb/db_break.c43
-rw-r--r--sys/ddb/db_command.c57
-rw-r--r--sys/ddb/db_main.c226
-rw-r--r--sys/ddb/db_output.c5
-rw-r--r--sys/ddb/db_print.c38
-rw-r--r--sys/ddb/db_ps.c26
-rw-r--r--sys/ddb/db_run.c66
-rw-r--r--sys/ddb/db_thread.c105
-rw-r--r--sys/ddb/db_variables.c121
-rw-r--r--sys/ddb/db_variables.h3
-rw-r--r--sys/ddb/ddb.h42
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_ */
OpenPOWER on IntegriCloud