summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2004-07-10 23:47:20 +0000
committermarcel <marcel@FreeBSD.org>2004-07-10 23:47:20 +0000
commitaae5483213805c645aad67985fa4f638d6e34915 (patch)
tree533bc344dcaf70d30b9a52c0dc5327488516647b /sys/amd64
parent1dca995d693b9df1e65a294b6385cc1d442233b1 (diff)
downloadFreeBSD-src-aae5483213805c645aad67985fa4f638d6e34915.zip
FreeBSD-src-aae5483213805c645aad67985fa4f638d6e34915.tar.gz
Mega update for the KDB framework: turn DDB into a KDB backend.
Most of the changes are a direct result of adding thread awareness. Typically, DDB_REGS is gone. All registers are taken from the trapframe and backtraces use the PCB based contexts. DDB_REGS was defined to be a trapframe on all platforms anyway. Thread awareness introduces the following new commands: thread X switch to thread X (where X is the TID), show threads list all threads. The backtrace code has been made more flexible so that one can create backtraces for any thread by giving the thread ID as an argument to trace. With this change, ia64 has support for breakpoints.
Diffstat (limited to 'sys/amd64')
-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
3 files changed, 259 insertions, 488 deletions
diff --git a/sys/amd64/amd64/db_interface.c b/sys/amd64/amd64/db_interface.c
index f6bf218..67c8ae5 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 6df1bd1..03842cb 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 18b5e5d..0a737eb 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)
/*
OpenPOWER on IntegriCloud