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
This commit is contained in:
Robert Watson 2009-06-24 12:06:15 +00:00
parent 8419ef9a1e
commit 36fecbf302
3 changed files with 67 additions and 13 deletions

View File

@ -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.

View File

@ -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

View File

@ -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