Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/kernel/dumpstack.c
10817 views
1
/*
2
* Copyright (C) 1991, 1992 Linus Torvalds
3
* Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4
* Copyright (C) 2009 Matt Fleming
5
*/
6
#include <linux/kallsyms.h>
7
#include <linux/ftrace.h>
8
#include <linux/debug_locks.h>
9
#include <asm/unwinder.h>
10
#include <asm/stacktrace.h>
11
12
void printk_address(unsigned long address, int reliable)
13
{
14
printk(" [<%p>] %s%pS\n", (void *) address,
15
reliable ? "" : "? ", (void *) address);
16
}
17
18
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
19
static void
20
print_ftrace_graph_addr(unsigned long addr, void *data,
21
const struct stacktrace_ops *ops,
22
struct thread_info *tinfo, int *graph)
23
{
24
struct task_struct *task = tinfo->task;
25
unsigned long ret_addr;
26
int index = task->curr_ret_stack;
27
28
if (addr != (unsigned long)return_to_handler)
29
return;
30
31
if (!task->ret_stack || index < *graph)
32
return;
33
34
index -= *graph;
35
ret_addr = task->ret_stack[index].ret;
36
37
ops->address(data, ret_addr, 1);
38
39
(*graph)++;
40
}
41
#else
42
static inline void
43
print_ftrace_graph_addr(unsigned long addr, void *data,
44
const struct stacktrace_ops *ops,
45
struct thread_info *tinfo, int *graph)
46
{ }
47
#endif
48
49
void
50
stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
51
unsigned long *sp, const struct stacktrace_ops *ops,
52
void *data)
53
{
54
struct thread_info *context;
55
int graph = 0;
56
57
context = (struct thread_info *)
58
((unsigned long)sp & (~(THREAD_SIZE - 1)));
59
60
while (!kstack_end(sp)) {
61
unsigned long addr = *sp++;
62
63
if (__kernel_text_address(addr)) {
64
ops->address(data, addr, 1);
65
66
print_ftrace_graph_addr(addr, data, ops,
67
context, &graph);
68
}
69
}
70
}
71
72
static int print_trace_stack(void *data, char *name)
73
{
74
printk("%s <%s> ", (char *)data, name);
75
return 0;
76
}
77
78
/*
79
* Print one address/symbol entries per line.
80
*/
81
static void print_trace_address(void *data, unsigned long addr, int reliable)
82
{
83
printk(data);
84
printk_address(addr, reliable);
85
}
86
87
static const struct stacktrace_ops print_trace_ops = {
88
.stack = print_trace_stack,
89
.address = print_trace_address,
90
};
91
92
void show_trace(struct task_struct *tsk, unsigned long *sp,
93
struct pt_regs *regs)
94
{
95
if (regs && user_mode(regs))
96
return;
97
98
printk("\nCall trace:\n");
99
100
unwind_stack(tsk, regs, sp, &print_trace_ops, "");
101
102
printk("\n");
103
104
if (!tsk)
105
tsk = current;
106
107
debug_show_held_locks(tsk);
108
}
109
110