From 480d3dd2ea4a9d721d69daa022568d8290bb5c97 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sat, 12 Jul 2003 04:35:09 +0000 Subject: [PATCH] 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. --- sys/ia64/ia64/db_trace.c | 23 +++++++++++++++++++++-- sys/ia64/ia64/unwind.c | 20 ++++++++++++++++---- sys/ia64/include/unwind.h | 1 + 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/sys/ia64/ia64/db_trace.c b/sys/ia64/ia64/db_trace.c index 4e164b2d308b..744c9e2d1ad0 100644 --- a/sys/ia64/ia64/db_trace.c +++ b/sys/ia64/ia64/db_trace.c @@ -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); diff --git a/sys/ia64/ia64/unwind.c b/sys/ia64/ia64/unwind.c index cfc5af7097f0..592a773dc06f 100644 --- a/sys/ia64/ia64/unwind.c +++ b/sys/ia64/ia64/unwind.c @@ -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) { diff --git a/sys/ia64/include/unwind.h b/sys/ia64/include/unwind.h index 794a85d19c7e..4ae85ecab97a 100644 --- a/sys/ia64/include/unwind.h +++ b/sys/ia64/include/unwind.h @@ -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);