summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2004-07-10 23:47:20 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2004-07-10 23:47:20 +0000
commit37224cd3fcb911d440e40dd8e1f31652e2452537 (patch)
tree533bc344dcaf70d30b9a52c0dc5327488516647b
parent5971a234e5b07f66372970c407b8085d6ad7904e (diff)
Notes
-rw-r--r--sys/alpha/alpha/db_disasm.c38
-rw-r--r--sys/alpha/alpha/db_interface.c293
-rw-r--r--sys/alpha/alpha/db_trace.c168
-rw-r--r--sys/alpha/include/db_machdep.h49
-rw-r--r--sys/amd64/amd64/db_interface.c314
-rw-r--r--sys/amd64/amd64/db_trace.c416
-rw-r--r--sys/amd64/include/db_machdep.h17
-rw-r--r--sys/conf/files36
-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
-rw-r--r--sys/i386/i386/db_interface.c319
-rw-r--r--sys/i386/i386/db_trace.c399
-rw-r--r--sys/i386/include/db_machdep.h17
-rw-r--r--sys/ia64/ia64/db_interface.c651
-rw-r--r--sys/ia64/ia64/db_trace.c54
-rw-r--r--sys/ia64/include/db_machdep.h120
-rw-r--r--sys/sparc64/include/db_machdep.h14
-rw-r--r--sys/sparc64/sparc64/db_interface.c79
-rw-r--r--sys/sparc64/sparc64/db_trace.c302
29 files changed, 1689 insertions, 2343 deletions
diff --git a/sys/alpha/alpha/db_disasm.c b/sys/alpha/alpha/db_disasm.c
index c54ec210cacbc..8d98121a8d2fc 100644
--- a/sys/alpha/alpha/db_disasm.c
+++ b/sys/alpha/alpha/db_disasm.c
@@ -813,26 +813,9 @@ register_name (ireg)
* (optional) alternate format. Return address of start of
* next instruction.
*/
-int alpha_print_instruction(db_addr_t, alpha_instruction, boolean_t);
-db_addr_t
-db_disasm(loc, altfmt)
- db_addr_t loc;
- boolean_t altfmt;
-{
- alpha_instruction inst;
-
- inst.bits = db_get_value(loc, 4, 0);
-
- loc += alpha_print_instruction(loc, inst, altfmt);
- return (loc);
-}
-
-int
-alpha_print_instruction(iadr, i, showregs)
- db_addr_t iadr;
- alpha_instruction i;
- boolean_t showregs;
+static int
+alpha_print_instr(db_addr_t iadr, alpha_instruction i, boolean_t showregs)
{
const char *opcode;
int ireg;
@@ -1038,7 +1021,7 @@ loadstore_address:
if (i.mem_format.opcode == op_ldah)
signed_immediate <<= 16;
db_printf(" <0x%lx>", signed_immediate +
- db_register_value(DDB_REGS, i.mem_format.rs));
+ db_register_value(i.mem_format.rs));
}
break;
case op_br:
@@ -1084,10 +1067,23 @@ branch_displacement:
db_printf(",");
db_printf("%s=0x%lx",
name_of_register[regnum[ireg]],
- db_register_value(DDB_REGS, regnum[ireg]));
+ db_register_value(regnum[ireg]));
}
db_printf(">");
}
db_printf("\n");
return (sizeof(alpha_instruction));
}
+
+db_addr_t
+db_disasm(loc, altfmt)
+ db_addr_t loc;
+ boolean_t altfmt;
+{
+ alpha_instruction inst;
+
+ inst.bits = db_get_value(loc, 4, 0);
+
+ loc += alpha_print_instr(loc, inst, altfmt);
+ return (loc);
+}
diff --git a/sys/alpha/alpha/db_interface.c b/sys/alpha/alpha/db_interface.c
index d11ad8fc3548c..7a7553f2ec5fa 100644
--- a/sys/alpha/alpha/db_interface.c
+++ b/sys/alpha/alpha/db_interface.c
@@ -50,14 +50,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/reboot.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/cons.h>
-#include <sys/ktr.h>
-#include <sys/lock.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
#include <sys/pcpu.h>
+#include <sys/proc.h>
#include <sys/smp.h>
#include <vm/vm.h>
@@ -73,209 +71,104 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
-#include <machine/setjmp.h>
-
-static jmp_buf *db_nofault = 0;
-extern jmp_buf db_jmpbuf;
-extern void gdb_handle_exception(db_regs_t *, int, int);
-
-#if 0
-extern char *trap_type[];
-extern int trap_types;
-#endif
-
-int db_active;
-
-void ddbprinttrap(unsigned long, unsigned long, unsigned long,
- unsigned long);
+static db_varfcn_t db_frame;
struct db_variable db_regs[] = {
- { "v0", &ddb_regs.tf_regs[FRAME_V0], FCN_NULL },
- { "t0", &ddb_regs.tf_regs[FRAME_T0], FCN_NULL },
- { "t1", &ddb_regs.tf_regs[FRAME_T1], FCN_NULL },
- { "t2", &ddb_regs.tf_regs[FRAME_T2], FCN_NULL },
- { "t3", &ddb_regs.tf_regs[FRAME_T3], FCN_NULL },
- { "t4", &ddb_regs.tf_regs[FRAME_T4], FCN_NULL },
- { "t5", &ddb_regs.tf_regs[FRAME_T5], FCN_NULL },
- { "t6", &ddb_regs.tf_regs[FRAME_T6], FCN_NULL },
- { "t7", &ddb_regs.tf_regs[FRAME_T7], FCN_NULL },
- { "s0", &ddb_regs.tf_regs[FRAME_S0], FCN_NULL },
- { "s1", &ddb_regs.tf_regs[FRAME_S1], FCN_NULL },
- { "s2", &ddb_regs.tf_regs[FRAME_S2], FCN_NULL },
- { "s3", &ddb_regs.tf_regs[FRAME_S3], FCN_NULL },
- { "s4", &ddb_regs.tf_regs[FRAME_S4], FCN_NULL },
- { "s5", &ddb_regs.tf_regs[FRAME_S5], FCN_NULL },
- { "s6", &ddb_regs.tf_regs[FRAME_S6], FCN_NULL },
- { "a0", &ddb_regs.tf_regs[FRAME_A0], FCN_NULL },
- { "a1", &ddb_regs.tf_regs[FRAME_A1], FCN_NULL },
- { "a2", &ddb_regs.tf_regs[FRAME_A2], FCN_NULL },
- { "a3", &ddb_regs.tf_regs[FRAME_A3], FCN_NULL },
- { "a4", &ddb_regs.tf_regs[FRAME_A4], FCN_NULL },
- { "a5", &ddb_regs.tf_regs[FRAME_A5], FCN_NULL },
- { "t8", &ddb_regs.tf_regs[FRAME_T8], FCN_NULL },
- { "t9", &ddb_regs.tf_regs[FRAME_T9], FCN_NULL },
- { "t10", &ddb_regs.tf_regs[FRAME_T10], FCN_NULL },
- { "t11", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
- { "ra", &ddb_regs.tf_regs[FRAME_RA], FCN_NULL },
- { "t12", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
- { "at", &ddb_regs.tf_regs[FRAME_AT], FCN_NULL },
- { "gp", &ddb_regs.tf_regs[FRAME_GP], FCN_NULL },
- { "sp", &ddb_regs.tf_regs[FRAME_SP], FCN_NULL },
- { "pc", &ddb_regs.tf_regs[FRAME_PC], FCN_NULL },
- { "ps", &ddb_regs.tf_regs[FRAME_PS], FCN_NULL },
- { "ai", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
- { "pv", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
+ { "v0", (db_expr_t *)FRAME_V0, db_frame },
+ { "t0", (db_expr_t *)FRAME_T0, db_frame },
+ { "t1", (db_expr_t *)FRAME_T1, db_frame },
+ { "t2", (db_expr_t *)FRAME_T2, db_frame },
+ { "t3", (db_expr_t *)FRAME_T3, db_frame },
+ { "t4", (db_expr_t *)FRAME_T4, db_frame },
+ { "t5", (db_expr_t *)FRAME_T5, db_frame },
+ { "t6", (db_expr_t *)FRAME_T6, db_frame },
+ { "t7", (db_expr_t *)FRAME_T7, db_frame },
+ { "s0", (db_expr_t *)FRAME_S0, db_frame },
+ { "s1", (db_expr_t *)FRAME_S1, db_frame },
+ { "s2", (db_expr_t *)FRAME_S2, db_frame },
+ { "s3", (db_expr_t *)FRAME_S3, db_frame },
+ { "s4", (db_expr_t *)FRAME_S4, db_frame },
+ { "s5", (db_expr_t *)FRAME_S5, db_frame },
+ { "s6", (db_expr_t *)FRAME_S6, db_frame },
+ { "a0", (db_expr_t *)FRAME_A0, db_frame },
+ { "a1", (db_expr_t *)FRAME_A1, db_frame },
+ { "a2", (db_expr_t *)FRAME_A2, db_frame },
+ { "a3", (db_expr_t *)FRAME_A3, db_frame },
+ { "a4", (db_expr_t *)FRAME_A4, db_frame },
+ { "a5", (db_expr_t *)FRAME_A5, db_frame },
+ { "t8", (db_expr_t *)FRAME_T8, db_frame },
+ { "t9", (db_expr_t *)FRAME_T9, db_frame },
+ { "t10", (db_expr_t *)FRAME_T10, db_frame },
+ { "t11", (db_expr_t *)FRAME_T11, db_frame },
+ { "ra", (db_expr_t *)FRAME_RA, db_frame },
+ { "t12", (db_expr_t *)FRAME_T12, db_frame },
+ { "at", (db_expr_t *)FRAME_AT, db_frame },
+ { "gp", (db_expr_t *)FRAME_GP, db_frame },
+ { "sp", (db_expr_t *)FRAME_SP, db_frame },
+ { "pc", (db_expr_t *)FRAME_PC, db_frame },
+ { "ps", (db_expr_t *)FRAME_PS, db_frame },
+ { "ai", (db_expr_t *)FRAME_T11, db_frame },
+ { "pv", (db_expr_t *)FRAME_T12, db_frame },
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
-/*
- * Print trap reason.
- */
-void
-ddbprinttrap(a0, a1, a2, entry)
- unsigned long a0, a1, a2, entry;
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
{
- /* XXX Implement. */
-
- printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2,
- entry);
-}
-
-/*
- * ddb_trap - field a kernel trap
- */
-int
-kdb_trap(a0, a1, a2, entry, regs)
- unsigned long a0, a1, a2, entry;
- db_regs_t *regs;
-{
- int ddb_mode = !(boothowto & RB_GDB);
- register_t s;
-
- /*
- * Don't bother checking for usermode, since a benign entry
- * by the kernel (call to Debugger() or a breakpoint) has
- * already checked for usermode. If neither of those
- * conditions exist, something Bad has happened.
- */
-
- if (entry != ALPHA_KENTRY_IF ||
- (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT
- && a0 != ALPHA_IF_CODE_GENTRAP)) {
-#if 0
- if (ddb_mode) {
- db_printf("ddbprinttrap from 0x%lx\n", /* XXX */
- regs->tf_regs[FRAME_PC]);
- ddbprinttrap(a0, a1, a2, entry);
- /*
- * Tell caller "We did NOT handle the trap."
- * Caller should panic, or whatever.
- */
- return (0);
- }
-#endif
- if (db_nofault) {
- jmp_buf *no_fault = db_nofault;
- db_nofault = 0;
- longjmp(*no_fault, 1);
- }
- }
-
- /*
- * XXX Should switch to DDB's own stack, here.
- */
-
- ddb_regs = *regs;
-
- s = intr_disable();
-
-#ifdef SMP
-#ifdef DIAGNOSTIC
- db_printf("stopping %x\n", PCPU_GET(other_cpus));
-#endif
- stop_cpus(PCPU_GET(other_cpus));
-#ifdef DIAGNOSTIC
- db_printf("stopped_cpus=%x\n", stopped_cpus);
-#endif
-#endif
-
- db_active++;
-
- if (ddb_mode) {
- cndbctl(TRUE); /* DDB active, unblank video */
- db_trap(entry, a0); /* Where the work happens */
- cndbctl(FALSE); /* DDB inactive */
- } else
- gdb_handle_exception(&ddb_regs, entry, a0);
-
- db_active--;
-
-#ifdef SMP
- restart_cpus(stopped_cpus);
-#endif
-
- intr_restore(s);
-
- *regs = ddb_regs;
-
- /*
- * Tell caller "We HAVE handled the trap."
- */
+ if (kdb_frame == NULL)
+ return (0);
+ if (op == DB_VAR_GET)
+ *valuep = kdb_frame->tf_regs[(uintptr_t)vp->valuep];
+ else
+ kdb_frame->tf_regs[(uintptr_t)vp->valuep] = *valuep;
return (1);
}
/*
* Read bytes from kernel address space for debugger.
*/
-void
-db_read_bytes(addr, size, data)
- vm_offset_t addr;
- register size_t size;
- register char *data;
+int
+db_read_bytes(vm_offset_t addr, size_t size, char *data)
{
- register char *src;
-
- db_nofault = &db_jmpbuf;
-
- src = (char *)addr;
- while (size-- > 0)
- *data++ = *src++;
-
- db_nofault = 0;
+ jmp_buf jb;
+ void *prev_jb;
+ char *src;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ src = (char *)addr;
+ while (size-- > 0)
+ *data++ = *src++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
/*
* Write bytes to kernel address space for debugger.
*/
-void
-db_write_bytes(addr, size, data)
- vm_offset_t addr;
- register size_t size;
- register char *data;
-{
- register char *dst;
-
- db_nofault = &db_jmpbuf;
-
- dst = (char *)addr;
- while (size-- > 0)
- *dst++ = *data++;
- alpha_pal_imb();
-
- db_nofault = 0;
-}
-
-void
-Debugger(const char* msg)
+int
+db_write_bytes(vm_offset_t addr, size_t size, char *data)
{
- u_int saveintr;
-
- printf("%s\n", msg);
- saveintr = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
- __asm("call_pal 0x81"); /* XXX bugchk */
- alpha_pal_swpipl(saveintr);
+ jmp_buf jb;
+ void *prev_jb;
+ char *dst;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ dst = (char *)addr;
+ while (size-- > 0)
+ *dst++ = *data++;
+ alpha_pal_imb();
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
/*
@@ -338,9 +231,7 @@ static int reg_to_frame[32] = {
};
u_long
-db_register_value(regs, regno)
- db_regs_t *regs;
- int regno;
+db_register_value(int regno)
{
if (regno > 31 || regno < 0) {
@@ -351,7 +242,7 @@ db_register_value(regs, regno)
if (regno == 31)
return (0);
- return (regs->tf_regs[reg_to_frame[regno]]);
+ return (kdb_frame->tf_regs[reg_to_frame[regno]]);
}
/*
@@ -446,19 +337,6 @@ db_inst_unconditional_flow_transfer(ins)
return (FALSE);
}
-#if 0
-boolean_t
-db_inst_spill(ins, regn)
- int ins, regn;
-{
- alpha_instruction insn;
-
- insn.bits = ins;
- return ((insn.mem_format.opcode == op_stq) &&
- (insn.mem_format.rd == regn));
-}
-#endif
-
boolean_t
db_inst_load(ins)
int ins;
@@ -520,10 +398,7 @@ db_inst_store(ins)
}
db_addr_t
-db_branch_taken(ins, pc, regs)
- int ins;
- db_addr_t pc;
- db_regs_t *regs;
+db_branch_taken(int ins, db_addr_t pc)
{
alpha_instruction insn;
db_addr_t newpc;
@@ -534,7 +409,7 @@ db_branch_taken(ins, pc, regs)
* Jump format: target PC is (contents of instruction's "RB") & ~3.
*/
case op_j:
- newpc = db_register_value(regs, insn.jump_format.rs) & ~3;
+ newpc = db_register_value(insn.jump_format.rs) & ~3;
break;
/*
diff --git a/sys/alpha/alpha/db_trace.c b/sys/alpha/alpha/db_trace.c
index 6eea6b19ef217..79ed437e0749c 100644
--- a/sys/alpha/alpha/db_trace.c
+++ b/sys/alpha/alpha/db_trace.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/sysent.h>
@@ -60,11 +61,6 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_output.h>
#include <alpha/alpha/db_instruction.h>
-struct trace_request {
- register_t ksp;
- register_t pc;
-};
-
/*
* Information about the `standard' Alpha function prologue.
*/
@@ -186,13 +182,15 @@ sym_is_trapsymbol(uintptr_t v)
}
static void
-decode_syscall(int number, struct proc *p)
+decode_syscall(int number, struct thread *td)
{
+ struct proc *p;
c_db_sym_t sym;
db_expr_t diff;
sy_call_t *f;
const char *symname;
+ p = (td != NULL) ? td->td_proc : NULL;
db_printf(" (%d", number);
if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
f = p->p_sysent->sv_table[number].sy_call;
@@ -205,99 +203,34 @@ decode_syscall(int number, struct proc *p)
db_printf(")");
}
-void
-db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif)
+static int
+db_backtrace(struct thread *td, db_addr_t frame, db_addr_t pc, int count)
{
- db_addr_t callpc = 0, frame = 0, symval;
struct prologue_info pi;
- db_expr_t diff;
+ struct trapframe *tf;
+ const char *symname;
c_db_sym_t sym;
+ db_expr_t diff;
+ db_addr_t symval;
+ u_long last_ipl, tfps;
int i;
- u_long tfps;
- const char *symname;
- struct pcb *pcbp;
- struct trapframe *tf = NULL;
- boolean_t ra_from_tf = FALSE;
- boolean_t ra_from_pcb;
- u_long last_ipl = ~0L;
- struct proc *p = NULL;
- struct thread *td = NULL;
- boolean_t have_trapframe = FALSE;
- pid_t pid;
if (count == -1)
- count = 65535;
-
- if (!have_addr) {
- td = curthread;
- p = td->td_proc;
- addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8;
- tf = (struct trapframe *)addr;
- have_trapframe = 1;
- } else if (addr < KERNBASE) {
- pid = (addr % 16) + ((addr >> 4) % 16) * 10 +
- ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 +
- ((addr >> 16) % 16) * 10000;
- /*
- * The pcb for curproc is not valid at this point,
- * so fall back to the default case.
- */
- if (pid == curthread->td_proc->p_pid) {
- td = curthread;
- p = td->td_proc;
- addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8;
- tf = (struct trapframe *)addr;
- have_trapframe = 1;
- } else {
- /* sx_slock(&allproc_lock); */
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid == pid)
- break;
- }
- /* sx_sunlock(&allproc_lock); */
- if (p == NULL) {
- db_printf("pid %d not found\n", pid);
- return;
- }
- if ((p->p_sflag & PS_INMEM) == 0) {
- db_printf("pid %d swapped out\n", pid);
- return;
- }
- pcbp = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */
- addr = (db_expr_t)pcbp->pcb_hw.apcb_ksp;
- callpc = pcbp->pcb_context[7];
- frame = addr;
- }
- } else {
- struct trace_request *tr;
-
- tr = (struct trace_request *)addr;
- if (tr->ksp < KERNBASE || tr->pc < KERNBASE) {
- db_printf("alpha trace requires known PC =eject=\n");
- return;
- }
- callpc = tr->pc;
- addr = tr->ksp;
- frame = addr;
- }
+ count = 1024;
+ last_ipl = ~0L;
+ tf = NULL;
while (count--) {
- if (have_trapframe) {
- frame = (db_addr_t)tf + FRAME_SIZE * 8;
- callpc = tf->tf_regs[FRAME_PC];
- ra_from_tf = TRUE;
- have_trapframe = 0;
- }
- sym = db_search_symbol(callpc, DB_STGY_ANY, &diff);
+ sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
if (sym == DB_SYM_NULL)
- break;
+ return (ENOENT);
db_symbol_values(sym, &symname, (db_expr_t *)&symval);
- if (callpc < symval) {
- db_printf("symbol botch: callpc 0x%lx < "
- "func 0x%lx (%s)\n", callpc, symval, symname);
- return;
+ if (pc < symval) {
+ db_printf("symbol botch: pc 0x%lx < "
+ "func 0x%lx (%s)\n", pc, symval, symname);
+ return (0);
}
/*
@@ -328,7 +261,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
* debugger (for serious debugging).
*/
db_printf("%s() at ", symname);
- db_printsym(callpc, DB_STGY_PROC);
+ db_printsym(pc, DB_STGY_PROC);
db_printf("\n");
/*
@@ -337,7 +270,6 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
*/
if (sym_is_trapsymbol(symval)) {
tf = (struct trapframe *)frame;
-
for (i = 0; special_symbols[i].ss_val != 0; ++i)
if (symval == special_symbols[i].ss_val)
db_printf("--- %s",
@@ -345,7 +277,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
tfps = tf->tf_regs[FRAME_PS];
if (symval == (uintptr_t)&XentSys)
- decode_syscall(tf->tf_regs[FRAME_V0], p);
+ decode_syscall(tf->tf_regs[FRAME_V0], td);
if ((tfps & ALPHA_PSL_IPL_MASK) != last_ipl) {
last_ipl = tfps & ALPHA_PSL_IPL_MASK;
if (symval != (uintptr_t)&XentSys)
@@ -356,7 +288,8 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
db_printf("--- user mode ---\n");
break; /* Terminate search. */
}
- have_trapframe = 1;
+ frame = (db_addr_t)(tf + 1);
+ pc = tf->tf_regs[FRAME_PC];
continue;
}
@@ -366,8 +299,8 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
*
* XXX How does this interact w/ alloca()?!
*/
- if (decode_prologue(callpc, symval, &pi))
- return;
+ if (decode_prologue(pc, symval, &pi))
+ return (0);
if ((pi.pi_regmask & (1 << 26)) == 0) {
/*
* No saved RA found. We might have RA from
@@ -375,37 +308,56 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
* in a leaf call). If not, we've found the
* root of the call graph.
*/
- if (ra_from_tf)
- callpc = tf->tf_regs[FRAME_RA];
+ if (tf)
+ pc = tf->tf_regs[FRAME_RA];
else {
db_printf("--- root of call graph ---\n");
break;
}
} else
- callpc = *(u_long *)(frame + pi.pi_reg_offset[26]);
- ra_from_tf = ra_from_pcb = FALSE;
-#if 0
- /*
- * The call was actually made at RA - 4; the PC is
- * updated before being stored in RA.
- */
- callpc -= 4;
-#endif
+ pc = *(u_long *)(frame + pi.pi_reg_offset[26]);
frame += pi.pi_frame_size;
+ tf = NULL;
}
+
+ return (0);
}
void
-db_print_backtrace(void)
+db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
+ char *modif)
{
- struct trace_request tr;
+ struct thread *td;
+
+ td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread;
+ if (td == NULL) {
+ db_printf("Thread %d not found\n", (int)addr);
+ return;
+ }
+ db_trace_thread(td, count);
+}
+
+void
+db_trace_self(void)
+{
+ register_t pc, sp;
__asm __volatile(
" mov $30,%0 \n"
" lda %1,1f \n"
"1:\n"
- : "=r" (tr.ksp), "=r" (tr.pc));
- db_stack_trace_cmd((db_addr_t)&tr, 1, -1, NULL);
+ : "=r" (sp), "=r" (pc));
+ db_backtrace(curthread, sp, pc, -1);
+}
+
+int
+db_trace_thread(struct thread *thr, int count)
+{
+ struct pcb *ctx;
+
+ ctx = kdb_thr_ctx(thr);
+ return (db_backtrace(thr, ctx->pcb_hw.apcb_ksp, ctx->pcb_context[7],
+ count));
}
int
diff --git a/sys/alpha/include/db_machdep.h b/sys/alpha/include/db_machdep.h
index d2c4837d21f5f..3f130ab1b94bd 100644
--- a/sys/alpha/include/db_machdep.h
+++ b/sys/alpha/include/db_machdep.h
@@ -31,54 +31,40 @@
#ifndef _ALPHA_DB_MACHDEP_H_
#define _ALPHA_DB_MACHDEP_H_
-/*
- * Machine-dependent defines for new kernel debugger.
- */
-#ifndef KLD_MODULE
-#include "opt_ddb.h"
-#endif
-
#include <sys/param.h>
#include <vm/vm.h>
#include <machine/frame.h>
-#define DB_NO_AOUT
+#define DB_NO_AOUT
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef long db_expr_t; /* expression - signed */
-typedef struct trapframe db_regs_t;
-#ifdef DDB
-extern db_regs_t ddb_regs; /* register state */
-#endif
-#define DDB_REGS (&ddb_regs)
-
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_regs[FRAME_PC])
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_context[7])
#define BKPT_INST 0x00000080 /* breakpoint instruction */
#define BKPT_SIZE (4) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
-#define FIXUP_PC_AFTER_BREAK \
- (ddb_regs.tf_regs[FRAME_PC] -= BKPT_SIZE);
+#define FIXUP_PC_AFTER_BREAK (kdb_frame->tf_regs[FRAME_PC] -= BKPT_SIZE);
#define SOFTWARE_SSTEP 1 /* no hardware support */
-#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \
- (code) == ALPHA_IF_CODE_BPT)
+
+#define IS_BREAKPOINT_TRAP(type, code) \
+ ((type) == ALPHA_KENTRY_IF && (code) == ALPHA_IF_CODE_BPT)
#define IS_WATCHPOINT_TRAP(type, code) 0
/*
* Functions needed for software single-stepping.
*/
-
-boolean_t db_inst_trap_return(int inst);
-boolean_t db_inst_return(int inst);
-boolean_t db_inst_call(int inst);
-boolean_t db_inst_branch(int inst);
-boolean_t db_inst_load(int inst);
-boolean_t db_inst_store(int inst);
-boolean_t db_inst_unconditional_flow_transfer(int inst);
-db_addr_t db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs);
+boolean_t db_inst_trap_return(int inst);
+boolean_t db_inst_return(int inst);
+boolean_t db_inst_call(int inst);
+boolean_t db_inst_branch(int inst);
+boolean_t db_inst_load(int inst);
+boolean_t db_inst_store(int inst);
+boolean_t db_inst_unconditional_flow_transfer(int inst);
+db_addr_t db_branch_taken(int inst, db_addr_t pc);
#define inst_trap_return(ins) db_inst_trap_return(ins)
#define inst_return(ins) db_inst_return(ins)
@@ -88,15 +74,12 @@ db_addr_t db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs);
#define inst_store(ins) db_inst_store(ins)
#define inst_unconditional_flow_transfer(ins) \
db_inst_unconditional_flow_transfer(ins)
-#define branch_taken(ins, pc, regs) \
- db_branch_taken((ins), (pc), (regs))
+#define branch_taken(ins, pc) db_branch_taken(ins, pc)
/* No delay slots on Alpha. */
#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4)))
-u_long db_register_value(db_regs_t *, int);
-int kdb_trap(unsigned long, unsigned long, unsigned long,
- unsigned long, struct trapframe *);
+u_long db_register_value(int);
/*
* Pretty arbitrary
diff --git a/sys/amd64/amd64/db_interface.c b/sys/amd64/amd64/db_interface.c
index f6bf218981930..67c8ae5c6549a 100644
--- a/sys/amd64/amd64/db_interface.c
+++ b/sys/amd64/amd64/db_interface.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/reboot.h>
#include <sys/cons.h>
#include <sys/pcpu.h>
@@ -45,284 +46,95 @@ __FBSDID("$FreeBSD$");
#include <ddb/ddb.h>
-#include <machine/setjmp.h>
-
-static jmp_buf *db_nofault = 0;
-extern jmp_buf db_jmpbuf;
-
-extern void gdb_handle_exception(db_regs_t *, int, int);
-
-int db_active;
-db_regs_t ddb_regs;
-
-static jmp_buf db_global_jmpbuf;
-
-/*
- * kdb_trap - field a TRACE or BPT trap
- */
-int
-kdb_trap(int type, int code, struct amd64_saved_state *regs)
-{
- u_long ef;
- volatile int ddb_mode = !(boothowto & RB_GDB);
-
- /*
- * XXX try to do nothing if the console is in graphics mode.
- * Handle trace traps (and hardware breakpoints...) by ignoring
- * them except for forgetting about them. Return 0 for other
- * traps to say that we haven't done anything. The trap handler
- * will usually panic. We should handle breakpoint traps for
- * our breakpoints by disarming our breakpoints and fixing up
- * %eip.
- */
- if (cnunavailable() != 0 && ddb_mode) {
- if (type == T_TRCTRAP) {
- regs->tf_rflags &= ~PSL_T;
- return (1);
- }
- return (0);
- }
-
- ef = read_rflags();
- disable_intr();
-
-#ifdef SMP
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("\nCPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid),
- PCPU_GET(other_cpus));
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* We stop all CPUs except ourselves (obviously) */
- stop_cpus(PCPU_GET(other_cpus));
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" stopped.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* SMP */
-
- switch (type) {
- case T_BPTFLT: /* breakpoint */
- case T_TRCTRAP: /* debug exception */
- break;
-
- default:
- /*
- * XXX this is almost useless now. In most cases,
- * trap_fatal() has already printed a much more verbose
- * message. However, it is dangerous to print things in
- * trap_fatal() - printf() might be reentered and trap.
- * The debugger should be given control first.
- */
- if (ddb_mode)
- db_printf("kernel: type %d trap, code=%x\n", type, code);
-
- if (db_nofault) {
- jmp_buf *no_fault = db_nofault;
- db_nofault = 0;
- longjmp(*no_fault, 1);
- }
- }
-
- /*
- * This handles unexpected traps in ddb commands, including calls to
- * non-ddb functions. db_nofault only applies to memory accesses by
- * internal ddb commands.
- */
- if (db_active)
- longjmp(db_global_jmpbuf, 1);
-
- /*
- * XXX We really should switch to a local stack here.
- */
- ddb_regs = *regs;
-
- /*
- * If in kernel mode, esp and ss are not saved, so dummy them up.
- */
- if (ISPL(regs->tf_cs) == 0) {
- ddb_regs.tf_rsp = (long)&regs->tf_rsp;
- ddb_regs.tf_ss = rss();
- }
-
- (void) setjmp(db_global_jmpbuf);
- if (ddb_mode) {
- if (!db_active)
- cndbctl(TRUE);
- db_active = 1;
- db_trap(type, code);
- cndbctl(FALSE);
- } else {
- db_active = 1;
- gdb_handle_exception(&ddb_regs, type, code);
- }
- db_active = 0;
-
- regs->tf_rip = ddb_regs.tf_rip;
- regs->tf_rflags = ddb_regs.tf_rflags;
- regs->tf_rax = ddb_regs.tf_rax;
- regs->tf_rcx = ddb_regs.tf_rcx;
- regs->tf_rdx = ddb_regs.tf_rdx;
- regs->tf_rbx = ddb_regs.tf_rbx;
-
- /*
- * If in user mode, the saved ESP and SS were valid, restore them.
- */
- if (ISPL(regs->tf_cs)) {
- regs->tf_rsp = ddb_regs.tf_rsp;
- regs->tf_ss = ddb_regs.tf_ss & 0xffff;
- }
-
- regs->tf_rbp = ddb_regs.tf_rbp;
- regs->tf_rsi = ddb_regs.tf_rsi;
- regs->tf_rdi = ddb_regs.tf_rdi;
-
- regs->tf_r8 = ddb_regs.tf_r8;
- regs->tf_r9 = ddb_regs.tf_r9;
- regs->tf_r10 = ddb_regs.tf_r10;
- regs->tf_r11 = ddb_regs.tf_r11;
- regs->tf_r12 = ddb_regs.tf_r12;
- regs->tf_r13 = ddb_regs.tf_r13;
- regs->tf_r14 = ddb_regs.tf_r14;
- regs->tf_r15 = ddb_regs.tf_r15;
-
-#if 0
- regs->tf_es = ddb_regs.tf_es & 0xffff;
- regs->tf_fs = ddb_regs.tf_fs & 0xffff;
-#endif
- regs->tf_cs = ddb_regs.tf_cs & 0xffff;
-#if 0
- regs->tf_ds = ddb_regs.tf_ds & 0xffff;
-#endif
-
-#ifdef SMP
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("\nCPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid),
- stopped_cpus);
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* Restart all the CPUs we previously stopped */
- if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) {
- db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
- PCPU_GET(other_cpus), stopped_cpus);
- panic("stop_cpus() failed");
- }
- restart_cpus(stopped_cpus);
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" restarted.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* SMP */
-
- write_rflags(ef);
-
- return (1);
-}
-
/*
* Read bytes from kernel address space for debugger.
*/
-void
+int
db_read_bytes(vm_offset_t addr, size_t size, char *data)
{
- char *src;
-
- db_nofault = &db_jmpbuf;
-
- src = (char *)addr;
- while (size-- > 0)
- *data++ = *src++;
-
- db_nofault = 0;
+ jmp_buf jb;
+ void *prev_jb;
+ char *src;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ src = (char *)addr;
+ while (size-- > 0)
+ *data++ = *src++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
/*
* Write bytes to kernel address space for debugger.
*/
-void
+int
db_write_bytes(vm_offset_t addr, size_t size, char *data)
{
- char *dst;
-
+ jmp_buf jb;
+ void *prev_jb;
+ char *dst;
pt_entry_t *ptep0 = NULL;
pt_entry_t oldmap0 = 0;
vm_offset_t addr1;
pt_entry_t *ptep1 = NULL;
pt_entry_t oldmap1 = 0;
-
- db_nofault = &db_jmpbuf;
-
- if (addr > trunc_page((vm_offset_t)btext) - size &&
- addr < round_page((vm_offset_t)etext)) {
-
- ptep0 = vtopte(addr);
- oldmap0 = *ptep0;
- *ptep0 |= PG_RW;
-
- /* Map another page if the data crosses a page boundary. */
- if ((*ptep0 & PG_PS) == 0) {
- addr1 = trunc_page(addr + size - 1);
- if (trunc_page(addr) != addr1) {
- ptep1 = vtopte(addr1);
- oldmap1 = *ptep1;
- *ptep1 |= PG_RW;
- }
- } else {
- addr1 = trunc_2mpage(addr + size - 1);
- if (trunc_2mpage(addr) != addr1) {
- ptep1 = vtopte(addr1);
- oldmap1 = *ptep1;
- *ptep1 |= PG_RW;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ if (addr > trunc_page((vm_offset_t)btext) - size &&
+ addr < round_page((vm_offset_t)etext)) {
+
+ ptep0 = vtopte(addr);
+ oldmap0 = *ptep0;
+ *ptep0 |= PG_RW;
+
+ /*
+ * Map another page if the data crosses a page
+ * boundary.
+ */
+ if ((*ptep0 & PG_PS) == 0) {
+ addr1 = trunc_page(addr + size - 1);
+ if (trunc_page(addr) != addr1) {
+ ptep1 = vtopte(addr1);
+ oldmap1 = *ptep1;
+ *ptep1 |= PG_RW;
+ }
+ } else {
+ addr1 = trunc_2mpage(addr + size - 1);
+ if (trunc_2mpage(addr) != addr1) {
+ ptep1 = vtopte(addr1);
+ oldmap1 = *ptep1;
+ *ptep1 |= PG_RW;
+ }
+ }
+
+ invltlb();
}
- }
-
- invltlb();
- }
- dst = (char *)addr;
+ dst = (char *)addr;
- while (size-- > 0)
- *dst++ = *data++;
+ while (size-- > 0)
+ *dst++ = *data++;
+ }
- db_nofault = 0;
+ (void)kdb_jmpbuf(prev_jb);
if (ptep0) {
- *ptep0 = oldmap0;
+ *ptep0 = oldmap0;
- if (ptep1)
- *ptep1 = oldmap1;
+ if (ptep1)
+ *ptep1 = oldmap1;
- invltlb();
+ invltlb();
}
-}
-/*
- * XXX
- * Move this to machdep.c and allow it to be called if any debugger is
- * installed.
- */
-void
-Debugger(const char *msg)
-{
- static volatile u_int in_Debugger;
-
- /*
- * XXX
- * Do nothing if the console is in graphics mode. This is
- * OK if the call is for the debugger hotkey but not if the call
- * is a weak form of panicing.
- */
- if (cnunavailable() != 0 && !(boothowto & RB_GDB))
- return;
-
- if (atomic_cmpset_acq_int(&in_Debugger, 0, 1)) {
- db_printf("Debugger(\"%s\")\n", msg);
- breakpoint();
- atomic_store_rel_int(&in_Debugger, 0);
- }
+ return (ret);
}
void
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 6df1bd10034b2..03842cb530eb7 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/proc.h>
#include <sys/sysent.h>
@@ -46,56 +47,134 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
-db_varfcn_t db_dr0;
-db_varfcn_t db_dr1;
-db_varfcn_t db_dr2;
-db_varfcn_t db_dr3;
-db_varfcn_t db_dr4;
-db_varfcn_t db_dr5;
-db_varfcn_t db_dr6;
-db_varfcn_t db_dr7;
+static db_varfcn_t db_dr0;
+static db_varfcn_t db_dr1;
+static db_varfcn_t db_dr2;
+static db_varfcn_t db_dr3;
+static db_varfcn_t db_dr4;
+static db_varfcn_t db_dr5;
+static db_varfcn_t db_dr6;
+static db_varfcn_t db_dr7;
+static db_varfcn_t db_frame;
+static db_varfcn_t db_rsp;
+static db_varfcn_t db_ss;
/*
* Machine register set.
*/
+#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
- { "cs", &ddb_regs.tf_cs, FCN_NULL },
+ { "cs", DB_OFFSET(tf_cs), db_frame },
#if 0
- { "ds", &ddb_regs.tf_ds, FCN_NULL },
- { "es", &ddb_regs.tf_es, FCN_NULL },
- { "fs", &ddb_regs.tf_fs, FCN_NULL },
- { "gs", &ddb_regs.tf_gs, FCN_NULL },
+ { "ds", DB_OFFSET(tf_ds), db_frame },
+ { "es", DB_OFFSET(tf_es), db_frame },
+ { "fs", DB_OFFSET(tf_fs), db_frame },
+ { "gs", DB_OFFSET(tf_gs), db_frame },
#endif
- { "ss", &ddb_regs.tf_ss, FCN_NULL },
- { "rax", &ddb_regs.tf_rax, FCN_NULL },
- { "rcx", &ddb_regs.tf_rcx, FCN_NULL },
- { "rdx", &ddb_regs.tf_rdx, FCN_NULL },
- { "rbx", &ddb_regs.tf_rbx, FCN_NULL },
- { "rsp", &ddb_regs.tf_rsp, FCN_NULL },
- { "rbp", &ddb_regs.tf_rbp, FCN_NULL },
- { "rsi", &ddb_regs.tf_rsi, FCN_NULL },
- { "rdi", &ddb_regs.tf_rdi, FCN_NULL },
- { "r8", &ddb_regs.tf_r8, FCN_NULL },
- { "r9", &ddb_regs.tf_r9, FCN_NULL },
- { "r10", &ddb_regs.tf_r10, FCN_NULL },
- { "r11", &ddb_regs.tf_r11, FCN_NULL },
- { "r12", &ddb_regs.tf_r12, FCN_NULL },
- { "r13", &ddb_regs.tf_r13, FCN_NULL },
- { "r14", &ddb_regs.tf_r14, FCN_NULL },
- { "r15", &ddb_regs.tf_r15, FCN_NULL },
- { "rip", &ddb_regs.tf_rip, FCN_NULL },
- { "rflags", &ddb_regs.tf_rflags, FCN_NULL },
- { "dr0", NULL, db_dr0 },
- { "dr1", NULL, db_dr1 },
- { "dr2", NULL, db_dr2 },
- { "dr3", NULL, db_dr3 },
- { "dr4", NULL, db_dr4 },
- { "dr5", NULL, db_dr5 },
- { "dr6", NULL, db_dr6 },
- { "dr7", NULL, db_dr7 },
+ { "ss", NULL, db_ss },
+ { "rax", DB_OFFSET(tf_rax), db_frame },
+ { "rcx", DB_OFFSET(tf_rcx), db_frame },
+ { "rdx", DB_OFFSET(tf_rdx), db_frame },
+ { "rbx", DB_OFFSET(tf_rbx), db_frame },
+ { "rsp", NULL, db_rsp },
+ { "rbp", DB_OFFSET(tf_rbp), db_frame },
+ { "rsi", DB_OFFSET(tf_rsi), db_frame },
+ { "rdi", DB_OFFSET(tf_rdi), db_frame },
+ { "r8", DB_OFFSET(tf_r8), db_frame },
+ { "r9", DB_OFFSET(tf_r9), db_frame },
+ { "r10", DB_OFFSET(tf_r10), db_frame },
+ { "r11", DB_OFFSET(tf_r11), db_frame },
+ { "r12", DB_OFFSET(tf_r12), db_frame },
+ { "r13", DB_OFFSET(tf_r13), db_frame },
+ { "r14", DB_OFFSET(tf_r14), db_frame },
+ { "r15", DB_OFFSET(tf_r15), db_frame },
+ { "rip", DB_OFFSET(tf_rip), db_frame },
+ { "rflags", DB_OFFSET(tf_rflags), db_frame },
+ { "dr0", NULL, db_dr0 },
+ { "dr1", NULL, db_dr1 },
+ { "dr2", NULL, db_dr2 },
+ { "dr3", NULL, db_dr3 },
+ { "dr4", NULL, db_dr4 },
+ { "dr5", NULL, db_dr5 },
+ { "dr6", NULL, db_dr6 },
+ { "dr7", NULL, db_dr7 },
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+#define DB_DRX_FUNC(reg) \
+static int \
+db_ ## reg (vp, valuep, op) \
+ struct db_variable *vp; \
+ db_expr_t * valuep; \
+ int op; \
+{ \
+ if (op == DB_VAR_GET) \
+ *valuep = r ## reg (); \
+ else \
+ load_ ## reg (*valuep); \
+ return (1); \
+}
+
+DB_DRX_FUNC(dr0)
+DB_DRX_FUNC(dr1)
+DB_DRX_FUNC(dr2)
+DB_DRX_FUNC(dr3)
+DB_DRX_FUNC(dr4)
+DB_DRX_FUNC(dr5)
+DB_DRX_FUNC(dr6)
+DB_DRX_FUNC(dr7)
+
+static __inline long
+get_rsp(struct trapframe *tf)
+{
+ return ((ISPL(tf->tf_cs)) ? tf->tf_rsp :
+ (db_expr_t)tf + offsetof(struct trapframe, tf_rsp));
+}
+
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+ long *reg;
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+ if (op == DB_VAR_GET)
+ *valuep = *reg;
+ else
+ *reg = *valuep;
+ return (1);
+}
+
+static int
+db_rsp(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ if (op == DB_VAR_GET)
+ *valuep = get_rsp(kdb_frame);
+ else if (ISPL(kdb_frame->tf_cs))
+ kdb_frame->tf_rsp = *valuep;
+ return (1);
+}
+
+static int
+db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ if (op == DB_VAR_GET)
+ *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
+ else if (ISPL(kdb_frame->tf_cs))
+ kdb_frame->tf_ss = *valuep;
+ return (1);
+}
+
/*
* Stack trace.
*/
@@ -112,13 +191,10 @@ struct amd64_frame {
#define INTERRUPT 2
#define SYSCALL 3
-static void db_nextframe(struct amd64_frame **, db_addr_t *, struct proc *);
+static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
static int db_numargs(struct amd64_frame *);
static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t);
-static void decode_syscall(int, struct proc *);
-static void db_trace_one_stack(int count, boolean_t have_addr,
- struct proc *p, struct amd64_frame *frame, db_addr_t callpc);
-
+static void decode_syscall(int, struct thread *);
static char * watchtype_str(int type);
int amd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
@@ -128,7 +204,6 @@ int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
void db_md_list_watchpoints(void);
-
/*
* Figure out how many arguments were passed into the frame at "fp".
*/
@@ -189,16 +264,16 @@ db_print_stack_entry(name, narg, argnp, argp, callpc)
}
static void
-decode_syscall(number, p)
- int number;
- struct proc *p;
+decode_syscall(int number, struct thread *td)
{
+ struct proc *p;
c_db_sym_t sym;
db_expr_t diff;
sy_call_t *f;
const char *symname;
db_printf(" (%d", number);
+ p = (td != NULL) ? td->td_proc : NULL;
if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
f = p->p_sysent->sv_table[number].sy_call;
sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff);
@@ -214,10 +289,7 @@ decode_syscall(number, p)
* Figure out the next frame up in the call stack.
*/
static void
-db_nextframe(fp, ip, p)
- struct amd64_frame **fp; /* in/out */
- db_addr_t *ip; /* out */
- struct proc *p; /* in */
+db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
{
struct trapframe *tf;
int frame_type;
@@ -265,8 +337,7 @@ db_nextframe(fp, ip, p)
tf = (struct trapframe *)((long)*fp + 16);
if (INKERNEL((long) tf)) {
- rsp = (ISPL(tf->tf_cs) == SEL_UPL) ?
- tf->tf_rsp : (long)&tf->tf_rsp;
+ rsp = get_rsp(tf);
rip = tf->tf_rip;
rbp = tf->tf_rbp;
switch (frame_type) {
@@ -275,7 +346,7 @@ db_nextframe(fp, ip, p)
break;
case SYSCALL:
db_printf("--- syscall");
- decode_syscall(tf->tf_rax, p);
+ decode_syscall(tf->tf_rax, td);
break;
case INTERRUPT:
db_printf("--- interrupt");
@@ -291,135 +362,26 @@ db_nextframe(fp, ip, p)
*fp = (struct amd64_frame *) rbp;
}
-void
-db_stack_trace_cmd(addr, have_addr, count, modif)
- db_expr_t addr;
- boolean_t have_addr;
- db_expr_t count;
- char *modif;
+static int
+db_backtrace(struct thread *td, struct trapframe *tf,
+ struct amd64_frame *frame, db_addr_t pc, int count)
{
- struct amd64_frame *frame;
- struct proc *p;
- struct pcb *pcb;
- struct thread *td;
- db_addr_t callpc;
- pid_t pid;
+ struct amd64_frame *actframe;
+#define MAXNARG 16
+ char *argnames[MAXNARG], **argnp = NULL;
+ const char *name;
+ long *argp;
+ db_expr_t offset;
+ c_db_sym_t sym;
+ int narg;
+ boolean_t first;
if (count == -1)
count = 1024;
- if (!have_addr) {
- td = curthread;
- p = td->td_proc;
- frame = (struct amd64_frame *)ddb_regs.tf_rbp;
- if (frame == NULL)
- frame = (struct amd64_frame *)(ddb_regs.tf_rsp - 8);
- callpc = (db_addr_t)ddb_regs.tf_rip;
- } else if (!INKERNEL(addr)) {
- pid = (addr % 16) + ((addr >> 4) % 16) * 10 +
- ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 +
- ((addr >> 16) % 16) * 10000;
- /*
- * The pcb for curproc is not valid at this point,
- * so fall back to the default case.
- */
- if (pid == curthread->td_proc->p_pid) {
- td = curthread;
- p = td->td_proc;
- frame = (struct amd64_frame *)ddb_regs.tf_rbp;
- if (frame == NULL)
- frame = (struct amd64_frame *)
- (ddb_regs.tf_rsp - 8);
- callpc = (db_addr_t)ddb_regs.tf_rip;
- } else {
-
- /* sx_slock(&allproc_lock); */
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid == pid)
- break;
- }
- /* sx_sunlock(&allproc_lock); */
- if (p == NULL) {
- db_printf("pid %d not found\n", pid);
- return;
- }
- if ((p->p_sflag & PS_INMEM) == 0) {
- db_printf("pid %d swapped out\n", pid);
- return;
- }
- pcb = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */
- frame = (struct amd64_frame *)pcb->pcb_rbp;
- if (frame == NULL)
- frame = (struct amd64_frame *)
- (pcb->pcb_rsp - 8);
- callpc = (db_addr_t)pcb->pcb_rip;
- }
- } else {
- p = NULL;
- frame = (struct amd64_frame *)addr;
- callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
- frame = frame->f_frame;
- }
- db_trace_one_stack(count, have_addr, p, frame, callpc);
-}
-
-void
-db_stack_thread(db_expr_t addr, boolean_t have_addr,
- db_expr_t count, char *modif)
-{
- struct amd64_frame *frame;
- struct thread *td;
- struct proc *p;
- struct pcb *pcb;
- db_addr_t callpc;
-
- if (!have_addr)
- return;
- if (!INKERNEL(addr)) {
- printf("bad thread address");
- return;
- }
- td = (struct thread *)addr;
- /* quick sanity check */
- if ((p = td->td_proc) != td->td_ksegrp->kg_proc)
- return;
- if (TD_IS_SWAPPED(td)) {
- db_printf("thread at %p swapped out\n", td);
- return;
- }
- if (td == curthread) {
- frame = (struct amd64_frame *)ddb_regs.tf_rbp;
- if (frame == NULL)
- frame = (struct amd64_frame *)(ddb_regs.tf_rsp - 8);
- callpc = (db_addr_t)ddb_regs.tf_rip;
- } else {
- pcb = td->td_pcb;
- frame = (struct amd64_frame *)pcb->pcb_rbp;
- if (frame == NULL)
- frame = (struct amd64_frame *) (pcb->pcb_rsp - 8);
- callpc = (db_addr_t)pcb->pcb_rip;
- }
- db_trace_one_stack(count, have_addr, p, frame, callpc);
-}
-
-static void
-db_trace_one_stack(int count, boolean_t have_addr,
- struct proc *p, struct amd64_frame *frame, db_addr_t callpc)
-{
- long *argp;
- boolean_t first;
-
first = TRUE;
while (count--) {
- struct amd64_frame *actframe;
- int narg;
- const char * name;
- db_expr_t offset;
- c_db_sym_t sym;
-#define MAXNARG 16
- char *argnames[MAXNARG], **argnp = NULL;
-
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
/*
@@ -435,37 +397,33 @@ db_trace_one_stack(int count, boolean_t have_addr,
*/
actframe = frame;
if (first) {
- if (!have_addr) {
+ if (tf != NULL) {
int instr;
- instr = db_get_value(callpc, 4, FALSE);
+ instr = db_get_value(pc, 4, FALSE);
if ((instr & 0xffffffff) == 0xe5894855) {
/* pushq %rbp; movq %rsp, %rbp */
- actframe = (struct amd64_frame *)
- (ddb_regs.tf_rsp - 8);
- } else if ((instr & 0x00ffffff) == 0x00e58948) {
+ actframe = (void *)(get_rsp(tf) - 8);
+ } else if ((instr & 0xffffff) == 0xe58948) {
/* movq %rsp, %rbp */
- actframe = (struct amd64_frame *)
- ddb_regs.tf_rsp;
- if (ddb_regs.tf_rbp == 0) {
- /* Fake caller's frame better. */
+ actframe = (void *)get_rsp(tf);
+ if (tf->tf_rbp == 0) {
+ /* Fake frame better. */
frame = actframe;
}
- } else if ((instr & 0x000000ff) == 0x000000c3) {
+ } else if ((instr & 0xff) == 0xc3) {
/* ret */
- actframe = (struct amd64_frame *)
- (ddb_regs.tf_rsp - 8);
+ actframe = (void *)(get_rsp(tf) - 8);
} else if (offset == 0) {
- /* Probably a symbol in assembler code. */
- actframe = (struct amd64_frame *)
- (ddb_regs.tf_rsp - 8);
+ /* Probably an assembler symbol. */
+ actframe = (void *)(get_rsp(tf) - 8);
}
} else if (strcmp(name, "fork_trampoline") == 0) {
/*
* Don't try to walk back on a stack for a
* process that hasn't actually been run yet.
*/
- db_print_stack_entry(name, 0, 0, 0, callpc);
+ db_print_stack_entry(name, 0, 0, 0, pc);
break;
}
first = FALSE;
@@ -479,60 +437,68 @@ db_trace_one_stack(int count, boolean_t have_addr,
narg = db_numargs(frame);
}
- db_print_stack_entry(name, narg, argnp, argp, callpc);
+ db_print_stack_entry(name, narg, argnp, argp, pc);
if (actframe != frame) {
/* `frame' belongs to caller. */
- callpc = (db_addr_t)
+ pc = (db_addr_t)
db_get_value((long)&actframe->f_retaddr, 8, FALSE);
continue;
}
- db_nextframe(&frame, &callpc, p);
+ db_nextframe(&frame, &pc, td);
- if (INKERNEL((long) callpc) && !INKERNEL((long) frame)) {
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ if (INKERNEL((long)pc) && !INKERNEL((long)frame)) {
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
- db_print_stack_entry(name, 0, 0, 0, callpc);
+ db_print_stack_entry(name, 0, 0, 0, pc);
break;
}
if (!INKERNEL((long) frame)) {
break;
}
}
+
+ return (0);
+}
+
+void
+db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
+ char *modif)
+{
+ struct thread *td;
+
+ td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread;
+ if (td == NULL) {
+ db_printf("Thread %ld not found\n", addr);
+ return;
+ }
+ db_trace_thread(td, count);
}
void
-db_print_backtrace(void)
+db_trace_self(void)
{
- register_t ebp;
+ struct amd64_frame *frame;
+ db_addr_t callpc;
+ register_t rbp;
- __asm __volatile("movq %%rbp,%0" : "=r" (ebp));
- db_stack_trace_cmd(ebp, 1, -1, NULL);
+ __asm __volatile("movq %%rbp,%0" : "=r" (rbp));
+ frame = (struct amd64_frame *)rbp;
+ callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
+ frame = frame->f_frame;
+ db_backtrace(curthread, NULL, frame, callpc, -1);
}
-#define DB_DRX_FUNC(reg) \
-int \
-db_ ## reg (vp, valuep, op) \
- struct db_variable *vp; \
- db_expr_t * valuep; \
- int op; \
-{ \
- if (op == DB_VAR_GET) \
- *valuep = r ## reg (); \
- else \
- load_ ## reg (*valuep); \
- return (0); \
-}
+int
+db_trace_thread(struct thread *thr, int count)
+{
+ struct pcb *ctx;
-DB_DRX_FUNC(dr0)
-DB_DRX_FUNC(dr1)
-DB_DRX_FUNC(dr2)
-DB_DRX_FUNC(dr3)
-DB_DRX_FUNC(dr4)
-DB_DRX_FUNC(dr5)
-DB_DRX_FUNC(dr6)
-DB_DRX_FUNC(dr7)
+ ctx = kdb_thr_ctx(thr);
+ return (db_backtrace(thr, NULL, (struct amd64_frame *)ctx->pcb_rbp,
+ ctx->pcb_rip, count));
+}
int
amd64_set_watch(watchnum, watchaddr, size, access, d)
diff --git a/sys/amd64/include/db_machdep.h b/sys/amd64/include/db_machdep.h
index 18b5e5d981f51..0a737ebb64bf8 100644
--- a/sys/amd64/include/db_machdep.h
+++ b/sys/amd64/include/db_machdep.h
@@ -30,30 +30,23 @@
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
-#include <machine/psl.h>
#include <machine/trap.h>
-#define amd64_saved_state trapframe
-
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef long db_expr_t; /* expression - signed */
-typedef struct amd64_saved_state db_regs_t;
-extern db_regs_t ddb_regs; /* register state */
-#define DDB_REGS (&ddb_regs)
-
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_rip)
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_rip)
#define BKPT_INST 0xcc /* breakpoint instruction */
#define BKPT_SIZE (1) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
-#define BKPT_SKIP ddb_regs.tf_rip += 1
+#define BKPT_SKIP kdb_frame->tf_rip += 1
-#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_rip -= 1;
+#define FIXUP_PC_AFTER_BREAK kdb_frame->tf_rip -= 1;
-#define db_clear_single_step(regs) ((regs)->tf_rflags &= ~PSL_T)
-#define db_set_single_step(regs) ((regs)->tf_rflags |= PSL_T)
+#define db_clear_single_step kdb_cpu_clear_singlestep
+#define db_set_single_step kdb_cpu_set_singlestep
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
/*
diff --git a/sys/conf/files b/sys/conf/files
index 32ece0714a979..811f502f92012 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -249,25 +249,23 @@ crypto/rijndael/rijndael-api.c optional ipsec
opencrypto/rmd160.c optional ipsec
crypto/sha1.c optional ipsec
crypto/sha2/sha2.c optional ipsec
-ddb/db_access.c optional ddb
-ddb/db_break.c optional ddb
-ddb/db_command.c optional ddb
-ddb/db_elf.c optional ddb
-ddb/db_examine.c optional ddb
-ddb/db_expr.c optional ddb
-ddb/db_input.c optional ddb
-ddb/db_kld.c optional ddb
-ddb/db_lex.c optional ddb
-ddb/db_output.c optional ddb
-ddb/db_print.c optional ddb
-ddb/db_ps.c optional ddb
-ddb/db_run.c optional ddb
-ddb/db_sym.c optional ddb
-ddb/db_sysctl.c optional ddb
-ddb/db_trap.c optional ddb
-ddb/db_variables.c optional ddb
-ddb/db_watch.c optional ddb
-ddb/db_write_cmd.c optional ddb
+ddb/db_access.c optional ddb
+ddb/db_break.c optional ddb
+ddb/db_command.c optional ddb
+ddb/db_examine.c optional ddb
+ddb/db_expr.c optional ddb
+ddb/db_input.c optional ddb
+ddb/db_lex.c optional ddb
+ddb/db_main.c optional ddb
+ddb/db_output.c optional ddb
+ddb/db_print.c optional ddb
+ddb/db_ps.c optional ddb
+ddb/db_run.c optional ddb
+ddb/db_sym.c optional ddb
+ddb/db_thread.c optional ddb
+ddb/db_variables.c optional ddb
+ddb/db_watch.c optional ddb
+ddb/db_write_cmd.c optional ddb
dev/aac/aac.c optional aac
dev/aac/aac_debug.c optional aac
dev/aac/aac_disk.c optional aac
diff --git a/sys/ddb/db_access.c b/sys/ddb/db_access.c
index 15545deef6f25..d8224ada5a521 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 577e338c600a5..78f4f4f3039e9 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 70b35568dd754..954a0d3951b8f 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 0000000000000..32dd347afdca2
--- /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 464d9162cfe75..ff2734caad8c3 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 60282ad08278d..b173c8ca95e39 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 f146cb380555f..47d4c7dc6e0b8 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 79b148af4f62e..ab589d3870056 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 0000000000000..b58f0b09a7d30
--- /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 1b283763e1770..cf8e2e73423c3 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 6c05118efdd5a..7f7a463bdcfea 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 1ef452cfd440d..c1ffff9c41d14 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_ */
diff --git a/sys/i386/i386/db_interface.c b/sys/i386/i386/db_interface.c
index a528502f2413d..02cf974f55841 100644
--- a/sys/i386/i386/db_interface.c
+++ b/sys/i386/i386/db_interface.c
@@ -32,290 +32,107 @@ __FBSDID("$FreeBSD$");
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/reboot.h>
#include <sys/cons.h>
+#include <sys/kdb.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
-#include <sys/smp.h>
#include <machine/cpu.h>
-#ifdef SMP
-#include <machine/smptests.h> /** CPUSTOP_ON_DDBBREAK */
-#endif
#include <vm/vm.h>
#include <vm/pmap.h>
#include <ddb/ddb.h>
-#include <machine/setjmp.h>
-
-static jmp_buf *db_nofault = 0;
-extern jmp_buf db_jmpbuf;
-
-extern void gdb_handle_exception(db_regs_t *, int, int);
-
-int db_active;
-db_regs_t ddb_regs;
-
-static jmp_buf db_global_jmpbuf;
-
-/*
- * kdb_trap - field a TRACE or BPT trap
- */
-int
-kdb_trap(int type, int code, struct i386_saved_state *regs)
-{
- u_int ef;
- volatile int ddb_mode = !(boothowto & RB_GDB);
-
- /*
- * XXX try to do nothing if the console is in graphics mode.
- * Handle trace traps (and hardware breakpoints...) by ignoring
- * them except for forgetting about them. Return 0 for other
- * traps to say that we haven't done anything. The trap handler
- * will usually panic. We should handle breakpoint traps for
- * our breakpoints by disarming our breakpoints and fixing up
- * %eip.
- */
- if (cnunavailable() != 0 && ddb_mode) {
- if (type == T_TRCTRAP) {
- regs->tf_eflags &= ~PSL_T;
- return (1);
- }
- return (0);
- }
-
- ef = read_eflags();
- disable_intr();
-
-#ifdef SMP
-#ifdef CPUSTOP_ON_DDBBREAK
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("\nCPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid),
- PCPU_GET(other_cpus));
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* We stop all CPUs except ourselves (obviously) */
- stop_cpus(PCPU_GET(other_cpus));
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" stopped.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* CPUSTOP_ON_DDBBREAK */
-#endif /* SMP */
-
- switch (type) {
- case T_BPTFLT: /* breakpoint */
- case T_TRCTRAP: /* debug exception */
- break;
-
- default:
- /*
- * XXX this is almost useless now. In most cases,
- * trap_fatal() has already printed a much more verbose
- * message. However, it is dangerous to print things in
- * trap_fatal() - printf() might be reentered and trap.
- * The debugger should be given control first.
- */
- if (ddb_mode)
- db_printf("kernel: type %d trap, code=%x\n", type, code);
-
- if (db_nofault) {
- jmp_buf *no_fault = db_nofault;
- db_nofault = 0;
- longjmp(*no_fault, 1);
- }
- }
-
- /*
- * This handles unexpected traps in ddb commands, including calls to
- * non-ddb functions. db_nofault only applies to memory accesses by
- * internal ddb commands.
- */
- if (db_active)
- longjmp(db_global_jmpbuf, 1);
-
- /*
- * XXX We really should switch to a local stack here.
- */
- ddb_regs = *regs;
-
- /*
- * If in kernel mode, esp and ss are not saved, so dummy them up.
- */
- if (ISPL(regs->tf_cs) == 0) {
- ddb_regs.tf_esp = (int)&regs->tf_esp;
- ddb_regs.tf_ss = rss();
- }
-
- (void) setjmp(db_global_jmpbuf);
- if (ddb_mode) {
- if (!db_active)
- cndbctl(TRUE);
- db_active = 1;
- db_trap(type, code);
- cndbctl(FALSE);
- } else {
- db_active = 1;
- gdb_handle_exception(&ddb_regs, type, code);
- }
- db_active = 0;
-
- regs->tf_eip = ddb_regs.tf_eip;
- regs->tf_eflags = ddb_regs.tf_eflags;
- regs->tf_eax = ddb_regs.tf_eax;
- regs->tf_ecx = ddb_regs.tf_ecx;
- regs->tf_edx = ddb_regs.tf_edx;
- regs->tf_ebx = ddb_regs.tf_ebx;
-
- /*
- * If in user mode, the saved ESP and SS were valid, restore them.
- */
- if (ISPL(regs->tf_cs)) {
- regs->tf_esp = ddb_regs.tf_esp;
- regs->tf_ss = ddb_regs.tf_ss & 0xffff;
- }
-
- regs->tf_ebp = ddb_regs.tf_ebp;
- regs->tf_esi = ddb_regs.tf_esi;
- regs->tf_edi = ddb_regs.tf_edi;
- regs->tf_es = ddb_regs.tf_es & 0xffff;
- regs->tf_fs = ddb_regs.tf_fs & 0xffff;
- regs->tf_cs = ddb_regs.tf_cs & 0xffff;
- regs->tf_ds = ddb_regs.tf_ds & 0xffff;
-
-#ifdef SMP
-#ifdef CPUSTOP_ON_DDBBREAK
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("\nCPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid),
- stopped_cpus);
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* Restart all the CPUs we previously stopped */
- if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) {
- db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
- PCPU_GET(other_cpus), stopped_cpus);
- panic("stop_cpus() failed");
- }
- restart_cpus(stopped_cpus);
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" restarted.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* CPUSTOP_ON_DDBBREAK */
-#endif /* SMP */
-
- write_eflags(ef);
-
- return (1);
-}
-
/*
* Read bytes from kernel address space for debugger.
*/
-void
+int
db_read_bytes(vm_offset_t addr, size_t size, char *data)
{
- char *src;
-
- db_nofault = &db_jmpbuf;
-
- src = (char *)addr;
- while (size-- > 0)
- *data++ = *src++;
-
- db_nofault = 0;
+ jmp_buf jb;
+ void *prev_jb;
+ char *src;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ src = (char *)addr;
+ while (size-- > 0)
+ *data++ = *src++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
/*
* Write bytes to kernel address space for debugger.
*/
-void
+int
db_write_bytes(vm_offset_t addr, size_t size, char *data)
{
- char *dst;
-
- pt_entry_t *ptep0 = NULL;
- pt_entry_t oldmap0 = 0;
- vm_offset_t addr1;
- pt_entry_t *ptep1 = NULL;
- pt_entry_t oldmap1 = 0;
-
- db_nofault = &db_jmpbuf;
-
- if (addr > trunc_page((vm_offset_t)btext) - size &&
- addr < round_page((vm_offset_t)etext)) {
-
- ptep0 = pmap_pte(kernel_pmap, addr);
- oldmap0 = *ptep0;
- *ptep0 |= PG_RW;
-
- /* Map another page if the data crosses a page boundary. */
- if ((*ptep0 & PG_PS) == 0) {
- addr1 = trunc_page(addr + size - 1);
- if (trunc_page(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
- oldmap1 = *ptep1;
- *ptep1 |= PG_RW;
- }
- } else {
- addr1 = trunc_4mpage(addr + size - 1);
- if (trunc_4mpage(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
- oldmap1 = *ptep1;
- *ptep1 |= PG_RW;
+ jmp_buf jb;
+ void *prev_jb;
+ char *dst;
+ pt_entry_t *ptep0 = NULL;
+ pt_entry_t oldmap0 = 0;
+ vm_offset_t addr1;
+ pt_entry_t *ptep1 = NULL;
+ pt_entry_t oldmap1 = 0;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ if (addr > trunc_page((vm_offset_t)btext) - size &&
+ addr < round_page((vm_offset_t)etext)) {
+
+ ptep0 = pmap_pte(kernel_pmap, addr);
+ oldmap0 = *ptep0;
+ *ptep0 |= PG_RW;
+
+ /*
+ * Map another page if the data crosses a page
+ * boundary.
+ */
+ if ((*ptep0 & PG_PS) == 0) {
+ addr1 = trunc_page(addr + size - 1);
+ if (trunc_page(addr) != addr1) {
+ ptep1 = pmap_pte(kernel_pmap, addr1);
+ oldmap1 = *ptep1;
+ *ptep1 |= PG_RW;
+ }
+ } else {
+ addr1 = trunc_4mpage(addr + size - 1);
+ if (trunc_4mpage(addr) != addr1) {
+ ptep1 = pmap_pte(kernel_pmap, addr1);
+ oldmap1 = *ptep1;
+ *ptep1 |= PG_RW;
+ }
+ }
+
+ invltlb();
}
- }
-
- invltlb();
- }
- dst = (char *)addr;
+ dst = (char *)addr;
- while (size-- > 0)
- *dst++ = *data++;
+ while (size-- > 0)
+ *dst++ = *data++;
+ }
- db_nofault = 0;
+ (void)kdb_jmpbuf(prev_jb);
if (ptep0) {
- *ptep0 = oldmap0;
+ *ptep0 = oldmap0;
- if (ptep1)
- *ptep1 = oldmap1;
+ if (ptep1)
+ *ptep1 = oldmap1;
- invltlb();
+ invltlb();
}
-}
-
-/*
- * XXX
- * Move this to machdep.c and allow it to be called if any debugger is
- * installed.
- */
-void
-Debugger(const char *msg)
-{
- static volatile u_int in_Debugger;
- /*
- * XXX
- * Do nothing if the console is in graphics mode. This is
- * OK if the call is for the debugger hotkey but not if the call
- * is a weak form of panicing.
- */
- if (cnunavailable() != 0 && !(boothowto & RB_GDB))
- return;
-
- if (atomic_cmpset_acq_int(&in_Debugger, 0, 1)) {
- db_printf("Debugger(\"%s\")\n", msg);
- breakpoint();
- atomic_store_rel_int(&in_Debugger, 0);
- }
+ return (ret);
}
void
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index 84ed2d9a0404a..aaf11e0ce96bf 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/proc.h>
#include <sys/sysent.h>
@@ -46,48 +47,123 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
-db_varfcn_t db_dr0;
-db_varfcn_t db_dr1;
-db_varfcn_t db_dr2;
-db_varfcn_t db_dr3;
-db_varfcn_t db_dr4;
-db_varfcn_t db_dr5;
-db_varfcn_t db_dr6;
-db_varfcn_t db_dr7;
+static db_varfcn_t db_dr0;
+static db_varfcn_t db_dr1;
+static db_varfcn_t db_dr2;
+static db_varfcn_t db_dr3;
+static db_varfcn_t db_dr4;
+static db_varfcn_t db_dr5;
+static db_varfcn_t db_dr6;
+static db_varfcn_t db_dr7;
+static db_varfcn_t db_esp;
+static db_varfcn_t db_frame;
+static db_varfcn_t db_ss;
/*
* Machine register set.
*/
+#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
- { "cs", &ddb_regs.tf_cs, FCN_NULL },
- { "ds", &ddb_regs.tf_ds, FCN_NULL },
- { "es", &ddb_regs.tf_es, FCN_NULL },
- { "fs", &ddb_regs.tf_fs, FCN_NULL },
-#if 0
- { "gs", &ddb_regs.tf_gs, FCN_NULL },
-#endif
- { "ss", &ddb_regs.tf_ss, FCN_NULL },
- { "eax", &ddb_regs.tf_eax, FCN_NULL },
- { "ecx", &ddb_regs.tf_ecx, FCN_NULL },
- { "edx", &ddb_regs.tf_edx, FCN_NULL },
- { "ebx", &ddb_regs.tf_ebx, FCN_NULL },
- { "esp", &ddb_regs.tf_esp, FCN_NULL },
- { "ebp", &ddb_regs.tf_ebp, FCN_NULL },
- { "esi", &ddb_regs.tf_esi, FCN_NULL },
- { "edi", &ddb_regs.tf_edi, FCN_NULL },
- { "eip", &ddb_regs.tf_eip, FCN_NULL },
- { "efl", &ddb_regs.tf_eflags, FCN_NULL },
- { "dr0", NULL, db_dr0 },
- { "dr1", NULL, db_dr1 },
- { "dr2", NULL, db_dr2 },
- { "dr3", NULL, db_dr3 },
- { "dr4", NULL, db_dr4 },
- { "dr5", NULL, db_dr5 },
- { "dr6", NULL, db_dr6 },
- { "dr7", NULL, db_dr7 },
+ { "cs", DB_OFFSET(tf_cs), db_frame },
+ { "ds", DB_OFFSET(tf_ds), db_frame },
+ { "es", DB_OFFSET(tf_es), db_frame },
+ { "fs", DB_OFFSET(tf_fs), db_frame },
+ { "ss", NULL, db_ss },
+ { "eax", DB_OFFSET(tf_eax), db_frame },
+ { "ecx", DB_OFFSET(tf_ecx), db_frame },
+ { "edx", DB_OFFSET(tf_edx), db_frame },
+ { "ebx", DB_OFFSET(tf_ebx), db_frame },
+ { "esp", NULL, db_esp },
+ { "ebp", DB_OFFSET(tf_ebp), db_frame },
+ { "esi", DB_OFFSET(tf_esi), db_frame },
+ { "edi", DB_OFFSET(tf_edi), db_frame },
+ { "eip", DB_OFFSET(tf_eip), db_frame },
+ { "efl", DB_OFFSET(tf_eflags), db_frame },
+ { "dr0", NULL, db_dr0 },
+ { "dr1", NULL, db_dr1 },
+ { "dr2", NULL, db_dr2 },
+ { "dr3", NULL, db_dr3 },
+ { "dr4", NULL, db_dr4 },
+ { "dr5", NULL, db_dr5 },
+ { "dr6", NULL, db_dr6 },
+ { "dr7", NULL, db_dr7 },
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+#define DB_DRX_FUNC(reg) \
+static int \
+db_ ## reg (vp, valuep, op) \
+ struct db_variable *vp; \
+ db_expr_t * valuep; \
+ int op; \
+{ \
+ if (op == DB_VAR_GET) \
+ *valuep = r ## reg (); \
+ else \
+ load_ ## reg (*valuep); \
+ return (1); \
+}
+
+DB_DRX_FUNC(dr0)
+DB_DRX_FUNC(dr1)
+DB_DRX_FUNC(dr2)
+DB_DRX_FUNC(dr3)
+DB_DRX_FUNC(dr4)
+DB_DRX_FUNC(dr5)
+DB_DRX_FUNC(dr6)
+DB_DRX_FUNC(dr7)
+
+static __inline int
+get_esp(struct trapframe *tf)
+{
+ return ((ISPL(tf->tf_cs)) ? tf->tf_esp :
+ (db_expr_t)tf + (uintptr_t)DB_OFFSET(tf_esp));
+}
+
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+ int *reg;
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ reg = (int *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+ if (op == DB_VAR_GET)
+ *valuep = *reg;
+ else
+ *reg = *valuep;
+ return (1);
+}
+
+static int
+db_esp(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ if (op == DB_VAR_GET)
+ *valuep = get_esp(kdb_frame);
+ else if (ISPL(kdb_frame->tf_cs))
+ kdb_frame->tf_esp = *valuep;
+ return (1);
+}
+
+static int
+db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ if (op == DB_VAR_GET)
+ *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
+ else if (ISPL(kdb_frame->tf_cs))
+ kdb_frame->tf_ss = *valuep;
+ return (1);
+}
+
/*
* Stack trace.
*/
@@ -104,13 +180,10 @@ struct i386_frame {
#define INTERRUPT 2
#define SYSCALL 3
-static void db_nextframe(struct i386_frame **, db_addr_t *, struct proc *);
+static void db_nextframe(struct i386_frame **, db_addr_t *, struct thread *);
static int db_numargs(struct i386_frame *);
static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
-static void decode_syscall(int, struct proc *);
-static void db_trace_one_stack(int count, boolean_t have_addr,
- struct proc *p, struct i386_frame *frame, db_addr_t callpc);
-
+static void decode_syscall(int, struct thread *);
static char * watchtype_str(int type);
int i386_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
@@ -120,7 +193,6 @@ int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
void db_md_list_watchpoints(void);
-
/*
* Figure out how many arguments were passed into the frame at "fp".
*/
@@ -175,16 +247,16 @@ db_print_stack_entry(name, narg, argnp, argp, callpc)
}
static void
-decode_syscall(number, p)
- int number;
- struct proc *p;
+decode_syscall(int number, struct thread *td)
{
+ struct proc *p;
c_db_sym_t sym;
db_expr_t diff;
sy_call_t *f;
const char *symname;
db_printf(" (%d", number);
+ p = (td != NULL) ? td->td_proc : NULL;
if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
f = p->p_sysent->sv_table[number].sy_call;
sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff);
@@ -200,10 +272,7 @@ decode_syscall(number, p)
* Figure out the next frame up in the call stack.
*/
static void
-db_nextframe(fp, ip, p)
- struct i386_frame **fp; /* in/out */
- db_addr_t *ip; /* out */
- struct proc *p; /* in */
+db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
{
struct trapframe *tf;
int frame_type;
@@ -254,8 +323,7 @@ db_nextframe(fp, ip, p)
tf = (struct trapframe *)((int)*fp + 8);
if (INKERNEL((int) tf)) {
- esp = (ISPL(tf->tf_cs) == SEL_UPL) ?
- tf->tf_esp : (int)&tf->tf_esp;
+ esp = get_esp(tf);
eip = tf->tf_eip;
ebp = tf->tf_ebp;
switch (frame_type) {
@@ -264,7 +332,7 @@ db_nextframe(fp, ip, p)
break;
case SYSCALL:
db_printf("--- syscall");
- decode_syscall(tf->tf_eax, p);
+ decode_syscall(tf->tf_eax, td);
break;
case INTERRUPT:
db_printf("--- interrupt");
@@ -280,135 +348,26 @@ db_nextframe(fp, ip, p)
*fp = (struct i386_frame *) ebp;
}
-void
-db_stack_trace_cmd(addr, have_addr, count, modif)
- db_expr_t addr;
- boolean_t have_addr;
- db_expr_t count;
- char *modif;
+static int
+db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
+ db_addr_t pc, int count)
{
- struct i386_frame *frame;
- struct proc *p;
- struct pcb *pcb;
- struct thread *td;
- db_addr_t callpc;
- pid_t pid;
+ struct i386_frame *actframe;
+#define MAXNARG 16
+ char *argnames[MAXNARG], **argnp = NULL;
+ const char *name;
+ int *argp;
+ db_expr_t offset;
+ c_db_sym_t sym;
+ int narg;
+ boolean_t first;
if (count == -1)
count = 1024;
- if (!have_addr) {
- td = curthread;
- p = td->td_proc;
- frame = (struct i386_frame *)ddb_regs.tf_ebp;
- if (frame == NULL)
- frame = (struct i386_frame *)(ddb_regs.tf_esp - 4);
- callpc = (db_addr_t)ddb_regs.tf_eip;
- } else if (!INKERNEL(addr)) {
- pid = (addr % 16) + ((addr >> 4) % 16) * 10 +
- ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 +
- ((addr >> 16) % 16) * 10000;
- /*
- * The pcb for curproc is not valid at this point,
- * so fall back to the default case.
- */
- if (pid == curthread->td_proc->p_pid) {
- td = curthread;
- p = td->td_proc;
- frame = (struct i386_frame *)ddb_regs.tf_ebp;
- if (frame == NULL)
- frame = (struct i386_frame *)
- (ddb_regs.tf_esp - 4);
- callpc = (db_addr_t)ddb_regs.tf_eip;
- } else {
-
- /* sx_slock(&allproc_lock); */
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid == pid)
- break;
- }
- /* sx_sunlock(&allproc_lock); */
- if (p == NULL) {
- db_printf("pid %d not found\n", pid);
- return;
- }
- if ((p->p_sflag & PS_INMEM) == 0) {
- db_printf("pid %d swapped out\n", pid);
- return;
- }
- pcb = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */
- frame = (struct i386_frame *)pcb->pcb_ebp;
- if (frame == NULL)
- frame = (struct i386_frame *)
- (pcb->pcb_esp - 4);
- callpc = (db_addr_t)pcb->pcb_eip;
- }
- } else {
- p = NULL;
- frame = (struct i386_frame *)addr;
- callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
- frame = frame->f_frame;
- }
- db_trace_one_stack(count, have_addr, p, frame, callpc);
-}
-
-void
-db_stack_thread(db_expr_t addr, boolean_t have_addr,
- db_expr_t count, char *modif)
-{
- struct i386_frame *frame;
- struct thread *td;
- struct proc *p;
- struct pcb *pcb;
- db_addr_t callpc;
-
- if (!have_addr)
- return;
- if (!INKERNEL(addr)) {
- printf("bad thread address");
- return;
- }
- td = (struct thread *)addr;
- /* quick sanity check */
- if ((p = td->td_proc) != td->td_ksegrp->kg_proc)
- return;
- if (TD_IS_SWAPPED(td)) {
- db_printf("thread at %p swapped out\n", td);
- return;
- }
- if (td == curthread) {
- frame = (struct i386_frame *)ddb_regs.tf_ebp;
- if (frame == NULL)
- frame = (struct i386_frame *)(ddb_regs.tf_esp - 4);
- callpc = (db_addr_t)ddb_regs.tf_eip;
- } else {
- pcb = td->td_pcb;
- frame = (struct i386_frame *)pcb->pcb_ebp;
- if (frame == NULL)
- frame = (struct i386_frame *) (pcb->pcb_esp - 4);
- callpc = (db_addr_t)pcb->pcb_eip;
- }
- db_trace_one_stack(count, have_addr, p, frame, callpc);
-}
-
-static void
-db_trace_one_stack(int count, boolean_t have_addr,
- struct proc *p, struct i386_frame *frame, db_addr_t callpc)
-{
- int *argp;
- boolean_t first;
-
first = TRUE;
while (count--) {
- struct i386_frame *actframe;
- int narg;
- const char * name;
- db_expr_t offset;
- c_db_sym_t sym;
-#define MAXNARG 16
- char *argnames[MAXNARG], **argnp = NULL;
-
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
/*
@@ -424,37 +383,33 @@ db_trace_one_stack(int count, boolean_t have_addr,
*/
actframe = frame;
if (first) {
- if (!have_addr) {
+ if (tf != NULL) {
int instr;
- instr = db_get_value(callpc, 4, FALSE);
- if ((instr & 0x00ffffff) == 0x00e58955) {
+ instr = db_get_value(pc, 4, FALSE);
+ if ((instr & 0xffffff) == 0x00e58955) {
/* pushl %ebp; movl %esp, %ebp */
- actframe = (struct i386_frame *)
- (ddb_regs.tf_esp - 4);
- } else if ((instr & 0x0000ffff) == 0x0000e589) {
+ actframe = (void *)(get_esp(tf) - 4);
+ } else if ((instr & 0xffff) == 0x0000e589) {
/* movl %esp, %ebp */
- actframe = (struct i386_frame *)
- ddb_regs.tf_esp;
- if (ddb_regs.tf_ebp == 0) {
- /* Fake caller's frame better. */
+ actframe = (void *)get_esp(tf);
+ if (tf->tf_ebp == 0) {
+ /* Fake frame better. */
frame = actframe;
}
- } else if ((instr & 0x000000ff) == 0x000000c3) {
+ } else if ((instr & 0xff) == 0x000000c3) {
/* ret */
- actframe = (struct i386_frame *)
- (ddb_regs.tf_esp - 4);
+ actframe = (void *)(get_esp(tf) - 4);
} else if (offset == 0) {
- /* Probably a symbol in assembler code. */
- actframe = (struct i386_frame *)
- (ddb_regs.tf_esp - 4);
+ /* Probably an assembler symbol. */
+ actframe = (void *)(get_esp(tf) - 4);
}
} else if (strcmp(name, "fork_trampoline") == 0) {
/*
* Don't try to walk back on a stack for a
* process that hasn't actually been run yet.
*/
- db_print_stack_entry(name, 0, 0, 0, callpc);
+ db_print_stack_entry(name, 0, 0, 0, pc);
break;
}
first = FALSE;
@@ -468,60 +423,68 @@ db_trace_one_stack(int count, boolean_t have_addr,
narg = db_numargs(frame);
}
- db_print_stack_entry(name, narg, argnp, argp, callpc);
+ db_print_stack_entry(name, narg, argnp, argp, pc);
if (actframe != frame) {
/* `frame' belongs to caller. */
- callpc = (db_addr_t)
+ pc = (db_addr_t)
db_get_value((int)&actframe->f_retaddr, 4, FALSE);
continue;
}
- db_nextframe(&frame, &callpc, p);
+ db_nextframe(&frame, &pc, td);
- if (INKERNEL((int) callpc) && !INKERNEL((int) frame)) {
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ if (INKERNEL((int)pc) && !INKERNEL((int) frame)) {
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
- db_print_stack_entry(name, 0, 0, 0, callpc);
+ db_print_stack_entry(name, 0, 0, 0, pc);
break;
}
if (!INKERNEL((int) frame)) {
break;
}
}
+
+ return (0);
+}
+
+void
+db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
+ char *modif)
+{
+ struct thread *td;
+
+ td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread;
+ if (td == NULL) {
+ db_printf("Thread %d not found\n", addr);
+ return;
+ }
+ db_trace_thread(td, count);
}
void
-db_print_backtrace(void)
+db_trace_self(void)
{
+ struct i386_frame *frame;
+ db_addr_t callpc;
register_t ebp;
__asm __volatile("movl %%ebp,%0" : "=r" (ebp));
- db_stack_trace_cmd(ebp, 1, -1, NULL);
+ frame = (struct i386_frame *)ebp;
+ callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
+ frame = frame->f_frame;
+ db_backtrace(curthread, NULL, frame, callpc, -1);
}
-#define DB_DRX_FUNC(reg) \
-int \
-db_ ## reg (vp, valuep, op) \
- struct db_variable *vp; \
- db_expr_t * valuep; \
- int op; \
-{ \
- if (op == DB_VAR_GET) \
- *valuep = r ## reg (); \
- else \
- load_ ## reg (*valuep); \
- return (0); \
-}
+int
+db_trace_thread(struct thread *thr, int count)
+{
+ struct pcb *ctx;
-DB_DRX_FUNC(dr0)
-DB_DRX_FUNC(dr1)
-DB_DRX_FUNC(dr2)
-DB_DRX_FUNC(dr3)
-DB_DRX_FUNC(dr4)
-DB_DRX_FUNC(dr5)
-DB_DRX_FUNC(dr6)
-DB_DRX_FUNC(dr7)
+ ctx = kdb_thr_ctx(thr);
+ return (db_backtrace(thr, NULL, (struct i386_frame *)ctx->pcb_ebp,
+ ctx->pcb_eip, count));
+}
int
i386_set_watch(watchnum, watchaddr, size, access, d)
diff --git a/sys/i386/include/db_machdep.h b/sys/i386/include/db_machdep.h
index ba84fc6834e8e..6922908bc81ef 100644
--- a/sys/i386/include/db_machdep.h
+++ b/sys/i386/include/db_machdep.h
@@ -30,30 +30,23 @@
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
-#include <machine/psl.h>
#include <machine/trap.h>
-#define i386_saved_state trapframe
-
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef int db_expr_t; /* expression - signed */
-typedef struct i386_saved_state db_regs_t;
-extern db_regs_t ddb_regs; /* register state */
-#define DDB_REGS (&ddb_regs)
-
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_eip)
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_eip)
#define BKPT_INST 0xcc /* breakpoint instruction */
#define BKPT_SIZE (1) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
-#define BKPT_SKIP ddb_regs.tf_eip += 1
+#define BKPT_SKIP kdb_frame->tf_eip += 1
-#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_eip -= 1;
+#define FIXUP_PC_AFTER_BREAK kdb_frame->tf_eip -= 1;
-#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T)
-#define db_set_single_step(regs) ((regs)->tf_eflags |= PSL_T)
+#define db_clear_single_step kdb_cpu_clear_singlestep
+#define db_set_single_step kdb_cpu_set_singlestep
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
/*
diff --git a/sys/ia64/ia64/db_interface.c b/sys/ia64/ia64/db_interface.c
index 525966fbc29d3..7d1bdc79dcadd 100644
--- a/sys/ia64/ia64/db_interface.c
+++ b/sys/ia64/ia64/db_interface.c
@@ -1,5 +1,3 @@
-/* $FreeBSD$ */
-
/*
* Mach Operating System
* Copyright (c) 1992,1991,1990 Carnegie Mellon University
@@ -28,29 +26,26 @@
* db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
*/
-/*
- * Parts of this file are derived from Mach 3:
- *
- * File: alpha_instruction.c
- * Author: Alessandro Forin, Carnegie Mellon University
- * Date: 6/92
- */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* Interface to DDB.
*/
#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/reboot.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/smp.h>
#include <sys/cons.h>
+#include <sys/kdb.h>
#include <sys/ktr.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/smp.h>
#include <vm/vm.h>
#include <machine/db_machdep.h>
+#include <machine/frame.h>
#include <machine/mutex.h>
#include <machine/setjmp.h>
@@ -61,433 +56,319 @@
#include <ia64/disasm/disasm.h>
-static jmp_buf *db_nofault = 0;
-extern jmp_buf db_jmpbuf;
+#define TMPL_BITS 5
+#define TMPL_MASK ((1 << TMPL_BITS) - 1)
+#define SLOT_BITS 41
+#define SLOT_COUNT 3
+#define SLOT_MASK ((1ULL << SLOT_BITS) - 1ULL)
+#define SLOT_SHIFT(i) (TMPL_BITS+((i)<<3)+(i))
-extern void gdb_handle_exception(db_regs_t *, int);
-
-int db_active;
-db_regs_t ddb_regs;
-
-static int db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op);
-static int db_get_ip_reg(struct db_variable *vp, db_expr_t *valuep, int op);
+static db_varfcn_t db_frame;
+static db_varfcn_t db_getrse;
+static db_varfcn_t db_getip;
+#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
- /* Misc control/app registers */
-#define DB_MISC_REGS 13 /* make sure this is correct */
-
- {"ip", NULL, db_get_ip_reg},
- {"psr", (db_expr_t*) &ddb_regs.tf_special.psr, FCN_NULL},
- {"cr.isr", (db_expr_t*) &ddb_regs.tf_special.isr, FCN_NULL},
- {"cr.ifa", (db_expr_t*) &ddb_regs.tf_special.ifa, FCN_NULL},
- {"pr", (db_expr_t*) &ddb_regs.tf_special.pr, FCN_NULL},
- {"ar.rsc", (db_expr_t*) &ddb_regs.tf_special.rsc, FCN_NULL},
- {"ar.pfs", (db_expr_t*) &ddb_regs.tf_special.pfs, FCN_NULL},
- {"cr.ifs", (db_expr_t*) &ddb_regs.tf_special.cfm, FCN_NULL},
- {"ar.bspstore", (db_expr_t*) &ddb_regs.tf_special.bspstore, FCN_NULL},
- {"ndirty", (db_expr_t*) &ddb_regs.tf_special.ndirty, FCN_NULL},
- {"ar.rnat", (db_expr_t*) &ddb_regs.tf_special.rnat, FCN_NULL},
- {"ar.unat", (db_expr_t*) &ddb_regs.tf_special.unat, FCN_NULL},
- {"ar.fpsr", (db_expr_t*) &ddb_regs.tf_special.fpsr, FCN_NULL},
-
- /* Branch registers */
- {"rp", (db_expr_t*) &ddb_regs.tf_special.rp, FCN_NULL},
- /* b1, b2, b3, b4, b5 are preserved */
- {"b6", (db_expr_t*) &ddb_regs.tf_scratch.br6, FCN_NULL},
- {"b7", (db_expr_t*) &ddb_regs.tf_scratch.br7, FCN_NULL},
-
- /* Static registers */
- {"gp", (db_expr_t*) &ddb_regs.tf_special.gp, FCN_NULL},
- {"r2", (db_expr_t*) &ddb_regs.tf_scratch.gr2, FCN_NULL},
- {"r3", (db_expr_t*) &ddb_regs.tf_scratch.gr3, FCN_NULL},
- {"r8", (db_expr_t*) &ddb_regs.tf_scratch.gr8, FCN_NULL},
- {"r9", (db_expr_t*) &ddb_regs.tf_scratch.gr9, FCN_NULL},
- {"r10", (db_expr_t*) &ddb_regs.tf_scratch.gr10, FCN_NULL},
- {"r11", (db_expr_t*) &ddb_regs.tf_scratch.gr11, FCN_NULL},
- {"sp", (db_expr_t*) &ddb_regs.tf_special.sp, FCN_NULL},
- {"tp", (db_expr_t*) &ddb_regs.tf_special.tp, FCN_NULL},
- {"r14", (db_expr_t*) &ddb_regs.tf_scratch.gr14, FCN_NULL},
- {"r15", (db_expr_t*) &ddb_regs.tf_scratch.gr15, FCN_NULL},
- {"r16", (db_expr_t*) &ddb_regs.tf_scratch.gr16, FCN_NULL},
- {"r17", (db_expr_t*) &ddb_regs.tf_scratch.gr17, FCN_NULL},
- {"r18", (db_expr_t*) &ddb_regs.tf_scratch.gr18, FCN_NULL},
- {"r19", (db_expr_t*) &ddb_regs.tf_scratch.gr19, FCN_NULL},
- {"r20", (db_expr_t*) &ddb_regs.tf_scratch.gr20, FCN_NULL},
- {"r21", (db_expr_t*) &ddb_regs.tf_scratch.gr21, FCN_NULL},
- {"r22", (db_expr_t*) &ddb_regs.tf_scratch.gr22, FCN_NULL},
- {"r23", (db_expr_t*) &ddb_regs.tf_scratch.gr23, FCN_NULL},
- {"r24", (db_expr_t*) &ddb_regs.tf_scratch.gr24, FCN_NULL},
- {"r25", (db_expr_t*) &ddb_regs.tf_scratch.gr25, FCN_NULL},
- {"r26", (db_expr_t*) &ddb_regs.tf_scratch.gr26, FCN_NULL},
- {"r27", (db_expr_t*) &ddb_regs.tf_scratch.gr27, FCN_NULL},
- {"r28", (db_expr_t*) &ddb_regs.tf_scratch.gr28, FCN_NULL},
- {"r29", (db_expr_t*) &ddb_regs.tf_scratch.gr29, FCN_NULL},
- {"r30", (db_expr_t*) &ddb_regs.tf_scratch.gr30, FCN_NULL},
- {"r31", (db_expr_t*) &ddb_regs.tf_scratch.gr31, FCN_NULL},
-
- /* Stacked registers */
- {"r32", (db_expr_t*) 32, db_get_rse_reg},
- {"r33", (db_expr_t*) 33, db_get_rse_reg},
- {"r34", (db_expr_t*) 34, db_get_rse_reg},
- {"r35", (db_expr_t*) 35, db_get_rse_reg},
- {"r36", (db_expr_t*) 36, db_get_rse_reg},
- {"r37", (db_expr_t*) 37, db_get_rse_reg},
- {"r38", (db_expr_t*) 38, db_get_rse_reg},
- {"r39", (db_expr_t*) 39, db_get_rse_reg},
- {"r40", (db_expr_t*) 40, db_get_rse_reg},
- {"r41", (db_expr_t*) 41, db_get_rse_reg},
- {"r42", (db_expr_t*) 42, db_get_rse_reg},
- {"r43", (db_expr_t*) 43, db_get_rse_reg},
- {"r44", (db_expr_t*) 44, db_get_rse_reg},
- {"r45", (db_expr_t*) 45, db_get_rse_reg},
- {"r46", (db_expr_t*) 46, db_get_rse_reg},
- {"r47", (db_expr_t*) 47, db_get_rse_reg},
- {"r48", (db_expr_t*) 48, db_get_rse_reg},
- {"r49", (db_expr_t*) 49, db_get_rse_reg},
- {"r50", (db_expr_t*) 50, db_get_rse_reg},
- {"r51", (db_expr_t*) 51, db_get_rse_reg},
- {"r52", (db_expr_t*) 52, db_get_rse_reg},
- {"r53", (db_expr_t*) 53, db_get_rse_reg},
- {"r54", (db_expr_t*) 54, db_get_rse_reg},
- {"r55", (db_expr_t*) 55, db_get_rse_reg},
- {"r56", (db_expr_t*) 56, db_get_rse_reg},
- {"r57", (db_expr_t*) 57, db_get_rse_reg},
- {"r58", (db_expr_t*) 58, db_get_rse_reg},
- {"r59", (db_expr_t*) 59, db_get_rse_reg},
- {"r60", (db_expr_t*) 60, db_get_rse_reg},
- {"r61", (db_expr_t*) 61, db_get_rse_reg},
- {"r62", (db_expr_t*) 62, db_get_rse_reg},
- {"r63", (db_expr_t*) 63, db_get_rse_reg},
- {"r64", (db_expr_t*) 64, db_get_rse_reg},
- {"r65", (db_expr_t*) 65, db_get_rse_reg},
- {"r66", (db_expr_t*) 66, db_get_rse_reg},
- {"r67", (db_expr_t*) 67, db_get_rse_reg},
- {"r68", (db_expr_t*) 68, db_get_rse_reg},
- {"r69", (db_expr_t*) 69, db_get_rse_reg},
- {"r70", (db_expr_t*) 70, db_get_rse_reg},
- {"r71", (db_expr_t*) 71, db_get_rse_reg},
- {"r72", (db_expr_t*) 72, db_get_rse_reg},
- {"r73", (db_expr_t*) 73, db_get_rse_reg},
- {"r74", (db_expr_t*) 74, db_get_rse_reg},
- {"r75", (db_expr_t*) 75, db_get_rse_reg},
- {"r76", (db_expr_t*) 76, db_get_rse_reg},
- {"r77", (db_expr_t*) 77, db_get_rse_reg},
- {"r78", (db_expr_t*) 78, db_get_rse_reg},
- {"r79", (db_expr_t*) 79, db_get_rse_reg},
- {"r80", (db_expr_t*) 80, db_get_rse_reg},
- {"r81", (db_expr_t*) 81, db_get_rse_reg},
- {"r82", (db_expr_t*) 82, db_get_rse_reg},
- {"r83", (db_expr_t*) 83, db_get_rse_reg},
- {"r84", (db_expr_t*) 84, db_get_rse_reg},
- {"r85", (db_expr_t*) 85, db_get_rse_reg},
- {"r86", (db_expr_t*) 86, db_get_rse_reg},
- {"r87", (db_expr_t*) 87, db_get_rse_reg},
- {"r88", (db_expr_t*) 88, db_get_rse_reg},
- {"r89", (db_expr_t*) 89, db_get_rse_reg},
- {"r90", (db_expr_t*) 90, db_get_rse_reg},
- {"r91", (db_expr_t*) 91, db_get_rse_reg},
- {"r92", (db_expr_t*) 92, db_get_rse_reg},
- {"r93", (db_expr_t*) 93, db_get_rse_reg},
- {"r94", (db_expr_t*) 94, db_get_rse_reg},
- {"r95", (db_expr_t*) 95, db_get_rse_reg},
- {"r96", (db_expr_t*) 96, db_get_rse_reg},
- {"r97", (db_expr_t*) 97, db_get_rse_reg},
- {"r98", (db_expr_t*) 98, db_get_rse_reg},
- {"r99", (db_expr_t*) 99, db_get_rse_reg},
- {"r100", (db_expr_t*) 100, db_get_rse_reg},
- {"r101", (db_expr_t*) 101, db_get_rse_reg},
- {"r102", (db_expr_t*) 102, db_get_rse_reg},
- {"r103", (db_expr_t*) 103, db_get_rse_reg},
- {"r104", (db_expr_t*) 104, db_get_rse_reg},
- {"r105", (db_expr_t*) 105, db_get_rse_reg},
- {"r106", (db_expr_t*) 106, db_get_rse_reg},
- {"r107", (db_expr_t*) 107, db_get_rse_reg},
- {"r108", (db_expr_t*) 108, db_get_rse_reg},
- {"r109", (db_expr_t*) 109, db_get_rse_reg},
- {"r110", (db_expr_t*) 110, db_get_rse_reg},
- {"r111", (db_expr_t*) 111, db_get_rse_reg},
- {"r112", (db_expr_t*) 112, db_get_rse_reg},
- {"r113", (db_expr_t*) 113, db_get_rse_reg},
- {"r114", (db_expr_t*) 114, db_get_rse_reg},
- {"r115", (db_expr_t*) 115, db_get_rse_reg},
- {"r116", (db_expr_t*) 116, db_get_rse_reg},
- {"r117", (db_expr_t*) 117, db_get_rse_reg},
- {"r118", (db_expr_t*) 118, db_get_rse_reg},
- {"r119", (db_expr_t*) 119, db_get_rse_reg},
- {"r120", (db_expr_t*) 120, db_get_rse_reg},
- {"r121", (db_expr_t*) 121, db_get_rse_reg},
- {"r122", (db_expr_t*) 122, db_get_rse_reg},
- {"r123", (db_expr_t*) 123, db_get_rse_reg},
- {"r124", (db_expr_t*) 124, db_get_rse_reg},
- {"r125", (db_expr_t*) 125, db_get_rse_reg},
- {"r126", (db_expr_t*) 126, db_get_rse_reg},
- {"r127", (db_expr_t*) 127, db_get_rse_reg},
+ {"ip", NULL, db_getip},
+ {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame},
+ {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame},
+ {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame},
+ {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame},
+ {"rp", DB_OFFSET(tf_special.rp), db_frame},
+ {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame},
+ {"psr", DB_OFFSET(tf_special.psr), db_frame},
+ {"cr.isr", DB_OFFSET(tf_special.isr), db_frame},
+ {"pr", DB_OFFSET(tf_special.pr), db_frame},
+ {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame},
+ {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame},
+ {"ar.unat", DB_OFFSET(tf_special.unat), db_frame},
+ {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame},
+ {"gp", DB_OFFSET(tf_special.gp), db_frame},
+ {"sp", DB_OFFSET(tf_special.sp), db_frame},
+ {"tp", DB_OFFSET(tf_special.tp), db_frame},
+ {"b6", DB_OFFSET(tf_scratch.br6), db_frame},
+ {"b7", DB_OFFSET(tf_scratch.br7), db_frame},
+ {"r2", DB_OFFSET(tf_scratch.gr2), db_frame},
+ {"r3", DB_OFFSET(tf_scratch.gr3), db_frame},
+ {"r8", DB_OFFSET(tf_scratch.gr8), db_frame},
+ {"r9", DB_OFFSET(tf_scratch.gr9), db_frame},
+ {"r10", DB_OFFSET(tf_scratch.gr10), db_frame},
+ {"r11", DB_OFFSET(tf_scratch.gr11), db_frame},
+ {"r14", DB_OFFSET(tf_scratch.gr14), db_frame},
+ {"r15", DB_OFFSET(tf_scratch.gr15), db_frame},
+ {"r16", DB_OFFSET(tf_scratch.gr16), db_frame},
+ {"r17", DB_OFFSET(tf_scratch.gr17), db_frame},
+ {"r18", DB_OFFSET(tf_scratch.gr18), db_frame},
+ {"r19", DB_OFFSET(tf_scratch.gr19), db_frame},
+ {"r20", DB_OFFSET(tf_scratch.gr20), db_frame},
+ {"r21", DB_OFFSET(tf_scratch.gr21), db_frame},
+ {"r22", DB_OFFSET(tf_scratch.gr22), db_frame},
+ {"r23", DB_OFFSET(tf_scratch.gr23), db_frame},
+ {"r24", DB_OFFSET(tf_scratch.gr24), db_frame},
+ {"r25", DB_OFFSET(tf_scratch.gr25), db_frame},
+ {"r26", DB_OFFSET(tf_scratch.gr26), db_frame},
+ {"r27", DB_OFFSET(tf_scratch.gr27), db_frame},
+ {"r28", DB_OFFSET(tf_scratch.gr28), db_frame},
+ {"r29", DB_OFFSET(tf_scratch.gr29), db_frame},
+ {"r30", DB_OFFSET(tf_scratch.gr30), db_frame},
+ {"r31", DB_OFFSET(tf_scratch.gr31), db_frame},
+ {"r32", (db_expr_t*)0, db_getrse},
+ {"r33", (db_expr_t*)1, db_getrse},
+ {"r34", (db_expr_t*)2, db_getrse},
+ {"r35", (db_expr_t*)3, db_getrse},
+ {"r36", (db_expr_t*)4, db_getrse},
+ {"r37", (db_expr_t*)5, db_getrse},
+ {"r38", (db_expr_t*)6, db_getrse},
+ {"r39", (db_expr_t*)7, db_getrse},
+ {"r40", (db_expr_t*)8, db_getrse},
+ {"r41", (db_expr_t*)9, db_getrse},
+ {"r42", (db_expr_t*)10, db_getrse},
+ {"r43", (db_expr_t*)11, db_getrse},
+ {"r44", (db_expr_t*)12, db_getrse},
+ {"r45", (db_expr_t*)13, db_getrse},
+ {"r46", (db_expr_t*)14, db_getrse},
+ {"r47", (db_expr_t*)15, db_getrse},
+ {"r48", (db_expr_t*)16, db_getrse},
+ {"r49", (db_expr_t*)17, db_getrse},
+ {"r50", (db_expr_t*)18, db_getrse},
+ {"r51", (db_expr_t*)19, db_getrse},
+ {"r52", (db_expr_t*)20, db_getrse},
+ {"r53", (db_expr_t*)21, db_getrse},
+ {"r54", (db_expr_t*)22, db_getrse},
+ {"r55", (db_expr_t*)23, db_getrse},
+ {"r56", (db_expr_t*)24, db_getrse},
+ {"r57", (db_expr_t*)25, db_getrse},
+ {"r58", (db_expr_t*)26, db_getrse},
+ {"r59", (db_expr_t*)27, db_getrse},
+ {"r60", (db_expr_t*)28, db_getrse},
+ {"r61", (db_expr_t*)29, db_getrse},
+ {"r62", (db_expr_t*)30, db_getrse},
+ {"r63", (db_expr_t*)31, db_getrse},
+ {"r64", (db_expr_t*)32, db_getrse},
+ {"r65", (db_expr_t*)33, db_getrse},
+ {"r66", (db_expr_t*)34, db_getrse},
+ {"r67", (db_expr_t*)35, db_getrse},
+ {"r68", (db_expr_t*)36, db_getrse},
+ {"r69", (db_expr_t*)37, db_getrse},
+ {"r70", (db_expr_t*)38, db_getrse},
+ {"r71", (db_expr_t*)39, db_getrse},
+ {"r72", (db_expr_t*)40, db_getrse},
+ {"r73", (db_expr_t*)41, db_getrse},
+ {"r74", (db_expr_t*)42, db_getrse},
+ {"r75", (db_expr_t*)43, db_getrse},
+ {"r76", (db_expr_t*)44, db_getrse},
+ {"r77", (db_expr_t*)45, db_getrse},
+ {"r78", (db_expr_t*)46, db_getrse},
+ {"r79", (db_expr_t*)47, db_getrse},
+ {"r80", (db_expr_t*)48, db_getrse},
+ {"r81", (db_expr_t*)49, db_getrse},
+ {"r82", (db_expr_t*)50, db_getrse},
+ {"r83", (db_expr_t*)51, db_getrse},
+ {"r84", (db_expr_t*)52, db_getrse},
+ {"r85", (db_expr_t*)53, db_getrse},
+ {"r86", (db_expr_t*)54, db_getrse},
+ {"r87", (db_expr_t*)55, db_getrse},
+ {"r88", (db_expr_t*)56, db_getrse},
+ {"r89", (db_expr_t*)57, db_getrse},
+ {"r90", (db_expr_t*)58, db_getrse},
+ {"r91", (db_expr_t*)59, db_getrse},
+ {"r92", (db_expr_t*)60, db_getrse},
+ {"r93", (db_expr_t*)61, db_getrse},
+ {"r94", (db_expr_t*)62, db_getrse},
+ {"r95", (db_expr_t*)63, db_getrse},
+ {"r96", (db_expr_t*)64, db_getrse},
+ {"r97", (db_expr_t*)65, db_getrse},
+ {"r98", (db_expr_t*)66, db_getrse},
+ {"r99", (db_expr_t*)67, db_getrse},
+ {"r100", (db_expr_t*)68, db_getrse},
+ {"r101", (db_expr_t*)69, db_getrse},
+ {"r102", (db_expr_t*)70, db_getrse},
+ {"r103", (db_expr_t*)71, db_getrse},
+ {"r104", (db_expr_t*)72, db_getrse},
+ {"r105", (db_expr_t*)73, db_getrse},
+ {"r106", (db_expr_t*)74, db_getrse},
+ {"r107", (db_expr_t*)75, db_getrse},
+ {"r108", (db_expr_t*)76, db_getrse},
+ {"r109", (db_expr_t*)77, db_getrse},
+ {"r110", (db_expr_t*)78, db_getrse},
+ {"r111", (db_expr_t*)79, db_getrse},
+ {"r112", (db_expr_t*)80, db_getrse},
+ {"r113", (db_expr_t*)81, db_getrse},
+ {"r114", (db_expr_t*)82, db_getrse},
+ {"r115", (db_expr_t*)83, db_getrse},
+ {"r116", (db_expr_t*)84, db_getrse},
+ {"r117", (db_expr_t*)85, db_getrse},
+ {"r118", (db_expr_t*)86, db_getrse},
+ {"r119", (db_expr_t*)87, db_getrse},
+ {"r120", (db_expr_t*)88, db_getrse},
+ {"r121", (db_expr_t*)89, db_getrse},
+ {"r122", (db_expr_t*)90, db_getrse},
+ {"r123", (db_expr_t*)91, db_getrse},
+ {"r124", (db_expr_t*)92, db_getrse},
+ {"r125", (db_expr_t*)93, db_getrse},
+ {"r126", (db_expr_t*)94, db_getrse},
+ {"r127", (db_expr_t*)95, db_getrse},
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
static int
-db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op)
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+ uint64_t *reg;
+
+ if (kdb_frame == NULL)
+ return (0);
+ reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
+ if (op == DB_VAR_GET)
+ *valuep = *reg;
+ else
+ *reg = *valuep;
+ return (1);
+}
+
+static int
+db_getrse(struct db_variable *vp, db_expr_t *valuep, int op)
{
u_int64_t *reg;
uint64_t bsp;
int nats, regno, sof;
- bsp = ddb_regs.tf_special.bspstore + ddb_regs.tf_special.ndirty;
- regno = (db_expr_t)vp->valuep - 32;
- sof = (int)(ddb_regs.tf_special.cfm & 0x7f);
- nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
-
- reg = (void*)(bsp - ((sof - regno + nats) << 3));
+ if (kdb_frame == NULL)
+ return (0);
- if (regno < sof) {
- if (op == DB_VAR_GET)
- *valuep = *reg;
- else
- *reg = *valuep;
- } else {
- if (op == DB_VAR_GET)
- *valuep = 0xdeadbeefdeadbeef;
- }
+ regno = (int)(intptr_t)valuep;
+ bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty;
+ sof = (int)(kdb_frame->tf_special.cfm & 0x7f);
- return (0);
-}
+ if (regno >= sof)
+ return (0);
-static int
-db_get_ip_reg(struct db_variable *vp, db_expr_t *valuep, int op)
-{
- /* Read only */
+ nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
+ reg = (void*)(bsp - ((sof - regno + nats) << 3));
if (op == DB_VAR_GET)
- *valuep = PC_REGS(DDB_REGS);
- return 0;
+ *valuep = *reg;
+ else
+ *reg = *valuep;
+ return (1);
}
-#if 0
-/*
- * Print trap reason.
- */
-static void
-ddbprinttrap(int vector)
+static int
+db_getip(struct db_variable *vp, db_expr_t *valuep, int op)
{
+ u_long iip, slot;
- /* XXX Implement. */
-
- printf("ddbprinttrap(%d)\n", vector);
-}
-#endif
-
-#define CPUSTOP_ON_DDBBREAK
-#define VERBOSE_CPUSTOP_ON_DDBBREAK
+ if (kdb_frame == NULL)
+ return (0);
-/*
- * ddb_trap - field a kernel trap
- */
-int
-kdb_trap(int vector, struct trapframe *regs)
-{
- int ddb_mode = !(boothowto & RB_GDB);
- register_t s;
-
- /*
- * Don't bother checking for usermode, since a benign entry
- * by the kernel (call to Debugger() or a breakpoint) has
- * already checked for usermode. If neither of those
- * conditions exist, something Bad has happened.
- */
-
- if (vector != IA64_VEC_BREAK
- && vector != IA64_VEC_SINGLE_STEP_TRAP) {
-#if 0
- if (ddb_mode) {
- db_printf("ddbprinttrap from 0x%lx\n", /* XXX */
- regs->tf_regs[FRAME_PC]);
- ddbprinttrap(a0, a1, a2, entry);
- /*
- * Tell caller "We did NOT handle the trap."
- * Caller should panic, or whatever.
- */
+ if (op == DB_VAR_GET) {
+ iip = kdb_frame->tf_special.iip;
+ slot = (kdb_frame->tf_special.psr >> 41) & 3;
+ *valuep = iip + slot;
+ } else {
+ iip = *valuep & ~0xf;
+ slot = *valuep & 0xf;
+ if (slot > 2)
return (0);
- }
-#endif
- if (db_nofault) {
- jmp_buf *no_fault = db_nofault;
- db_nofault = 0;
- longjmp(*no_fault, 1);
- }
- }
-
- /*
- * XXX Should switch to DDB's own stack, here.
- */
-
- s = intr_disable();
-
-#ifdef SMP
-#ifdef CPUSTOP_ON_DDBBREAK
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("CPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid),
- PCPU_GET(other_cpus));
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* We stop all CPUs except ourselves (obviously) */
- stop_cpus(PCPU_GET(other_cpus));
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" stopped.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* CPUSTOP_ON_DDBBREAK */
-#endif /* SMP */
-
- ddb_regs = *regs;
-
- /*
- * XXX pretend that registers outside the current frame don't exist.
- */
- db_eregs = db_regs + DB_MISC_REGS + 3 + 27 +
- (ddb_regs.tf_special.cfm & 0x7f);
-
- __asm __volatile("flushrs"); /* so we can look at them */
-
- db_active++;
-
- if (ddb_mode) {
- cndbctl(TRUE); /* DDB active, unblank video */
- db_trap(vector, 0); /* Where the work happens */
- cndbctl(FALSE); /* DDB inactive */
- } else
- gdb_handle_exception(&ddb_regs, vector);
-
- db_active--;
-
-#ifdef SMP
-#ifdef CPUSTOP_ON_DDBBREAK
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf("CPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid),
- stopped_cpus);
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
- /* Restart all the CPUs we previously stopped */
- if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) {
- db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
- PCPU_GET(other_cpus), stopped_cpus);
- panic("stop_cpus() failed");
+ kdb_frame->tf_special.iip = iip;
+ kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
+ kdb_frame->tf_special.psr |= slot << 41;
}
- restart_cpus(stopped_cpus);
-
-#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
- db_printf(" restarted.\n");
-#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
-
-#endif /* CPUSTOP_ON_DDBBREAK */
-#endif /* SMP */
-
- *regs = ddb_regs;
-
- intr_restore(s);
-
-
- /*
- * Tell caller "We HAVE handled the trap."
- */
return (1);
}
/*
* Read bytes from kernel address space for debugger.
*/
-void
+int
db_read_bytes(vm_offset_t addr, size_t size, char *data)
{
-
- db_nofault = &db_jmpbuf;
-
- if (addr < VM_MAX_ADDRESS)
- copyin((char *)addr, data, size);
- else
- bcopy((char *)addr, data, size);
-
- db_nofault = 0;
+ jmp_buf jb;
+ void *prev_jb;
+ char *src;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ src = (char *)addr;
+ while (size-- > 0)
+ *data++ = *src++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
/*
* Write bytes to kernel address space for debugger.
*/
-void
+int
db_write_bytes(vm_offset_t addr, size_t size, char *data)
{
-
- db_nofault = &db_jmpbuf;
-
- if (addr < VM_MAX_ADDRESS)
- copyout(data, (char *)addr, size);
- else
- bcopy(data, (char *)addr, size);
-
- db_nofault = 0;
+ jmp_buf jb;
+ void *prev_jb;
+ char *dst;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ dst = (char *)addr;
+ while (size-- > 0)
+ *dst++ = *data++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
void
-Debugger(const char* msg)
+db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage)
{
- printf("%s\n", msg);
- __asm("break 0x80100");
-}
+ BKPT_INST_TYPE tmp;
+ db_addr_t loc;
+ int slot;
-u_long
-db_register_value(db_regs_t *regs, int regno)
-{
- uint64_t *rsp;
- uint64_t bsp;
- int nats, sof;
+ slot = addr & 0xfUL;
+ if (slot >= SLOT_COUNT)
+ return;
+ loc = (addr & ~0xfUL) + (slot << 2);
- if (regno == 0)
- return (0);
- if (regno == 1)
- return (regs->tf_special.gp);
- if (regno >= 2 && regno <= 3)
- return ((&regs->tf_scratch.gr2)[regno - 2]);
- if (regno >= 8 && regno <= 11)
- return ((&regs->tf_scratch.gr8)[regno - 8]);
- if (regno == 12)
- return (regs->tf_special.sp);
- if (regno == 13)
- return (regs->tf_special.tp);
- if (regno >= 14 && regno <= 31)
- return ((&regs->tf_scratch.gr14)[regno - 14]);
-
- sof = (int)(regs->tf_special.cfm & 0x7f);
- if (regno >= 32 && regno < sof + 32) {
- bsp = regs->tf_special.bspstore + regs->tf_special.ndirty;
- regno -= 32;
- nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
- rsp = (void*)(bsp - ((sof - regno + nats) << 3));
- return (*rsp);
- }
+ db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
+ *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK;
- db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno);
- return (0);
+ tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
+ tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
+ db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
}
void
-db_write_breakpoint(vm_offset_t addr, u_int64_t *storage)
+db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage)
{
+ BKPT_INST_TYPE tmp;
+ db_addr_t loc;
+ int slot;
+
+ slot = addr & 0xfUL;
+ if (slot >= SLOT_COUNT)
+ return;
+ loc = (addr & ~0xfUL) + (slot << 2);
+
+ db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
+ tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
+ tmp |= *storage << SLOT_SHIFT(slot);
+ db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
}
void
-db_clear_breakpoint(vm_offset_t addr, u_int64_t *storage)
+db_bkpt_skip(void)
{
-}
-void
-db_skip_breakpoint()
-{
+ if (kdb_frame == NULL)
+ return;
- ddb_regs.tf_special.psr += IA64_PSR_RI_1;
- if ((ddb_regs.tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
- ddb_regs.tf_special.psr &= ~IA64_PSR_RI;
- ddb_regs.tf_special.iip += 16;
+ kdb_frame->tf_special.psr += IA64_PSR_RI_1;
+ if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
+ kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
+ kdb_frame->tf_special.iip += 16;
}
}
diff --git a/sys/ia64/ia64/db_trace.c b/sys/ia64/ia64/db_trace.c
index be301797e1f2b..11a2e5582771b 100644
--- a/sys/ia64/ia64/db_trace.c
+++ b/sys/ia64/ia64/db_trace.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2003, 2004 Marcel Moolenaar
* Copyright (c) 2000-2001 Doug Rabson
* All rights reserved.
*
@@ -27,8 +28,13 @@
*/
#include <sys/param.h>
+#include <sys/kdb.h>
#include <sys/proc.h>
+
#include <machine/db_machdep.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
#include <machine/unwind.h>
#include <machine/vmparam.h>
@@ -38,14 +44,12 @@
#include <ddb/db_variables.h>
#include <ddb/db_output.h>
-
int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
void db_md_list_watchpoints(void);
-void
-db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
- char *modif)
+static int
+db_backtrace(struct thread *td, struct pcb *pcb, int count)
{
struct unw_regstate rs;
struct trapframe *tf;
@@ -55,8 +59,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
c_db_sym_t sym;
int args, error, i;
- tf = &ddb_regs;
- error = unw_create(&rs, tf);
+ error = unw_create_from_pcb(&rs, pcb);
while (!error && count--) {
error = unw_get_cfm(&rs, &cfm);
if (!error)
@@ -68,15 +71,14 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
if (error)
break;
- args = (cfm >> 7) & 0x7f;
+ args = IA64_CFM_SOL(cfm);
if (args > 8)
args = 8;
error = unw_step(&rs);
if (!error) {
- error = unw_get_cfm(&rs, &pfs);
- if (!error) {
- i = (pfs & 0x7f) - ((pfs >> 7) & 0x7f);
+ if (!unw_get_cfm(&rs, &pfs)) {
+ i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs);
if (args > i)
args = i;
}
@@ -115,15 +117,43 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
/* XXX ask if we should unwind across the trapframe. */
db_printf("--- trapframe at %p\n", tf);
unw_delete(&rs);
- error = unw_create(&rs, tf);
+ error = unw_create_from_frame(&rs, tf);
}
unw_delete(&rs);
+ return (error);
}
void
-db_print_backtrace(void)
+db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
+ char *modif)
{
+ struct thread *td;
+
+ td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread;
+ if (td == NULL) {
+ db_printf("Thread %d not found\n", (int)addr);
+ return;
+ }
+ db_trace_thread(td, count);
+}
+
+void
+db_trace_self(void)
+{
+ struct pcb pcb;
+
+ savectx(&pcb);
+ db_backtrace(curthread, &pcb, -1);
+}
+
+int
+db_trace_thread(struct thread *td, int count)
+{
+ struct pcb *ctx;
+
+ ctx = kdb_thr_ctx(td);
+ return (db_backtrace(td, ctx, count));
}
int
diff --git a/sys/ia64/include/db_machdep.h b/sys/ia64/include/db_machdep.h
index 4b801f6279bdd..25288cd331e27 100644
--- a/sys/ia64/include/db_machdep.h
+++ b/sys/ia64/include/db_machdep.h
@@ -1,66 +1,64 @@
-/* $FreeBSD$ */
-/* $NetBSD: db_machdep.h,v 1.6 1997/09/06 02:02:25 thorpej Exp $ */
-
/*
- * Copyright (c) 1995 Carnegie-Mellon University.
+ * Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
*
- * Author: Chris G. Demetriou
- *
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
- * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 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.
*
- * Carnegie Mellon requests users of this software to return to
+ * 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.
*
- * 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.
+ * $FreeBSD$
*/
#ifndef _MACHINE_DB_MACHDEP_H_
#define _MACHINE_DB_MACHDEP_H_
-/*
- * Machine-dependent defines for new kernel debugger.
- */
-
-#include <sys/param.h>
-#include <vm/vm.h>
-#include <machine/frame.h>
#include <machine/ia64_cpu.h>
-#define DB_NO_AOUT
+/* We define some of our own commands. */
+#define DB_MACHINE_COMMANDS
+
+/* We use Elf64 symbols in DDB. */
+#define DB_ELFSIZE 64
-struct ia64_bundle;
+/* Pretty arbitrary. */
+#define DB_SMALL_VALUE_MAX 0x7fffffff
+#define DB_SMALL_VALUE_MIN (-0x400001)
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef long db_expr_t; /* expression - signed */
-typedef struct trapframe db_regs_t;
-extern db_regs_t ddb_regs; /* register state */
-#define DDB_REGS (&ddb_regs)
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_special.iip + \
- (((regs)->tf_special.psr >> 41) & 3))
+#define PC_REGS() ((kdb_thrctx->pcb_special.__spare == 0) ? \
+ kdb_thrctx->pcb_special.rp : \
+ kdb_thrctx->pcb_special.iip + ((kdb_thrctx->pcb_special.psr>>41) & 3))
-#define BKPT_WRITE(addr, storage) db_write_breakpoint(addr, storage)
-#define BKPT_CLEAR(addr, storage) db_clear_breakpoint(addr, storage)
-#define BKPT_INST_TYPE u_int64_t
+#define BKPT_WRITE(addr, storage) db_bkpt_write(addr, storage)
+#define BKPT_CLEAR(addr, storage) db_bkpt_clear(addr, storage)
+#define BKPT_SKIP db_bkpt_skip()
+#define BKPT_INST_TYPE uint64_t
-#define BKPT_SKIP db_skip_breakpoint()
+void db_bkpt_write(db_addr_t, BKPT_INST_TYPE *storage);
+void db_bkpt_clear(db_addr_t, uint64_t *storage);
+void db_bkpt_skip(void);
-#define db_clear_single_step(regs) ddb_regs.tf_special.psr &= ~IA64_PSR_SS
-#define db_set_single_step(regs) ddb_regs.tf_special.psr |= IA64_PSR_SS
+#define db_clear_single_step kdb_cpu_clear_singlestep
+#define db_set_single_step kdb_cpu_set_singlestep
#define IS_BREAKPOINT_TRAP(type, code) (type == IA64_VEC_BREAK)
#define IS_WATCHPOINT_TRAP(type, code) 0
@@ -72,43 +70,7 @@ extern db_regs_t ddb_regs; /* register state */
#define inst_load(ins) (ins & 0)
#define inst_store(ins) (ins & 0)
#define inst_unconditional_flow_transfer(ins) (ins & 0)
-
-#define branch_taken(ins, pc, regs) pc
-
-/*
- * Functions needed for software single-stepping.
- */
-
-/* No delay slots on Alpha. */
-#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4)))
-u_long db_register_value(db_regs_t *, int);
-int kdb_trap(int vector, struct trapframe *regs);
-
-u_int64_t *db_rse_current_frame(void);
-u_int64_t *db_rse_previous_frame(u_int64_t *bsp, int sof);
-u_int64_t *db_rse_register_address(u_int64_t *bsp, int regno);
-
-void db_read_bundle(db_addr_t addr, struct ia64_bundle *bp);
-void db_write_bundle(db_addr_t addr, struct ia64_bundle *bp);
-void db_write_breakpoint(db_addr_t addr, u_int64_t *storage);
-void db_clear_breakpoint(db_addr_t addr, u_int64_t *storage);
-void db_skip_breakpoint(void);
-
-/*
- * Pretty arbitrary
- */
-#define DB_SMALL_VALUE_MAX 0x7fffffff
-#define DB_SMALL_VALUE_MIN (-0x400001)
-
-/*
- * We define some of our own commands.
- */
-#define DB_MACHINE_COMMANDS
-
-/*
- * We use Elf64 symbols in DDB.
- */
-#define DB_ELFSIZE 64
+#define branch_taken(ins, pc, regs) pc
#endif /* _MACHINE_DB_MACHDEP_H_ */
diff --git a/sys/sparc64/include/db_machdep.h b/sys/sparc64/include/db_machdep.h
index a31ec62d4b551..bb29debe249f6 100644
--- a/sys/sparc64/include/db_machdep.h
+++ b/sys/sparc64/include/db_machdep.h
@@ -38,23 +38,19 @@
typedef vm_offset_t db_addr_t;
typedef long db_expr_t;
-typedef struct trapframe db_regs_t;
-extern db_regs_t ddb_regs;
-#define DDB_REGS (&ddb_regs)
-
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_tpc)
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_pc)
#define BKPT_INST (0x91d03001)
#define BKPT_SIZE (4)
#define BKPT_SET(inst) (BKPT_INST)
#define BKPT_SKIP do { \
- ddb_regs.tf_tpc = ddb_regs.tf_tnpc + 4; \
- ddb_regs.tf_tnpc += 8; \
+ kdb_frame->tf_tpc = kdb_frame->tf_tnpc + 4; \
+ kdb_frame->tf_tnpc += 8; \
} while (0)
-#define db_clear_single_step(regs)
-#define db_set_single_step(regs)
+#define db_clear_single_step kdb_cpu_clear_singlestep
+#define db_set_single_step kdb_cpu_set_singlestep
#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT)
#define IS_WATCHPOINT_TRAP(type, code) (0)
diff --git a/sys/sparc64/sparc64/db_interface.c b/sys/sparc64/sparc64/db_interface.c
index b6a1e2032c0e0..77e1493652eb7 100644
--- a/sys/sparc64/sparc64/db_interface.c
+++ b/sys/sparc64/sparc64/db_interface.c
@@ -30,6 +30,7 @@
#include <sys/systm.h>
#include <sys/reboot.h>
#include <sys/cons.h>
+#include <sys/kdb.h>
#include <sys/ktr.h>
#include <sys/linker_set.h>
#include <sys/lock.h>
@@ -51,66 +52,42 @@
#include <machine/atomic.h>
#include <machine/setjmp.h>
-static jmp_buf *db_nofault = 0;
-extern jmp_buf db_jmpbuf;
-
-int db_active;
-db_regs_t ddb_regs;
-
-static jmp_buf db_global_jmpbuf;
-static int db_global_jmpbuf_valid;
-
int
-kdb_trap(struct trapframe *tf)
-{
-
- if (db_global_jmpbuf_valid)
- longjmp(db_global_jmpbuf, 1);
- flushw();
- ddb_regs = *tf;
- critical_enter();
- setjmp(db_global_jmpbuf);
- db_global_jmpbuf_valid = TRUE;
- atomic_add_acq_int(&db_active, 1);
-#ifdef SMP
- stop_cpus(PCPU_GET(other_cpus));
-#endif
- cndbctl(TRUE);
- db_trap(tf->tf_type, 0);
- cndbctl(FALSE);
- db_active--;
-#ifdef SMP
- restart_cpus(stopped_cpus);
-#endif
- db_global_jmpbuf_valid = FALSE;
- critical_exit();
- *tf = ddb_regs;
- TF_DONE(tf);
- return (1);
-}
-
-void
db_read_bytes(vm_offset_t addr, size_t size, char *data)
{
+ jmp_buf jb;
+ void *prev_jb;
char *src;
-
- db_nofault = &db_jmpbuf;
- src = (char *)addr;
- while (size-- > 0)
- *data++ = *src++;
- db_nofault = NULL;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ src = (char *)addr;
+ while (size-- > 0)
+ *data++ = *src++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
-void
+int
db_write_bytes(vm_offset_t addr, size_t size, char *data)
{
+ jmp_buf jb;
+ void *prev_jb;
char *dst;
-
- db_nofault = &db_jmpbuf;
- dst = (char *)addr;
- while (size-- > 0)
- *dst++ = *data++;
- db_nofault = NULL;
+ int ret;
+
+ prev_jb = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0) {
+ dst = (char *)addr;
+ while (size-- > 0)
+ *dst++ = *data++;
+ }
+ (void)kdb_jmpbuf(prev_jb);
+ return (ret);
}
void
diff --git a/sys/sparc64/sparc64/db_trace.c b/sys/sparc64/sparc64/db_trace.c
index c57223fc62e75..ae538413cc92c 100644
--- a/sys/sparc64/sparc64/db_trace.c
+++ b/sys/sparc64/sparc64/db_trace.c
@@ -28,6 +28,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/linker_set.h>
#include <sys/proc.h>
#include <sys/sysent.h>
@@ -47,138 +48,89 @@
#include <ddb/db_variables.h>
#include <ddb/db_watch.h>
-static int db_print_trap(struct thread *td, struct trapframe *);
-static void db_utrace(struct thread *td, struct trapframe *tf);
-
#define INKERNEL(va) \
((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS)
+static db_varfcn_t db_frame;
+
+#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
- { "g0", &ddb_regs.tf_global[0], FCN_NULL },
- { "g1", &ddb_regs.tf_global[1], FCN_NULL },
- { "g2", &ddb_regs.tf_global[2], FCN_NULL },
- { "g3", &ddb_regs.tf_global[3], FCN_NULL },
- { "g4", &ddb_regs.tf_global[4], FCN_NULL },
- { "g5", &ddb_regs.tf_global[5], FCN_NULL },
- { "g6", &ddb_regs.tf_global[6], FCN_NULL },
- { "g7", &ddb_regs.tf_global[7], FCN_NULL },
- { "i0", &ddb_regs.tf_out[0], FCN_NULL },
- { "i1", &ddb_regs.tf_out[1], FCN_NULL },
- { "i2", &ddb_regs.tf_out[2], FCN_NULL },
- { "i3", &ddb_regs.tf_out[3], FCN_NULL },
- { "i4", &ddb_regs.tf_out[4], FCN_NULL },
- { "i5", &ddb_regs.tf_out[5], FCN_NULL },
- { "i6", &ddb_regs.tf_out[6], FCN_NULL },
- { "i7", &ddb_regs.tf_out[7], FCN_NULL },
- { "tnpc", &ddb_regs.tf_tnpc, FCN_NULL },
- { "tpc", &ddb_regs.tf_tpc, FCN_NULL },
- { "tstate", &ddb_regs.tf_tstate, FCN_NULL },
+ { "g0", DB_OFFSET(tf_global[0]), db_frame },
+ { "g1", DB_OFFSET(tf_global[1]), db_frame },
+ { "g2", DB_OFFSET(tf_global[2]), db_frame },
+ { "g3", DB_OFFSET(tf_global[3]), db_frame },
+ { "g4", DB_OFFSET(tf_global[4]), db_frame },
+ { "g5", DB_OFFSET(tf_global[5]), db_frame },
+ { "g6", DB_OFFSET(tf_global[6]), db_frame },
+ { "g7", DB_OFFSET(tf_global[7]), db_frame },
+ { "i0", DB_OFFSET(tf_out[0]), db_frame },
+ { "i1", DB_OFFSET(tf_out[1]), db_frame },
+ { "i2", DB_OFFSET(tf_out[2]), db_frame },
+ { "i3", DB_OFFSET(tf_out[3]), db_frame },
+ { "i4", DB_OFFSET(tf_out[4]), db_frame },
+ { "i5", DB_OFFSET(tf_out[5]), db_frame },
+ { "i6", DB_OFFSET(tf_out[6]), db_frame },
+ { "i7", DB_OFFSET(tf_out[7]), db_frame },
+ { "tnpc", DB_OFFSET(tf_tnpc), db_frame },
+ { "tpc", DB_OFFSET(tf_tpc), db_frame },
+ { "tstate", DB_OFFSET(tf_tstate), db_frame },
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
-void
-db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
- char *modif)
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
{
- struct trapframe *tf;
- struct frame *fp;
- struct proc *p;
- struct thread *td;
- const char *name;
- c_db_sym_t sym;
- db_expr_t offset;
- db_expr_t value;
- db_addr_t npc;
- db_addr_t pc;
- int trap;
- int user;
- pid_t pid;
+ uint64_t *reg;
- trap = 0;
- user = 0;
- npc = 0;
- if (count == -1)
- count = 1024;
- td = curthread;
- p = td->td_proc;
- /*
- * Provide an /a modifier to pass the stack address instead of a PID
- * as argument.
- * Note that, if this address is not on the stack of curthread, the
- * printed data may be wrong (at the moment, this applies only to the
- * sysent list).
- */
- if (!have_addr)
- addr = DDB_REGS->tf_out[6];
- else if (strcmp(modif, "a") != 0) {
- /*
- * addr was parsed as hex, convert so it is interpreted as
- * decimal (ugh).
- */
- pid = (addr % 16) + ((addr >> 4) % 16) * 10 +
- ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 +
- ((addr >> 16) % 16) * 10000;
- /*
- * The pcb for curproc is not valid at this point,
- * so fall back to the default case.
- */
- if (pid == curthread->td_proc->p_pid) {
- td = curthread;
- p = td->td_proc;
- addr = DDB_REGS->tf_out[6];
- } else {
- /* sx_slock(&allproc_lock); */
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid == pid)
- break;
- }
- /* sx_sunlock(&allproc_lock); */
- if (p == NULL) {
- db_printf("pid %d not found\n", pid);
- return;
- }
- if ((p->p_sflag & PS_INMEM) == 0) {
- db_printf("pid %d swapped out\n", pid);
- return;
- }
- td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */
- addr = td->td_pcb->pcb_sp;
- }
- }
- fp = (struct frame *)(addr + SPOFF);
+ if (kdb_frame == NULL)
+ return (0);
+ reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
+ if (op == DB_VAR_GET)
+ *valuep = *reg;
+ else
+ *reg = *valuep;
+ return (1);
+}
- while (count-- && !user) {
- pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc,
- sizeof(fp->fr_pc), FALSE);
- if (trap) {
- pc = npc;
- trap = 0;
+/*
+ * User stack trace (debugging aid).
+ */
+static void
+db_utrace(struct thread *td, struct trapframe *tf)
+{
+ struct pcb *pcb;
+ db_addr_t sp, rsp, o7, pc;
+ int i, found;
+
+ pcb = td->td_pcb;
+ sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE);
+ o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]),
+ FALSE);
+ pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE);
+ db_printf("user trace: trap %%o7=%#lx\n", o7);
+ while (sp != 0) {
+ db_printf("pc %#lx, sp %#lx\n", pc, sp);
+ /* First, check whether the frame is in the pcb. */
+ found = 0;
+ for (i = 0; i < pcb->pcb_nsaved; i++) {
+ if (pcb->pcb_rwsp[i] == sp) {
+ found = 1;
+ sp = pcb->pcb_rw[i].rw_in[6];
+ pc = pcb->pcb_rw[i].rw_in[7];
+ break;
+ }
}
- if (!INKERNEL((vm_offset_t)pc))
- break;
- sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
- if (sym == C_DB_SYM_NULL) {
- value = 0;
- name = NULL;
- } else
- db_symbol_values(sym, &name, &value);
- if (name == NULL)
- name = "(null)";
- fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp,
- sizeof(fp->fr_fp), FALSE) + SPOFF);
- if (bcmp(name, "tl0_", 4) == 0 ||
- bcmp(name, "tl1_", 4) == 0) {
- tf = (struct trapframe *)(fp + 1);
- npc = db_get_value((db_addr_t)&tf->tf_tpc,
- sizeof(tf->tf_tpc), FALSE);
- user = db_print_trap(td, tf);
- trap = 1;
- } else {
- db_printf("%s() at ", name);
- db_printsym(pc, DB_STGY_PROC);
- db_printf("\n");
+ if (!found) {
+ rsp = sp + SPOFF;
+ sp = 0;
+ if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)),
+ &sp, sizeof(sp)) != 0 ||
+ copyin((void *)(rsp + offsetof(struct frame, fr_pc)),
+ &pc, sizeof(pc)) != 0)
+ break;
}
}
+ db_printf("done\n");
}
static int
@@ -265,52 +217,88 @@ db_print_trap(struct thread *td, struct trapframe *tf)
return (user);
}
-/*
- * User stack trace (debugging aid).
- */
-static void
-db_utrace(struct thread *td, struct trapframe *tf)
+static int
+db_backtrace(struct thread *td, struct frame *fp, int count)
{
- struct pcb *pcb;
- db_addr_t sp, rsp, o7, pc;
- int i, found;
+ struct trapframe *tf;
+ const char *name;
+ c_db_sym_t sym;
+ db_expr_t offset;
+ db_expr_t value;
+ db_addr_t npc;
+ db_addr_t pc;
+ int trap;
+ int user;
- pcb = td->td_pcb;
- sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE);
- o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]),
- FALSE);
- pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE);
- db_printf("user trace: trap %%o7=%#lx\n", o7);
- while (sp != 0) {
- db_printf("pc %#lx, sp %#lx\n", pc, sp);
- /* First, check whether the frame is in the pcb. */
- found = 0;
- for (i = 0; i < pcb->pcb_nsaved; i++) {
- if (pcb->pcb_rwsp[i] == sp) {
- found = 1;
- sp = pcb->pcb_rw[i].rw_in[6];
- pc = pcb->pcb_rw[i].rw_in[7];
- break;
- }
+ if (count == -1)
+ count = 1024;
+
+ trap = 0;
+ user = 0;
+ npc = 0;
+ while (count-- && !user) {
+ pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc,
+ sizeof(fp->fr_pc), FALSE);
+ if (trap) {
+ pc = npc;
+ trap = 0;
}
- if (!found) {
- rsp = sp + SPOFF;
- sp = 0;
- if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)),
- &sp, sizeof(sp)) != 0 ||
- copyin((void *)(rsp + offsetof(struct frame, fr_pc)),
- &pc, sizeof(pc)) != 0)
- break;
+ if (!INKERNEL((vm_offset_t)pc))
+ break;
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
+ if (sym == C_DB_SYM_NULL) {
+ value = 0;
+ name = NULL;
+ } else
+ db_symbol_values(sym, &name, &value);
+ if (name == NULL)
+ name = "(null)";
+ fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp,
+ sizeof(fp->fr_fp), FALSE) + SPOFF);
+ if (bcmp(name, "tl0_", 4) == 0 ||
+ bcmp(name, "tl1_", 4) == 0) {
+ tf = (struct trapframe *)(fp + 1);
+ npc = db_get_value((db_addr_t)&tf->tf_tpc,
+ sizeof(tf->tf_tpc), FALSE);
+ user = db_print_trap(td, tf);
+ trap = 1;
+ } else {
+ db_printf("%s() at ", name);
+ db_printsym(pc, DB_STGY_PROC);
+ db_printf("\n");
}
}
- db_printf("done\n");
+ return (0);
}
void
-db_print_backtrace(void)
+db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
+ char *modif)
+{
+ struct thread *td;
+
+ td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread;
+ if (td == NULL) {
+ db_printf("Thread %d not found\n", (int)addr);
+ return;
+ }
+ db_trace_thread(td, count);
+}
+
+void
+db_trace_self(void)
+{
+ db_expr_t addr;
+
+ addr = (db_expr_t)__builtin_frame_address(1);
+ db_backtrace(curthread, (struct frame *)(addr + SPOFF), -1);
+}
+
+int
+db_trace_thread(struct thread *td, int count)
{
- u_long *sp;
+ struct pcb *ctx;
- sp = __builtin_frame_address(1);
- db_stack_trace_cmd((db_expr_t)sp, TRUE, -1, "a");
+ ctx = kdb_thr_ctx(td);
+ return (db_backtrace(td, (struct frame*)(ctx->pcb_sp + SPOFF), count));
}