diff options
Diffstat (limited to 'sys/kern/subr_stack.c')
-rw-r--r-- | sys/kern/subr_stack.c | 103 |
1 files changed, 79 insertions, 24 deletions
diff --git a/sys/kern/subr_stack.c b/sys/kern/subr_stack.c index 705c21b..e3cf156 100644 --- a/sys/kern/subr_stack.c +++ b/sys/kern/subr_stack.c @@ -24,6 +24,8 @@ * SUCH DAMAGE. */ +#include "opt_ddb.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -40,7 +42,12 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); -static void stack_symbol(vm_offset_t pc, const char **name, long *offset); +static void stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, + long *offset); +#ifdef DDB +static void stack_symbol_ddb(vm_offset_t pc, char *namebuf, u_int buflen, + long *offset); +#endif struct stack * stack_create(void) @@ -86,30 +93,67 @@ stack_zero(struct stack *st) void stack_print(struct stack *st) { - const char *name; + char namebuf[64]; long offset; int i; KASSERT(st->depth <= STACK_MAX, ("bogus stack")); for (i = 0; i < st->depth; i++) { - stack_symbol(st->pcs[i], &name, &offset); + stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), &offset); printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], - name, offset); + namebuf, offset); } } void +stack_print_ddb(struct stack *st) +{ + char namebuf[64]; + long offset; + int i; + + KASSERT(st->depth <= STACK_MAX, ("bogus stack")); + for (i = 0; i < st->depth; i++) { + stack_symbol_ddb(st->pcs[i], namebuf, sizeof(namebuf), + &offset); + printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], + namebuf, offset); + } +} + +/* + * Two print routines -- one for use from DDB and DDB-like contexts, the + * other for use in the live kernel. + */ +void stack_sbuf_print(struct sbuf *sb, struct stack *st) { - const char *name; + char namebuf[64]; + long offset; + int i; + + KASSERT(st->depth <= STACK_MAX, ("bogus stack")); + for (i = 0; i < st->depth; i++) { + stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), &offset); + sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], + namebuf, offset); + } +} + +#ifdef DDB +void +stack_sbuf_print_ddb(struct sbuf *sb, struct stack *st) +{ + char namebuf[64]; long offset; int i; KASSERT(st->depth <= STACK_MAX, ("bogus stack")); for (i = 0; i < st->depth; i++) { - stack_symbol(st->pcs[i], &name, &offset); + stack_symbol_ddb(st->pcs[i], namebuf, sizeof(namebuf), + &offset); sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], - name, offset); + namebuf, offset); } } @@ -118,7 +162,7 @@ void stack_ktr(u_int mask, const char *file, int line, struct stack *st, u_int depth, int cheap) { - const char *name; + char namebuf[64]; long offset; int i; @@ -141,29 +185,40 @@ stack_ktr(u_int mask, const char *file, int line, struct stack *st, u_int depth, if (depth == 0 || st->depth < depth) depth = st->depth; for (i = 0; i < depth; i++) { - stack_symbol(st->pcs[i], &name, &offset); + stack_symbol_ddb(st->pcs[i], namebuf, + sizeof(namebuf), &offset); ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx", - i, st->pcs[i], (u_long)name, offset, 0, 0); + i, st->pcs[i], (u_long)namebuf, offset, 0, 0); } } } #endif +#endif +/* + * Two variants of stack symbol lookup -- one that uses the DDB interfaces + * and bypasses linker locking, and the other that doesn't. + */ static void -stack_symbol(vm_offset_t pc, const char **name, long *offset) +stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset) { - linker_symval_t symval; - c_linker_sym_t sym; - - if (linker_ddb_search_symbol((caddr_t)pc, &sym, offset) != 0) - goto out; - if (linker_ddb_symbol_values(sym, &symval) != 0) - goto out; - if (symval.name != NULL) { - *name = symval.name; - return; + + if (linker_search_symbol_name((caddr_t)pc, namebuf, buflen, + offset) != 0) { + *offset = 0; + strlcpy(namebuf, "Unknown func", buflen); } -out: - *offset = 0; - *name = "Unknown func"; } + +#ifdef DDB +static void +stack_symbol_ddb(vm_offset_t pc, char *namebuf, u_int buflen, long *offset) +{ + + if (linker_ddb_search_symbol_name((caddr_t)pc, namebuf, buflen, + offset) != 0) { + *offset = 0; + strlcpy(namebuf, "Unknown func", buflen); + }; +} +#endif |