summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/Makefile1
-rw-r--r--share/man/man9/stack.917
-rw-r--r--sys/kern/kern_lock.c2
-rw-r--r--sys/kern/subr_stack.c103
-rw-r--r--sys/sys/stack.h2
-rw-r--r--sys/vm/redzone.c8
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.");
}
OpenPOWER on IntegriCloud