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:
parent
8419ef9a1e
commit
36fecbf302
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user