/** * stack_trace_print - Print the entries in the stack trace * @entries: Pointer to storage array * @nr_entries: Number of entries in the storage array * @spaces: Number of leading spaces to print
*/ void stack_trace_print(constunsignedlong *entries, unsignedint nr_entries, int spaces)
{ unsignedint i;
if (WARN_ON(!entries)) return;
for (i = 0; i < nr_entries; i++)
printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]);
}
EXPORT_SYMBOL_GPL(stack_trace_print);
/** * stack_trace_snprint - Print the entries in the stack trace into a buffer * @buf: Pointer to the print buffer * @size: Size of the print buffer * @entries: Pointer to storage array * @nr_entries: Number of entries in the storage array * @spaces: Number of leading spaces to print * * Return: Number of bytes printed.
*/ int stack_trace_snprint(char *buf, size_t size, constunsignedlong *entries, unsignedint nr_entries, int spaces)
{ unsignedint generated, i, total = 0;
if (WARN_ON(!entries)) return 0;
for (i = 0; i < nr_entries && size; i++) {
generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ',
(void *)entries[i]);
/** * stack_trace_save - Save a stack trace into a storage array * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored.
*/ unsignedint stack_trace_save(unsignedlong *store, unsignedint size, unsignedint skipnr)
{
stack_trace_consume_fn consume_entry = stack_trace_consume_entry; struct stacktrace_cookie c = {
.store = store,
.size = size,
.skip = skipnr + 1,
};
/** * stack_trace_save_tsk - Save a task stack trace into a storage array * @tsk: The task to examine * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored.
*/ unsignedint stack_trace_save_tsk(struct task_struct *tsk, unsignedlong *store, unsignedint size, unsignedint skipnr)
{
stack_trace_consume_fn consume_entry = stack_trace_consume_entry_nosched; struct stacktrace_cookie c = {
.store = store,
.size = size, /* skip this function if they are tracing us */
.skip = skipnr + (current == tsk),
};
/** * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array * @regs: Pointer to pt_regs to examine * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored.
*/ unsignedint stack_trace_save_regs(struct pt_regs *regs, unsignedlong *store, unsignedint size, unsignedint skipnr)
{
stack_trace_consume_fn consume_entry = stack_trace_consume_entry; struct stacktrace_cookie c = {
.store = store,
.size = size,
.skip = skipnr,
};
#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE /** * stack_trace_save_tsk_reliable - Save task stack with verification * @tsk: Pointer to the task to examine * @store: Pointer to storage array * @size: Size of the storage array * * Return: An error if it detects any unreliable features of the * stack. Otherwise it guarantees that the stack trace is * reliable and returns the number of entries stored. * * If the task is not 'current', the caller *must* ensure the task is inactive.
*/ int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsignedlong *store, unsignedint size)
{
stack_trace_consume_fn consume_entry = stack_trace_consume_entry; struct stacktrace_cookie c = {
.store = store,
.size = size,
}; int ret;
/* * If the task doesn't have a stack (e.g., a zombie), the stack is * "reliably" empty.
*/ if (!try_get_task_stack(tsk)) return 0;
ret = arch_stack_walk_reliable(consume_entry, &c, tsk);
put_task_stack(tsk); return ret ? ret : c.len;
} #endif
#ifdef CONFIG_USER_STACKTRACE_SUPPORT /** * stack_trace_save_user - Save a user space stack trace into a storage array * @store: Pointer to storage array * @size: Size of the storage array * * Return: Number of trace entries stored.
*/ unsignedint stack_trace_save_user(unsignedlong *store, unsignedint size)
{
stack_trace_consume_fn consume_entry = stack_trace_consume_entry; struct stacktrace_cookie c = {
.store = store,
.size = size,
};
/* Trace user stack if not a kernel thread */ if (current->flags & PF_KTHREAD) return 0;
/* * Architectures that do not implement save_stack_trace_*() * get these weak aliases and once-per-bootup warnings * (whenever this facility is utilized - for example by procfs):
*/
__weak void
save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n");
}
/** * stack_trace_save - Save a stack trace into a storage array * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored
*/ unsignedint stack_trace_save(unsignedlong *store, unsignedint size, unsignedint skipnr)
{ struct stack_trace trace = {
.entries = store,
.max_entries = size,
.skip = skipnr + 1,
};
/** * stack_trace_save_tsk - Save a task stack trace into a storage array * @task: The task to examine * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored
*/ unsignedint stack_trace_save_tsk(struct task_struct *task, unsignedlong *store, unsignedint size, unsignedint skipnr)
{ struct stack_trace trace = {
.entries = store,
.max_entries = size, /* skip this function if they are tracing us */
.skip = skipnr + (current == task),
};
/** * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array * @regs: Pointer to pt_regs to examine * @store: Pointer to storage array * @size: Size of the storage array * @skipnr: Number of entries to skip at the start of the stack trace * * Return: Number of trace entries stored
*/ unsignedint stack_trace_save_regs(struct pt_regs *regs, unsignedlong *store, unsignedint size, unsignedint skipnr)
{ struct stack_trace trace = {
.entries = store,
.max_entries = size,
.skip = skipnr,
};
#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE /** * stack_trace_save_tsk_reliable - Save task stack with verification * @tsk: Pointer to the task to examine * @store: Pointer to storage array * @size: Size of the storage array * * Return: An error if it detects any unreliable features of the * stack. Otherwise it guarantees that the stack trace is * reliable and returns the number of entries stored. * * If the task is not 'current', the caller *must* ensure the task is inactive.
*/ int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsignedlong *store, unsignedint size)
{ struct stack_trace trace = {
.entries = store,
.max_entries = size,
}; int ret = save_stack_trace_tsk_reliable(tsk, &trace);
return ret ? ret : trace.nr_entries;
} #endif
#ifdef CONFIG_USER_STACKTRACE_SUPPORT /** * stack_trace_save_user - Save a user space stack trace into a storage array * @store: Pointer to storage array * @size: Size of the storage array * * Return: Number of trace entries stored
*/ unsignedint stack_trace_save_user(unsignedlong *store, unsignedint size)
{ struct stack_trace trace = {
.entries = store,
.max_entries = size,
};
/** * filter_irq_stacks - Find first IRQ stack entry in trace * @entries: Pointer to stack trace array * @nr_entries: Number of entries in the storage array * * Return: Number of trace entries until IRQ stack starts.
*/ unsignedint filter_irq_stacks(unsignedlong *entries, unsignedint nr_entries)
{ unsignedint i;
for (i = 0; i < nr_entries; i++) { if (in_irqentry_text(entries[i])) { /* Include the irqentry function into the stack. */ return i + 1;
}
} return nr_entries;
}
EXPORT_SYMBOL_GPL(filter_irq_stacks);
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.