Blame view

arch/sh/kernel/dumpstack.c 2.24 KB
4e14dfc72   Matt Fleming   sh: Use the gener...
1
2
3
4
5
6
7
8
  /*
   *  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>
0eff9f66d   Matt Fleming   sh: Use the new s...
9
  #include <asm/unwinder.h>
4e14dfc72   Matt Fleming   sh: Use the gener...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  #include <asm/stacktrace.h>
  
  void printk_address(unsigned long address, int reliable)
  {
  	printk(" [<%p>] %s%pS
  ", (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
0eff9f66d   Matt Fleming   sh: Use the new s...
49
50
51
52
  void
  stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
  		  unsigned long *sp, const struct stacktrace_ops *ops,
  		  void *data)
4e14dfc72   Matt Fleming   sh: Use the gener...
53
54
55
56
57
58
59
60
61
62
63
  {
  	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)) {
f9967e23c   Paul Mundt   sh: flag the defa...
64
  			ops->address(data, addr, 1);
4e14dfc72   Matt Fleming   sh: Use the gener...
65
66
67
68
69
70
  
  			print_ftrace_graph_addr(addr, data, ops,
  						context, &graph);
  		}
  	}
  }
4e14dfc72   Matt Fleming   sh: Use the gener...
71

4e14dfc72   Matt Fleming   sh: Use the gener...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  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(data);
  	printk_address(addr, reliable);
  }
  
  static const struct stacktrace_ops print_trace_ops = {
4e14dfc72   Matt Fleming   sh: Use the gener...
88
89
90
91
92
93
94
95
96
97
98
99
100
  	.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("
  Call trace:
  ");
0eff9f66d   Matt Fleming   sh: Use the new s...
101
  	unwind_stack(tsk, regs, sp, &print_trace_ops, "");
4e14dfc72   Matt Fleming   sh: Use the gener...
102
103
104
105
106
107
108
109
110
  
  	printk("
  ");
  
  	if (!tsk)
  		tsk = current;
  
  	debug_show_held_locks(tsk);
  }