summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
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