1. Remove kdbframe. Bad idea.
2. Add a TF_DONE macro, which fiddles a trapframe to make the retry on return from traps act like a done (advance past the trapping instruction instead of re-executing). 3. Flush the windows before entering the debugger, since it is no longer done in the breakpoint trap vector. 4. Print a warning if trace <pid> is attempted, it is not yet implemented. 5. Print traps better and decode system calls in traces. Submitted by: rwatson (4)
This commit is contained in:
parent
bc40966754
commit
d5a7911f4a
@ -38,10 +38,6 @@
|
||||
typedef vm_offset_t db_addr_t;
|
||||
typedef long db_expr_t;
|
||||
|
||||
struct db_regs {
|
||||
u_long dr_global[8];
|
||||
};
|
||||
|
||||
typedef struct trapframe db_regs_t;
|
||||
extern db_regs_t ddb_regs;
|
||||
#define DDB_REGS (&ddb_regs)
|
||||
@ -52,10 +48,10 @@ extern db_regs_t ddb_regs;
|
||||
#define BKPT_SIZE (4)
|
||||
#define BKPT_SET(inst) (BKPT_INST)
|
||||
|
||||
#define FIXUP_PC_AFTER_BREAK do { \
|
||||
ddb_regs.tf_tpc = ddb_regs.tf_tnpc; \
|
||||
ddb_regs.tf_tnpc += BKPT_SIZE; \
|
||||
} while (0);
|
||||
#define BKPT_SKIP do { \
|
||||
ddb_regs.tf_tpc = ddb_regs.tf_tnpc + 4; \
|
||||
ddb_regs.tf_tnpc += 8; \
|
||||
} while (0)
|
||||
|
||||
#define db_clear_single_step(regs)
|
||||
#define db_set_single_step(regs)
|
||||
|
@ -49,22 +49,17 @@ struct trapframe {
|
||||
tf->tf_tnpc += 4; \
|
||||
} while (0)
|
||||
|
||||
#define TF_DONE(tf) do { \
|
||||
tf->tf_tpc = tf->tf_tnpc; \
|
||||
tf->tf_tnpc += 4; \
|
||||
} while (0)
|
||||
|
||||
struct mmuframe {
|
||||
u_long mf_sfar;
|
||||
u_long mf_sfsr;
|
||||
u_long mf_tar;
|
||||
};
|
||||
|
||||
struct kdbframe {
|
||||
u_long kf_fp;
|
||||
u_long kf_cfp;
|
||||
u_long kf_canrestore;
|
||||
u_long kf_cansave;
|
||||
u_long kf_cleanwin;
|
||||
u_long kf_cwp;
|
||||
u_long kf_otherwin;
|
||||
};
|
||||
|
||||
struct clockframe {
|
||||
struct trapframe cf_tf;
|
||||
};
|
||||
|
@ -62,13 +62,11 @@ static int db_global_jmpbuf_valid;
|
||||
int
|
||||
kdb_trap(struct trapframe *tf)
|
||||
{
|
||||
struct kdbframe *kf;
|
||||
|
||||
if (db_global_jmpbuf_valid)
|
||||
longjmp(db_global_jmpbuf, 1);
|
||||
flushw();
|
||||
ddb_regs = *tf;
|
||||
kf = (struct kdbframe *)ddb_regs.tf_arg;
|
||||
kf->kf_cfp = kf->kf_fp;
|
||||
setjmp(db_global_jmpbuf);
|
||||
db_global_jmpbuf_valid = TRUE;
|
||||
db_active++;
|
||||
@ -77,6 +75,7 @@ kdb_trap(struct trapframe *tf)
|
||||
cndbctl(FALSE);
|
||||
db_active--;
|
||||
db_global_jmpbuf_valid = FALSE;
|
||||
*tf = ddb_regs;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/linker_set.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
@ -63,13 +64,10 @@ static db_varfcn_t db_show_local5;
|
||||
static db_varfcn_t db_show_local6;
|
||||
static db_varfcn_t db_show_local7;
|
||||
|
||||
static int db_print_trap(struct trapframe *);
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
static int db_print_trap(struct proc *p, struct trapframe *);
|
||||
|
||||
#define INKERNEL(va) \
|
||||
((va) >= (u_long)_start && (va) <= (u_long)_end)
|
||||
((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS)
|
||||
|
||||
struct db_variable db_regs[] = {
|
||||
{ "g0", &ddb_regs.tf_global[0], FCN_NULL },
|
||||
@ -107,8 +105,9 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
char *modif)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
struct kdbframe *kfp;
|
||||
struct frame *fp;
|
||||
struct proc *p;
|
||||
struct thread *td;
|
||||
const char *name;
|
||||
c_db_sym_t sym;
|
||||
db_expr_t offset;
|
||||
@ -118,6 +117,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
db_addr_t pc;
|
||||
int trap;
|
||||
int user;
|
||||
pid_t pid;
|
||||
|
||||
trap = 0;
|
||||
user = 0;
|
||||
@ -125,10 +125,28 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
if (count == -1)
|
||||
count = 1024;
|
||||
if (!have_addr) {
|
||||
kfp = (struct kdbframe *)DDB_REGS->tf_arg;
|
||||
fp = (struct frame *)(kfp->kf_cfp + SPOFF);
|
||||
} else
|
||||
fp = (struct frame *)(addr + SPOFF);
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
addr = DDB_REGS->tf_out[6];
|
||||
} 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;
|
||||
} else {
|
||||
/* search for pid */
|
||||
}
|
||||
db_printf("trace pid not implemented\n");
|
||||
return;
|
||||
}
|
||||
fp = (struct frame *)(addr + SPOFF);
|
||||
|
||||
while (count-- && !user) {
|
||||
pc = (db_addr_t)db_get_value((db_addr_t)&fp->f_pc,
|
||||
sizeof(db_addr_t), FALSE);
|
||||
@ -153,7 +171,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
tf = (struct trapframe *)(nfp + sizeof(*fp));
|
||||
npc = db_get_value((db_addr_t)&tf->tf_tpc,
|
||||
sizeof(u_long), FALSE);
|
||||
user = db_print_trap(tf);
|
||||
user = db_print_trap(curthread->td_proc, tf);
|
||||
trap = 1;
|
||||
} else {
|
||||
db_printf("%s() at ", name);
|
||||
@ -166,32 +184,54 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
}
|
||||
|
||||
static int
|
||||
db_print_trap(struct trapframe *tf)
|
||||
db_print_trap(struct proc *p, struct trapframe *tf)
|
||||
{
|
||||
const char *symname;
|
||||
struct mmuframe *mf;
|
||||
c_db_sym_t sym;
|
||||
db_expr_t diff;
|
||||
db_addr_t func;
|
||||
db_addr_t tpc;
|
||||
u_long type;
|
||||
u_long va;
|
||||
u_long code;
|
||||
|
||||
type = db_get_value((db_addr_t)&tf->tf_type, sizeof(u_long), FALSE);
|
||||
db_printf("-- %s trap (%s) -- ", type & T_KERNEL ? "kernel" : "user",
|
||||
trap_msg[type & ~T_KERNEL]);
|
||||
if ((type & T_KERNEL) == 0)
|
||||
db_printf("tpc=0x%lx, tnpc=0x%lx ", tf->tf_tpc, tf->tf_tnpc);
|
||||
type = db_get_value((db_addr_t)&tf->tf_type, sizeof(db_addr_t), FALSE);
|
||||
db_printf("-- %s", trap_msg[type & ~T_KERNEL]);
|
||||
switch (type & ~T_KERNEL) {
|
||||
case T_ALIGN:
|
||||
mf = (struct mmuframe *)db_get_value((db_addr_t)&tf->tf_arg,
|
||||
sizeof(void *), FALSE);
|
||||
va = (u_long)db_get_value((db_addr_t)&mf->mf_sfar,
|
||||
sizeof(u_long), FALSE);
|
||||
db_printf("va=%#lx", va);
|
||||
db_printf(" va=%#lx", va);
|
||||
break;
|
||||
case T_SYSCALL:
|
||||
code = db_get_value((db_addr_t)&tf->tf_global[1],
|
||||
sizeof(u_long), FALSE);
|
||||
db_printf(" (%ld", code);
|
||||
if (code >= 0 && code < p->p_sysent->sv_size) {
|
||||
func = (db_addr_t)p->p_sysent->sv_table[code].sy_call;
|
||||
sym = db_search_symbol(func, DB_STGY_ANY, &diff);
|
||||
if (sym != DB_SYM_NULL && diff == 0) {
|
||||
db_symbol_values(sym, &symname, NULL);
|
||||
db_printf(", %s, %s", p->p_sysent->sv_name,
|
||||
symname);
|
||||
}
|
||||
db_printf(")");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
tpc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(db_addr_t), FALSE);
|
||||
db_printf(" -- at ");
|
||||
db_printsym(tpc, DB_STGY_PROC);
|
||||
db_printf("\n");
|
||||
return ((type & T_KERNEL) == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
DB_COMMAND(down, db_frame_down)
|
||||
{
|
||||
struct kdbframe *kfp;
|
||||
@ -231,16 +271,15 @@ DB_COMMAND(up, db_frame_up)
|
||||
kfp->kf_cfp = db_get_value((db_addr_t)&cfp->f_fp, sizeof(u_long),
|
||||
FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DB_SHOW_REG(name, num) \
|
||||
static int \
|
||||
db_show_ ## name ## num(struct db_variable *dp, db_expr_t *vp, int op) \
|
||||
{ \
|
||||
struct kdbframe *kfp; \
|
||||
struct frame *fp; \
|
||||
\
|
||||
kfp = (struct kdbframe *)DDB_REGS->tf_arg; \
|
||||
fp = (struct frame *)(kfp->kf_cfp + SPOFF); \
|
||||
fp = (struct frame *)(DDB_REGS->tf_out[6] + SPOFF); \
|
||||
if (op == DB_VAR_GET) \
|
||||
*vp = db_get_value((db_addr_t)&fp->f_ ## name ## [num], \
|
||||
sizeof(u_long), FALSE); \
|
||||
|
Loading…
Reference in New Issue
Block a user