Add logic to trace across/over a trapframe. We have ABI markers in
our unwind information for functions that are entry points into the kernel. When stepping to the next frame, the unwinder will let us know when sych a marker was encountered. We use this to stop the current unwind session, query the trapframe and restart a new unwind session based on the new trapframe. The implementation is a bit sloppy, but at this time there are bigger fish to fry.
This commit is contained in:
parent
67f74420f4
commit
480d3dd2ea
@ -49,19 +49,23 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
char *modif)
|
||||
{
|
||||
struct unw_regstate rs;
|
||||
struct trapframe *tf;
|
||||
const char *name;
|
||||
db_expr_t offset;
|
||||
uint64_t bsp, cfm, ip, pfs, reg;
|
||||
uint64_t bsp, cfm, ip, pfs, reg, sp;
|
||||
c_db_sym_t sym;
|
||||
int args, error, i;
|
||||
|
||||
error = unw_create(&rs, &ddb_regs);
|
||||
tf = &ddb_regs;
|
||||
error = unw_create(&rs, tf);
|
||||
while (!error && count--) {
|
||||
error = unw_get_cfm(&rs, &cfm);
|
||||
if (!error)
|
||||
error = unw_get_bsp(&rs, &bsp);
|
||||
if (!error)
|
||||
error = unw_get_ip(&rs, &ip);
|
||||
if (!error)
|
||||
error = unw_get_sp(&rs, &sp);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
@ -98,6 +102,21 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
|
||||
|
||||
db_printsym(ip, DB_STGY_PROC);
|
||||
db_printf("\n");
|
||||
|
||||
if (error != EOVERFLOW)
|
||||
continue;
|
||||
if (sp < IA64_RR_BASE(5))
|
||||
break;
|
||||
|
||||
tf = (struct trapframe *)(sp + 16);
|
||||
if ((tf->tf_flags & FRAME_SYSCALL) != 0 ||
|
||||
tf->tf_special.iip < IA64_RR_BASE(5))
|
||||
break;
|
||||
|
||||
/* XXX ask if we should unwind across the trapframe. */
|
||||
db_printf("--- trapframe at %p\n", tf);
|
||||
unw_delete(&rs);
|
||||
error = unw_create(&rs, tf);
|
||||
}
|
||||
|
||||
unw_delete(&rs);
|
||||
|
@ -282,16 +282,19 @@ void
|
||||
unw_delete(struct unw_regstate *rs)
|
||||
{
|
||||
|
||||
uwx_free(rs->env);
|
||||
if (rs->env != NULL)
|
||||
uwx_free(rs->env);
|
||||
}
|
||||
|
||||
int
|
||||
unw_step(struct unw_regstate *rs)
|
||||
{
|
||||
int uwxerr;
|
||||
int err;
|
||||
|
||||
uwxerr = uwx_step(rs->env);
|
||||
return ((uwxerr) ? EINVAL : 0); /* XXX */
|
||||
err = uwx_step(rs->env);
|
||||
if (err == UWX_ABI_FRAME)
|
||||
return (EOVERFLOW);
|
||||
return ((err != 0) ? EINVAL : 0); /* XXX */
|
||||
}
|
||||
|
||||
int
|
||||
@ -321,6 +324,15 @@ unw_get_ip(struct unw_regstate *s, uint64_t *r)
|
||||
return ((uwxerr) ? EINVAL : 0); /* XXX */
|
||||
}
|
||||
|
||||
int
|
||||
unw_get_sp(struct unw_regstate *s, uint64_t *r)
|
||||
{
|
||||
int uwxerr;
|
||||
|
||||
uwxerr = uwx_get_reg(s->env, UWX_REG_SP, r);
|
||||
return ((uwxerr) ? EINVAL : 0); /* XXX */
|
||||
}
|
||||
|
||||
int
|
||||
unw_table_add(uint64_t base, uint64_t start, uint64_t end)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ int unw_step(struct unw_regstate *s);
|
||||
int unw_get_bsp(struct unw_regstate *s, uint64_t *r);
|
||||
int unw_get_cfm(struct unw_regstate *s, uint64_t *r);
|
||||
int unw_get_ip(struct unw_regstate *s, uint64_t *r);
|
||||
int unw_get_sp(struct unw_regstate *s, uint64_t *r);
|
||||
|
||||
int unw_table_add(uint64_t, uint64_t, uint64_t);
|
||||
void unw_table_remove(uint64_t);
|
||||
|
Loading…
Reference in New Issue
Block a user