summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_stack.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-12-01 22:04:16 +0000
committerrwatson <rwatson@FreeBSD.org>2007-12-01 22:04:16 +0000
commit090235e567d2103bb33c8098bde951eb3c184d05 (patch)
tree078abf5d6f6ec15b509ed5ddcf1ae98c1893fb79 /sys/kern/subr_stack.c
parenta032664fc9c37f7b29a9713d084d2e3510510531 (diff)
downloadFreeBSD-src-090235e567d2103bb33c8098bde951eb3c184d05.zip
FreeBSD-src-090235e567d2103bb33c8098bde951eb3c184d05.tar.gz
Modify stack(9) stack_print() and stack_sbuf_print() routines to use new
linker interfaces for looking up function names and offsets from instruction pointers. Create two variants of each call: one that is "DDB-safe" and avoids locking in the linker, and one that is safe for use in live kernels, by virtue of observing locking, and in particular safe when kernel modules are being loaded and unloaded simultaneous to their use. This will allow them to be used outside of debugging contexts. Modify two of three current stack(9) consumers to use the DDB-safe interfaces, as they run in low-level debugging contexts, such as inside lockmgr(9) and the kernel memory allocator. Update man page.
Diffstat (limited to 'sys/kern/subr_stack.c')
-rw-r--r--sys/kern/subr_stack.c103
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
OpenPOWER on IntegriCloud