Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_stack.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
FEATURE(stack, "Support for capturing kernel stack"); | FEATURE(stack, "Support for capturing kernel stack"); | ||||
static MALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); | static MALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); | ||||
static int 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); | long *offset, int flags); | ||||
static int 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); | ||||
struct stack * | struct stack * | ||||
stack_create(int flags) | stack_create(int flags) | ||||
{ | { | ||||
struct stack *st; | struct stack *st; | ||||
st = malloc(sizeof(*st), M_STACK, flags | M_ZERO); | st = malloc(sizeof(*st), M_STACK, flags | M_ZERO); | ||||
Show All 37 Lines | |||||
{ | { | ||||
char namebuf[64]; | char namebuf[64]; | ||||
long offset; | long offset; | ||||
int i; | int i; | ||||
KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | ||||
for (i = 0; i < st->depth; i++) { | for (i = 0; i < st->depth; i++) { | ||||
(void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | ||||
&offset); | &offset, M_WAITOK); | ||||
printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], | printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], | ||||
namebuf, offset); | namebuf, offset); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
stack_print_short(const struct stack *st) | stack_print_short(const struct stack *st) | ||||
{ | { | ||||
char namebuf[64]; | char namebuf[64]; | ||||
long offset; | long offset; | ||||
int i; | int i; | ||||
KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | ||||
for (i = 0; i < st->depth; i++) { | for (i = 0; i < st->depth; i++) { | ||||
if (i > 0) | if (i > 0) | ||||
printf(" "); | printf(" "); | ||||
if (stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | if (stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | ||||
&offset) == 0) | &offset, M_WAITOK) == 0) | ||||
printf("%s+%#lx", namebuf, offset); | printf("%s+%#lx", namebuf, offset); | ||||
else | else | ||||
printf("%p", (void *)st->pcs[i]); | printf("%p", (void *)st->pcs[i]); | ||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
void | void | ||||
Show All 28 Lines | for (i = 0; i < st->depth; i++) { | ||||
else | else | ||||
printf("%p", (void *)st->pcs[i]); | printf("%p", (void *)st->pcs[i]); | ||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Two print routines -- one for use from DDB and DDB-like contexts, the | * Format stack into sbuf from live kernel. | ||||
* other for use in the live kernel. | * | ||||
* flags - M_WAITOK or M_NOWAIT (EWOULDBLOCK). | |||||
*/ | */ | ||||
void | int | ||||
stack_sbuf_print(struct sbuf *sb, const struct stack *st) | stack_sbuf_print_flags(struct sbuf *sb, const struct stack *st, int flags) | ||||
{ | { | ||||
char namebuf[64]; | char namebuf[64]; | ||||
long offset; | long offset; | ||||
int i; | int i, error; | ||||
KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | KASSERT(st->depth <= STACK_MAX, ("bogus stack")); | ||||
for (i = 0; i < st->depth; i++) { | for (i = 0; i < st->depth; i++) { | ||||
(void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | error = stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), | ||||
&offset); | &offset, flags); | ||||
if (error == EWOULDBLOCK) | |||||
return (error); | |||||
sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], | sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], | ||||
namebuf, offset); | namebuf, offset); | ||||
} | } | ||||
return (0); | |||||
} | } | ||||
void | |||||
stack_sbuf_print(struct sbuf *sb, const struct stack *st) | |||||
{ | |||||
markj: Style: missing newline. | |||||
cemAuthorUnsubmitted Done Inline Actionswill fix cem: will fix | |||||
(void)stack_sbuf_print_flags(sb, st, M_WAITOK); | |||||
} | |||||
#if defined(DDB) || defined(WITNESS) | #if defined(DDB) || defined(WITNESS) | ||||
void | void | ||||
stack_sbuf_print_ddb(struct sbuf *sb, const struct stack *st) | stack_sbuf_print_ddb(struct sbuf *sb, const struct stack *st) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
long offset; | long offset; | ||||
int i; | int i; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Two variants of stack symbol lookup -- one that uses the DDB interfaces | * Two variants of stack symbol lookup -- one that uses the DDB interfaces | ||||
* and bypasses linker locking, and the other that doesn't. | * and bypasses linker locking, and the other that doesn't. | ||||
*/ | */ | ||||
static int | static int | ||||
stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset) | stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset, | ||||
int flags) | |||||
{ | { | ||||
int error; | |||||
if (linker_search_symbol_name((caddr_t)pc, namebuf, buflen, | error = linker_search_symbol_name_flags((caddr_t)pc, namebuf, buflen, | ||||
offset) != 0) { | offset, flags); | ||||
if (error == 0 || error == EWOULDBLOCK) | |||||
return (error); | |||||
*offset = 0; | *offset = 0; | ||||
strlcpy(namebuf, "??", buflen); | strlcpy(namebuf, "??", buflen); | ||||
return (ENOENT); | return (ENOENT); | ||||
} else | |||||
return (0); | |||||
} | } | ||||
static int | static int | ||||
stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset) | stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset) | ||||
{ | { | ||||
linker_symval_t symval; | linker_symval_t symval; | ||||
c_linker_sym_t sym; | c_linker_sym_t sym; | ||||
Show All 13 Lines |
Style: missing newline.