summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-24 12:06:15 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-24 12:06:15 +0000
commitdf217187ceff1bf82bb7c6ccdd84056b3690156e (patch)
treef482fa5a28657a27ba066c1b1909e4d84a54dfd3
parent841360d91c453a8c5ac107cf8463b159146ecefd (diff)
downloadFreeBSD-src-df217187ceff1bf82bb7c6ccdd84056b3690156e.zip
FreeBSD-src-df217187ceff1bf82bb7c6ccdd84056b3690156e.tar.gz
Add stack_print_short() and stack_print_short_ddb() interfaces to
stack(9), which generate a more compact rendition of a stack trace via the kernel's printf. MFC after: 1 week
-rw-r--r--share/man/man9/stack.914
-rw-r--r--sys/kern/subr_stack.c64
-rw-r--r--sys/sys/stack.h2
3 files changed, 67 insertions, 13 deletions
diff --git a/share/man/man9/stack.9 b/share/man/man9/stack.9
index 8d03dd7..6567641 100644
--- a/share/man/man9/stack.9
+++ b/share/man/man9/stack.9
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 2007 Robert N. M. Watson
+.\" Copyright (c) 2007-2009 Robert N. M. Watson
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 27, 2007
+.Dd June 24, 2009
.Dt STACK 9
.Os
.Sh NAME
@@ -54,6 +54,10 @@ In the kernel configuration file:
.Ft void
.Fn stack_print_ddb "struct stack *st"
.Ft void
+.Fn stack_print_short "struct stack *st"
+.Ft void
+.Fn stack_print_short_ddb "struct stack *st"
+.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"
@@ -84,6 +88,8 @@ A trace of the current kernel thread's call stack may be captured using
.Fn stack_save .
.Pp
.Fn stack_print
+and
+.Fn stack_print_short
may be used to print a stack trace using the kernel
.Xr printf 9 ,
and may sleep as a result of acquiring
@@ -91,7 +97,9 @@ and may sleep as a result of acquiring
locks in the kernel linker while looking up symbol names.
In locking-sensitive environments, the unsynchronized
.Fn stack_print_ddb
-variant may be invoked.
+and
+.Fn stack_print_short_ddb
+variants may be invoked.
This function bypasses kernel linker locking, making it usable in
.Xr ddb 4 ,
but not in a live system where linker data structures may change.
diff --git a/sys/kern/subr_stack.c b/sys/kern/subr_stack.c
index 99e35ea..6b80554 100644
--- a/sys/kern/subr_stack.c
+++ b/sys/kern/subr_stack.c
@@ -42,10 +42,10 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_STACK, "stack", "Stack Traces");
-static void stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen,
+static int stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen,
long *offset);
#ifdef DDB
-static void stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset);
+static int stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset);
#endif
struct stack *
@@ -98,12 +98,33 @@ stack_print(struct stack *st)
KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
for (i = 0; i < st->depth; i++) {
- stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), &offset);
+ (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
+ &offset);
printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
namebuf, offset);
}
}
+void
+stack_print_short(struct stack *st)
+{
+ char namebuf[64];
+ long offset;
+ int i;
+
+ KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
+ for (i = 0; i < st->depth; i++) {
+ if (i > 0)
+ printf(" ");
+ if (stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
+ &offset) == 0)
+ printf("%s+%#lx", namebuf, offset);
+ else
+ printf("%p", (void *)st->pcs[i]);
+ }
+ printf("\n");
+}
+
#ifdef DDB
void
stack_print_ddb(struct stack *st)
@@ -119,6 +140,25 @@ stack_print_ddb(struct stack *st)
name, offset);
}
}
+
+void
+stack_print_short_ddb(struct stack *st)
+{
+ const char *name;
+ long offset;
+ int i;
+
+ KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
+ for (i = 0; i < st->depth; i++) {
+ if (i > 0)
+ printf(" ");
+ if (stack_symbol_ddb(st->pcs[i], &name, &offset) == 0)
+ printf("%s+%#lx", name, offset);
+ else
+ printf("%p", (void *)st->pcs[i]);
+ }
+ printf("\n");
+}
#endif
/*
@@ -134,7 +174,8 @@ stack_sbuf_print(struct sbuf *sb, struct stack *st)
KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
for (i = 0; i < st->depth; i++) {
- stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), &offset);
+ (void)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);
}
@@ -150,7 +191,7 @@ stack_sbuf_print_ddb(struct sbuf *sb, struct stack *st)
KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
for (i = 0; i < st->depth; i++) {
- stack_symbol_ddb(st->pcs[i], &name, &offset);
+ (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
name, offset);
}
@@ -188,7 +229,7 @@ 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_ddb(st->pcs[i], &name, &offset);
+ (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx",
i, st->pcs[i], (u_long)name, offset, 0, 0);
}
@@ -201,7 +242,7 @@ stack_ktr(u_int mask, const char *file, int line, struct stack *st, u_int depth,
* Two variants of stack symbol lookup -- one that uses the DDB interfaces
* and bypasses linker locking, and the other that doesn't.
*/
-static void
+static int
stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset)
{
@@ -209,11 +250,13 @@ stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset)
offset) != 0) {
*offset = 0;
strlcpy(namebuf, "??", buflen);
- }
+ return (ENOENT);
+ } else
+ return (0);
}
#ifdef DDB
-static void
+static int
stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset)
{
linker_symval_t symval;
@@ -225,10 +268,11 @@ stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset)
goto out;
if (symval.name != NULL) {
*name = symval.name;
- return;
+ return (0);
}
out:
*offset = 0;
*name = "??";
+ return (ENOENT);
}
#endif
diff --git a/sys/sys/stack.h b/sys/sys/stack.h
index 0ebdd22..734b967 100644
--- a/sys/sys/stack.h
+++ b/sys/sys/stack.h
@@ -41,6 +41,8 @@ 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_print_short(struct stack *);
+void stack_print_short_ddb(struct stack *);
void stack_sbuf_print(struct sbuf *, struct stack *);
void stack_sbuf_print_ddb(struct sbuf *, struct stack *);
#ifdef KTR
OpenPOWER on IntegriCloud