@@ -19,32 +19,14 @@ static inline void unwind_state_fixup(struct unwind_state *state)
19
19
#endif
20
20
}
21
21
22
- unsigned long unwind_get_return_address (struct unwind_state * state )
23
- {
24
- if (unwind_done (state ))
25
- return 0 ;
26
-
27
- return state -> pc ;
28
- }
29
- EXPORT_SYMBOL_GPL (unwind_get_return_address );
30
-
31
- static bool unwind_by_guess (struct unwind_state * state )
32
- {
33
- struct stack_info * info = & state -> stack_info ;
34
- unsigned long addr ;
35
-
36
- for (state -> sp += sizeof (unsigned long );
37
- state -> sp < info -> end ;
38
- state -> sp += sizeof (unsigned long )) {
39
- addr = * (unsigned long * )(state -> sp );
40
- state -> pc = unwind_graph_addr (state , addr , state -> sp + 8 );
41
- if (__kernel_text_address (state -> pc ))
42
- return true;
43
- }
44
-
45
- return false;
46
- }
47
-
22
+ /*
23
+ * LoongArch function prologue is like follows,
24
+ * [instructions not use stack var]
25
+ * addi.d sp, sp, -imm
26
+ * st.d xx, sp, offset <- save callee saved regs and
27
+ * st.d yy, sp, offset save ra if function is nest.
28
+ * [others instructions]
29
+ */
48
30
static bool unwind_by_prologue (struct unwind_state * state )
49
31
{
50
32
long frame_ra = -1 ;
@@ -91,6 +73,10 @@ static bool unwind_by_prologue(struct unwind_state *state)
91
73
ip ++ ;
92
74
}
93
75
76
+ /*
77
+ * Can't find stack alloc action, PC may be in a leaf function. Only the
78
+ * first being true is reasonable, otherwise indicate analysis is broken.
79
+ */
94
80
if (!frame_size ) {
95
81
if (state -> first )
96
82
goto first ;
@@ -108,6 +94,7 @@ static bool unwind_by_prologue(struct unwind_state *state)
108
94
ip ++ ;
109
95
}
110
96
97
+ /* Can't find save $ra action, PC may be in a leaf function, too. */
111
98
if (frame_ra < 0 ) {
112
99
if (state -> first ) {
113
100
state -> sp = state -> sp + frame_size ;
@@ -116,96 +103,48 @@ static bool unwind_by_prologue(struct unwind_state *state)
116
103
return false;
117
104
}
118
105
119
- if (state -> first )
120
- state -> first = false;
121
-
122
106
state -> pc = * (unsigned long * )(state -> sp + frame_ra );
123
107
state -> sp = state -> sp + frame_size ;
124
108
goto out ;
125
109
126
110
first :
127
- state -> first = false;
128
- if (state -> pc == state -> ra )
129
- return false;
130
-
131
111
state -> pc = state -> ra ;
132
112
133
113
out :
114
+ state -> first = false;
134
115
unwind_state_fixup (state );
135
116
return !!__kernel_text_address (state -> pc );
136
117
}
137
118
138
- void unwind_start (struct unwind_state * state , struct task_struct * task ,
139
- struct pt_regs * regs )
140
- {
141
- memset (state , 0 , sizeof (* state ));
142
- state -> type = UNWINDER_PROLOGUE ;
143
-
144
- if (regs ) {
145
- state -> sp = regs -> regs [3 ];
146
- state -> pc = regs -> csr_era ;
147
- state -> ra = regs -> regs [1 ];
148
- if (!__kernel_text_address (state -> pc ))
149
- state -> type = UNWINDER_GUESS ;
150
- } else if (task && task != current ) {
151
- state -> sp = thread_saved_fp (task );
152
- state -> pc = thread_saved_ra (task );
153
- state -> ra = 0 ;
154
- } else {
155
- state -> sp = (unsigned long )__builtin_frame_address (0 );
156
- state -> pc = (unsigned long )__builtin_return_address (0 );
157
- state -> ra = 0 ;
158
- }
159
-
160
- state -> task = task ;
161
- state -> first = true;
162
- state -> pc = unwind_graph_addr (state , state -> pc , state -> sp );
163
- get_stack_info (state -> sp , state -> task , & state -> stack_info );
164
-
165
- if (!unwind_done (state ) && !__kernel_text_address (state -> pc ))
166
- unwind_next_frame (state );
167
- }
168
- EXPORT_SYMBOL_GPL (unwind_start );
169
-
170
- bool unwind_next_frame (struct unwind_state * state )
119
+ static bool next_frame (struct unwind_state * state )
171
120
{
172
- struct stack_info * info = & state -> stack_info ;
173
- struct pt_regs * regs ;
174
121
unsigned long pc ;
122
+ struct pt_regs * regs ;
123
+ struct stack_info * info = & state -> stack_info ;
175
124
176
125
if (unwind_done (state ))
177
126
return false;
178
127
179
128
do {
180
- switch (state -> type ) {
181
- case UNWINDER_GUESS :
182
- state -> first = false;
183
- if (unwind_by_guess (state ))
184
- return true;
185
- break ;
186
-
187
- case UNWINDER_PROLOGUE :
188
- if (unwind_by_prologue (state )) {
189
- state -> pc = unwind_graph_addr (state , state -> pc , state -> sp );
190
- return true;
191
- }
129
+ if (unwind_by_prologue (state )) {
130
+ state -> pc = unwind_graph_addr (state , state -> pc , state -> sp );
131
+ return true;
132
+ }
192
133
193
- if (info -> type == STACK_TYPE_IRQ &&
194
- info -> end == state -> sp ) {
195
- regs = (struct pt_regs * )info -> next_sp ;
196
- pc = regs -> csr_era ;
134
+ if (info -> type == STACK_TYPE_IRQ && info -> end == state -> sp ) {
135
+ regs = (struct pt_regs * )info -> next_sp ;
136
+ pc = regs -> csr_era ;
197
137
198
- if (user_mode (regs ) || !__kernel_text_address (pc ))
199
- return false;
138
+ if (user_mode (regs ) || !__kernel_text_address (pc ))
139
+ return false;
200
140
201
- state -> first = true;
202
- state -> ra = regs -> regs [ 1 ] ;
203
- state -> sp = regs -> regs [3 ];
204
- state -> pc = pc ;
205
- get_stack_info (state -> sp , state -> task , info );
141
+ state -> first = true;
142
+ state -> pc = pc ;
143
+ state -> ra = regs -> regs [1 ];
144
+ state -> sp = regs -> regs [ 3 ] ;
145
+ get_stack_info (state -> sp , state -> task , info );
206
146
207
- return true;
208
- }
147
+ return true;
209
148
}
210
149
211
150
state -> sp = info -> next_sp ;
@@ -214,4 +153,36 @@ bool unwind_next_frame(struct unwind_state *state)
214
153
215
154
return false;
216
155
}
156
+
157
+ unsigned long unwind_get_return_address (struct unwind_state * state )
158
+ {
159
+ return __unwind_get_return_address (state );
160
+ }
161
+ EXPORT_SYMBOL_GPL (unwind_get_return_address );
162
+
163
+ void unwind_start (struct unwind_state * state , struct task_struct * task ,
164
+ struct pt_regs * regs )
165
+ {
166
+ __unwind_start (state , task , regs );
167
+ state -> type = UNWINDER_PROLOGUE ;
168
+ state -> first = true;
169
+
170
+ /*
171
+ * The current PC is not kernel text address, we cannot find its
172
+ * relative symbol. Thus, prologue analysis will be broken. Luckily,
173
+ * we can use the default_next_frame().
174
+ */
175
+ if (!__kernel_text_address (state -> pc )) {
176
+ state -> type = UNWINDER_GUESS ;
177
+ if (!unwind_done (state ))
178
+ unwind_next_frame (state );
179
+ }
180
+ }
181
+ EXPORT_SYMBOL_GPL (unwind_start );
182
+
183
+ bool unwind_next_frame (struct unwind_state * state )
184
+ {
185
+ return state -> type == UNWINDER_PROLOGUE ?
186
+ next_frame (state ) : default_next_frame (state );
187
+ }
217
188
EXPORT_SYMBOL_GPL (unwind_next_frame );
0 commit comments