diff options
-rw-r--r-- | share/man/man9/Makefile | 1 | ||||
-rw-r--r-- | share/man/man9/stack.9 | 17 | ||||
-rw-r--r-- | sys/kern/kern_lock.c | 2 | ||||
-rw-r--r-- | sys/kern/subr_stack.c | 103 | ||||
-rw-r--r-- | sys/sys/stack.h | 2 | ||||
-rw-r--r-- | sys/vm/redzone.c | 8 |
6 files changed, 102 insertions, 31 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index f3257bf..53ae350 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1074,6 +1074,7 @@ MLINKS+=stack.9 stack_copy.9 \ stack.9 stack_put.9 \ stack.9 stack_save.9 \ stack.9 stack_sbuf_print.9 \ + stack.9 stack_sbuf_print_ddb.9 \ stack.9 stack_zero.9 MLINKS+=store.9 subyte.9 \ store.9 suswintr.9 \ diff --git a/share/man/man9/stack.9 b/share/man/man9/stack.9 index dabef1a..17cf509 100644 --- a/share/man/man9/stack.9 +++ b/share/man/man9/stack.9 @@ -54,6 +54,8 @@ In kernel configuration files: .Ft void .Fn stack_sbuf_print "struct sbuf sb*" "struct stack *st" .Ft void +.Fn stack_sbuf_print_ddb "struct sbuf sb*" "struct stack *st" +.Ft void .Fn stack_save "struct stack *st" .Sh DESCRIPTION The @@ -96,7 +98,17 @@ as described in .Xr sbuf 9 . This function may sleep if an auto-extending .Dv struct sbuf -is used. +is used, and because the kernel linker (used to look up symbol names) uses +.Xr sx 9 +locks. +.Pp +In locking-sensitive environments, such as +.Xr DDB 4 , +the unsynchronized +.Fn stack_sbuf_print_ddb +variant may be invoked; this makes use of kernel linker data structures to +look up symbol names without following locking protocols, so is appropriate +for use in the debugger but not while the system is live. .Pp The utility functions .Nm stack_zero , @@ -107,7 +119,8 @@ may be used to manipulate stack data structures directly. .Sh SEE ALSO .Xr DDB 4 , .Xr printf 9 , -.Xr sbuf 9 +.Xr sbuf 9 , +.Xr sx 9 .Sh AUTHORS .An -nosplit The diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index b06e17e..3e1d78f 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -625,7 +625,7 @@ lockmgr_printinfo(lkp) if (lkp->lk_waitcount > 0) printf(" with %d pending", lkp->lk_waitcount); #ifdef DEBUG_LOCKS - stack_print(&lkp->lk_stack); + stack_print_ddb(&lkp->lk_stack); #endif } 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 diff --git a/sys/sys/stack.h b/sys/sys/stack.h index a7ac114..ca83472 100644 --- a/sys/sys/stack.h +++ b/sys/sys/stack.h @@ -45,7 +45,9 @@ int stack_put(struct stack *, vm_offset_t); void stack_copy(struct stack *, struct stack *); void stack_zero(struct stack *); void stack_print(struct stack *); +void stack_print_ddb(struct stack *); void stack_sbuf_print(struct sbuf *, struct stack *); +void stack_sbuf_print_ddb(struct sbuf *, struct stack *); #ifdef KTR void stack_ktr(u_int, const char *, int, struct stack *, u_int, int); #define CTRSTACK(m, st, depth, cheap) do { \ diff --git a/sys/vm/redzone.c b/sys/vm/redzone.c index 5598b5d..b3e5c88 100644 --- a/sys/vm/redzone.c +++ b/sys/vm/redzone.c @@ -152,10 +152,10 @@ redzone_check(caddr_t naddr) "corrupted before %p (%lu bytes allocated).\n", ncorruptions, ncorruptions == 1 ? "" : "s", naddr, nsize); printf("Allocation backtrace:\n"); - stack_print(&ast); + stack_print_ddb(&ast); printf("Free backtrace:\n"); stack_save(&fst); - stack_print(&fst); + stack_print_ddb(&fst); if (redzone_panic) panic("Stopping here."); } @@ -171,10 +171,10 @@ redzone_check(caddr_t naddr) "after %p (%lu bytes allocated).\n", ncorruptions, ncorruptions == 1 ? "" : "s", naddr + nsize, nsize); printf("Allocation backtrace:\n"); - stack_print(&ast); + stack_print_ddb(&ast); printf("Free backtrace:\n"); stack_save(&fst); - stack_print(&fst); + stack_print_ddb(&fst); if (redzone_panic) panic("Stopping here."); } |