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:
Marcel Moolenaar 2003-07-12 04:35:09 +00:00
parent 67f74420f4
commit 480d3dd2ea
3 changed files with 38 additions and 6 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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);