123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
- * Copyright (C) 2009 Matt Fleming
- */
- #include <linux/kallsyms.h>
- #include <linux/ftrace.h>
- #include <linux/debug_locks.h>
- #include <asm/unwinder.h>
- #include <asm/stacktrace.h>
- void printk_address(unsigned long address, int reliable)
- {
- printk(" [<%p>] %s%pS\n", (void *) address,
- reliable ? "" : "? ", (void *) address);
- }
- #ifdef CONFIG_FUNCTION_GRAPH_TRACER
- static void
- print_ftrace_graph_addr(unsigned long addr, void *data,
- const struct stacktrace_ops *ops,
- struct thread_info *tinfo, int *graph)
- {
- struct task_struct *task = tinfo->task;
- unsigned long ret_addr;
- int index = task->curr_ret_stack;
- if (addr != (unsigned long)return_to_handler)
- return;
- if (!task->ret_stack || index < *graph)
- return;
- index -= *graph;
- ret_addr = task->ret_stack[index].ret;
- ops->address(data, ret_addr, 1);
- (*graph)++;
- }
- #else
- static inline void
- print_ftrace_graph_addr(unsigned long addr, void *data,
- const struct stacktrace_ops *ops,
- struct thread_info *tinfo, int *graph)
- { }
- #endif
- void
- stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
- unsigned long *sp, const struct stacktrace_ops *ops,
- void *data)
- {
- struct thread_info *context;
- int graph = 0;
- context = (struct thread_info *)
- ((unsigned long)sp & (~(THREAD_SIZE - 1)));
- while (!kstack_end(sp)) {
- unsigned long addr = *sp++;
- if (__kernel_text_address(addr)) {
- ops->address(data, addr, 1);
- print_ftrace_graph_addr(addr, data, ops,
- context, &graph);
- }
- }
- }
- static int print_trace_stack(void *data, char *name)
- {
- printk("%s <%s> ", (char *)data, name);
- return 0;
- }
- /*
- * Print one address/symbol entries per line.
- */
- static void print_trace_address(void *data, unsigned long addr, int reliable)
- {
- printk("%s", (char *)data);
- printk_address(addr, reliable);
- }
- static const struct stacktrace_ops print_trace_ops = {
- .stack = print_trace_stack,
- .address = print_trace_address,
- };
- void show_trace(struct task_struct *tsk, unsigned long *sp,
- struct pt_regs *regs)
- {
- if (regs && user_mode(regs))
- return;
- printk("\nCall trace:\n");
- unwind_stack(tsk, regs, sp, &print_trace_ops, "");
- printk("\n");
- if (!tsk)
- tsk = current;
- debug_show_held_locks(tsk);
- }
|