1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/sched/task_stack.h>
14#include <linux/kernel.h>
15
16#include <asm/unwinder.h>
17
18#ifdef CONFIG_FRAME_POINTER
19struct or1k_frameinfo {
20 unsigned long *fp;
21 unsigned long ra;
22 unsigned long top;
23};
24
25
26
27
28
29
30
31static inline int or1k_frameinfo_valid(struct or1k_frameinfo *frameinfo)
32{
33 return (frameinfo->fp == NULL ||
34 (!kstack_end(frameinfo->fp) &&
35 frameinfo->fp > &frameinfo->top)) &&
36 __kernel_text_address(frameinfo->ra);
37}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60void unwind_stack(void *data, unsigned long *stack,
61 void (*trace)(void *data, unsigned long addr, int reliable))
62{
63 unsigned long *next_fp = NULL;
64 struct or1k_frameinfo *frameinfo = NULL;
65 int reliable = 0;
66
67 while (!kstack_end(stack)) {
68 frameinfo = container_of(stack,
69 struct or1k_frameinfo,
70 top);
71
72 if (__kernel_text_address(frameinfo->ra)) {
73 if (or1k_frameinfo_valid(frameinfo) &&
74 (next_fp == NULL ||
75 next_fp == &frameinfo->top)) {
76 reliable = 1;
77 next_fp = frameinfo->fp;
78 } else
79 reliable = 0;
80
81 trace(data, frameinfo->ra, reliable);
82 }
83 stack++;
84 }
85}
86
87#else
88
89
90
91
92
93void unwind_stack(void *data, unsigned long *stack,
94 void (*trace)(void *data, unsigned long addr, int reliable))
95{
96 unsigned long addr;
97
98 while (!kstack_end(stack)) {
99 addr = *stack++;
100 if (__kernel_text_address(addr))
101 trace(data, addr, 0);
102 }
103}
104#endif
105
106