blob: 5a657986ebbf4bef7beff4e8c8d20f1343872347 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Kernel unwinding support
4 *
5 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
6 *
7 * Derived partially from the IA64 implementation. The PA-RISC
8 * Runtime Architecture Document is also a useful reference to
9 * understand what is happening here
10 */
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/kernel.h>
13#include <linux/init.h>
Matthew Wilcoxe6fc0442006-12-15 09:34:36 -070014#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/slab.h>
16#include <linux/kallsyms.h>
Helge Deller8f78df82009-11-06 23:07:42 +000017#include <linux/sort.h>
Helge Dellere77900a2017-09-17 21:05:02 +020018#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080020#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <asm/assembly.h>
Randolph Chung05dc16d2007-06-12 14:27:32 +080022#include <asm/asm-offsets.h>
23#include <asm/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#include <asm/unwind.h>
26
27/* #define DEBUG 1 */
28#ifdef DEBUG
29#define dbg(x...) printk(x)
30#else
31#define dbg(x...)
32#endif
33
Helge Deller33a932d2009-11-28 20:33:11 +000034#define KERNEL_START (KERNEL_BINARY_TEXT_START)
Randolph Chunge0363062007-06-12 14:27:32 +080035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036extern struct unwind_table_entry __start___unwind[];
37extern struct unwind_table_entry __stop___unwind[];
38
Helge Deller76cffeb2017-08-04 23:54:19 +020039static DEFINE_SPINLOCK(unwind_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040/*
41 * the kernel unwind block is not dynamically allocated so that
42 * we can call unwind_init as early in the bootup process as
43 * possible (before the slab allocator is initialized)
44 */
Helge Deller8039de12006-01-10 20:35:03 -050045static struct unwind_table kernel_unwind_table __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -070046static LIST_HEAD(unwind_tables);
47
48static inline const struct unwind_table_entry *
49find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
50{
51 const struct unwind_table_entry *e = NULL;
52 unsigned long lo, hi, mid;
53
54 lo = 0;
55 hi = table->length - 1;
56
57 while (lo <= hi) {
58 mid = (hi - lo) / 2 + lo;
59 e = &table->table[mid];
60 if (addr < e->region_start)
61 hi = mid - 1;
62 else if (addr > e->region_end)
63 lo = mid + 1;
64 else
65 return e;
66 }
67
68 return NULL;
69}
70
71static const struct unwind_table_entry *
72find_unwind_entry(unsigned long addr)
73{
74 struct unwind_table *table;
75 const struct unwind_table_entry *e = NULL;
76
77 if (addr >= kernel_unwind_table.start &&
78 addr <= kernel_unwind_table.end)
79 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
Mikulas Patockabe24a8972011-06-29 00:48:19 +020080 else {
81 unsigned long flags;
82
83 spin_lock_irqsave(&unwind_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 list_for_each_entry(table, &unwind_tables, list) {
85 if (addr >= table->start &&
86 addr <= table->end)
87 e = find_unwind_entry_in_table(table, addr);
Phil Carmodyb1b1d4a2010-09-10 13:47:59 +030088 if (e) {
89 /* Move-to-front to exploit common traces */
90 list_move(&table->list, &unwind_tables);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 break;
Phil Carmodyb1b1d4a2010-09-10 13:47:59 +030092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 }
Mikulas Patockabe24a8972011-06-29 00:48:19 +020094 spin_unlock_irqrestore(&unwind_lock, flags);
95 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97 return e;
98}
99
100static void
101unwind_table_init(struct unwind_table *table, const char *name,
102 unsigned long base_addr, unsigned long gp,
103 void *table_start, void *table_end)
104{
105 struct unwind_table_entry *start = table_start;
106 struct unwind_table_entry *end =
107 (struct unwind_table_entry *)table_end - 1;
108
109 table->name = name;
110 table->base_addr = base_addr;
111 table->gp = gp;
112 table->start = base_addr + start->region_start;
113 table->end = base_addr + end->region_end;
114 table->table = (struct unwind_table_entry *)table_start;
115 table->length = end - start + 1;
116 INIT_LIST_HEAD(&table->list);
117
118 for (; start <= end; start++) {
119 if (start < end &&
120 start->region_end > (start+1)->region_start) {
121 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1);
122 }
123
124 start->region_start += base_addr;
125 start->region_end += base_addr;
126 }
127}
128
Helge Deller8f78df82009-11-06 23:07:42 +0000129static int cmp_unwind_table_entry(const void *a, const void *b)
130{
131 return ((const struct unwind_table_entry *)a)->region_start
132 - ((const struct unwind_table_entry *)b)->region_start;
133}
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135static void
136unwind_table_sort(struct unwind_table_entry *start,
137 struct unwind_table_entry *finish)
138{
Helge Deller8f78df82009-11-06 23:07:42 +0000139 sort(start, finish - start, sizeof(struct unwind_table_entry),
140 cmp_unwind_table_entry, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141}
142
143struct unwind_table *
144unwind_table_add(const char *name, unsigned long base_addr,
145 unsigned long gp,
146 void *start, void *end)
147{
148 struct unwind_table *table;
149 unsigned long flags;
150 struct unwind_table_entry *s = (struct unwind_table_entry *)start;
151 struct unwind_table_entry *e = (struct unwind_table_entry *)end;
152
153 unwind_table_sort(s, e);
154
155 table = kmalloc(sizeof(struct unwind_table), GFP_USER);
156 if (table == NULL)
157 return NULL;
158 unwind_table_init(table, name, base_addr, gp, start, end);
159 spin_lock_irqsave(&unwind_lock, flags);
160 list_add_tail(&table->list, &unwind_tables);
161 spin_unlock_irqrestore(&unwind_lock, flags);
162
163 return table;
164}
165
166void unwind_table_remove(struct unwind_table *table)
167{
168 unsigned long flags;
169
170 spin_lock_irqsave(&unwind_lock, flags);
171 list_del(&table->list);
172 spin_unlock_irqrestore(&unwind_lock, flags);
173
174 kfree(table);
175}
176
177/* Called from setup_arch to import the kernel unwind info */
Helge Dellerc790b412013-11-30 21:23:20 +0100178int __init unwind_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179{
180 long start, stop;
181 register unsigned long gp __asm__ ("r27");
182
183 start = (long)&__start___unwind[0];
184 stop = (long)&__stop___unwind[0];
185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
187 start, stop,
188 (stop - start) / sizeof(struct unwind_table_entry));
189
190 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
191 gp,
192 &__start___unwind[0], &__stop___unwind[0]);
193#if 0
194 {
195 int i;
196 for (i = 0; i < 10; i++)
197 {
198 printk("region 0x%x-0x%x\n",
199 __start___unwind[i].region_start,
200 __start___unwind[i].region_end);
201 }
202 }
203#endif
204 return 0;
205}
206
Randolph Chung05dc16d2007-06-12 14:27:32 +0800207#ifdef CONFIG_64BIT
208#define get_func_addr(fptr) fptr[2]
209#else
210#define get_func_addr(fptr) fptr[0]
211#endif
212
213static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
214{
Kyle McMartin78199942007-10-18 00:03:56 -0700215 extern void handle_interruption(int, struct pt_regs *);
216 static unsigned long *hi = (unsigned long *)&handle_interruption;
Randolph Chung05dc16d2007-06-12 14:27:32 +0800217
218 if (pc == get_func_addr(hi)) {
219 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
220 dbg("Unwinding through handle_interruption()\n");
221 info->prev_sp = regs->gr[30];
222 info->prev_ip = regs->iaoq[0];
223
224 return 1;
225 }
226
227 return 0;
228}
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230static void unwind_frame_regs(struct unwind_frame_info *info)
231{
232 const struct unwind_table_entry *e;
233 unsigned long npc;
234 unsigned int insn;
235 long frame_size = 0;
236 int looking_for_rp, rpoffset = 0;
237
238 e = find_unwind_entry(info->ip);
239 if (e == NULL) {
240 unsigned long sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
242 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
243
244#ifdef CONFIG_KALLSYMS
245 /* Handle some frequent special cases.... */
246 {
Tejun Heo9281acea2007-07-17 04:03:51 -0700247 char symname[KSYM_NAME_LEN];
Kyle McMartincb957792007-05-30 02:24:28 -0400248 char *modname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Kyle McMartincb957792007-05-30 02:24:28 -0400250 kallsyms_lookup(info->ip, NULL, NULL, &modname,
251 symname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
254
255 if (strcmp(symname, "_switch_to_ret") == 0) {
256 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
257 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
258 dbg("_switch_to_ret @ %lx - setting "
259 "prev_sp=%lx prev_ip=%lx\n",
260 info->ip, info->prev_sp,
261 info->prev_ip);
262 return;
263 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 ||
264 strcmp(symname, "syscall_exit") == 0) {
265 info->prev_ip = info->prev_sp = 0;
266 return;
267 }
268 }
269#endif
270
271 /* Since we are doing the unwinding blind, we don't know if
272 we are adjusting the stack correctly or extracting the rp
273 correctly. The rp is checked to see if it belongs to the
274 kernel text section, if not we assume we don't have a
275 correct stack frame and we continue to unwind the stack.
276 This is not quite correct, and will fail for loadable
277 modules. */
278 sp = info->sp & ~63;
279 do {
280 unsigned long tmp;
281
282 info->prev_sp = sp - 64;
283 info->prev_ip = 0;
Helge Dellere77900a2017-09-17 21:05:02 +0200284
285 /* The stack is at the end inside the thread_union
286 * struct. If we reach data, we have reached the
287 * beginning of the stack and should stop unwinding. */
288 if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
289 info->prev_sp < ((unsigned long) task_thread_info(info->t)
290 + THREAD_SZ_ALGN)) {
291 info->prev_sp = 0;
292 break;
293 }
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
296 break;
297 info->prev_ip = tmp;
298 sp = info->prev_sp;
Helge Dellerc790b412013-11-30 21:23:20 +0100299 } while (!kernel_text_address(info->prev_ip));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 info->rp = 0;
302
303 dbg("analyzing func @ %lx with no unwind info, setting "
304 "prev_sp=%lx prev_ip=%lx\n", info->ip,
305 info->prev_sp, info->prev_ip);
306 } else {
307 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
308 "Save_RP = %d, Millicode = %d size = %u\n",
309 e->region_start, e->region_end, e->Save_SP, e->Save_RP,
310 e->Millicode, e->Total_frame_size);
311
312 looking_for_rp = e->Save_RP;
313
314 for (npc = e->region_start;
315 (frame_size < (e->Total_frame_size << 3) ||
316 looking_for_rp) &&
317 npc < info->ip;
318 npc += 4) {
319
320 insn = *(unsigned int *)npc;
321
Mikulas Patockabe24a8972011-06-29 00:48:19 +0200322 if ((insn & 0xffffc001) == 0x37de0000 ||
323 (insn & 0xffe00001) == 0x6fc00000) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 /* ldo X(sp), sp, or stwm X,D(sp) */
Mikulas Patockabe24a8972011-06-29 00:48:19 +0200325 frame_size += (insn & 0x3fff) >> 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 dbg("analyzing func @ %lx, insn=%08x @ "
327 "%lx, frame_size = %ld\n", info->ip,
328 insn, npc, frame_size);
Mikulas Patockabe24a8972011-06-29 00:48:19 +0200329 } else if ((insn & 0xffe00009) == 0x73c00008) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 /* std,ma X,D(sp) */
Mikulas Patockabe24a8972011-06-29 00:48:19 +0200331 frame_size += ((insn >> 4) & 0x3ff) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 dbg("analyzing func @ %lx, insn=%08x @ "
333 "%lx, frame_size = %ld\n", info->ip,
334 insn, npc, frame_size);
335 } else if (insn == 0x6bc23fd9) {
336 /* stw rp,-20(sp) */
337 rpoffset = 20;
338 looking_for_rp = 0;
339 dbg("analyzing func @ %lx, insn=stw rp,"
340 "-20(sp) @ %lx\n", info->ip, npc);
341 } else if (insn == 0x0fc212c1) {
342 /* std rp,-16(sr0,sp) */
343 rpoffset = 16;
344 looking_for_rp = 0;
345 dbg("analyzing func @ %lx, insn=std rp,"
346 "-16(sp) @ %lx\n", info->ip, npc);
347 }
348 }
349
Mikulas Patockabe24a8972011-06-29 00:48:19 +0200350 if (frame_size > e->Total_frame_size << 3)
351 frame_size = e->Total_frame_size << 3;
352
Randolph Chung05dc16d2007-06-12 14:27:32 +0800353 if (!unwind_special(info, e->region_start, frame_size)) {
354 info->prev_sp = info->sp - frame_size;
355 if (e->Millicode)
356 info->rp = info->r31;
357 else if (rpoffset)
358 info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
359 info->prev_ip = info->rp;
360 info->rp = 0;
361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 dbg("analyzing func @ %lx, setting prev_sp=%lx "
364 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
365 info->prev_ip, npc);
366 }
367}
368
369void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
370 struct pt_regs *regs)
371{
372 memset(info, 0, sizeof(struct unwind_frame_info));
373 info->t = t;
374 info->sp = regs->gr[30];
375 info->ip = regs->iaoq[0];
376 info->rp = regs->gr[2];
377 info->r31 = regs->gr[31];
378
379 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
380 t ? (int)t->pid : -1, info->sp, info->ip);
381}
382
383void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
384{
385 struct pt_regs *r = &t->thread.regs;
386 struct pt_regs *r2;
387
Helge Dellere0e7ed42008-12-17 23:57:34 +0100388 r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (!r2)
390 return;
391 *r2 = *r;
392 r2->gr[30] = r->ksp;
393 r2->iaoq[0] = r->kpc;
394 unwind_frame_init(info, t, r2);
395 kfree(r2);
396}
397
398void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
399{
400 unwind_frame_init(info, current, regs);
401}
402
403int unwind_once(struct unwind_frame_info *next_frame)
404{
405 unwind_frame_regs(next_frame);
406
407 if (next_frame->prev_sp == 0 ||
408 next_frame->prev_ip == 0)
409 return -1;
410
411 next_frame->sp = next_frame->prev_sp;
412 next_frame->ip = next_frame->prev_ip;
413 next_frame->prev_sp = 0;
414 next_frame->prev_ip = 0;
415
416 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
417 next_frame->t ? (int)next_frame->t->pid : -1,
418 next_frame->sp, next_frame->ip);
419
420 return 0;
421}
422
423int unwind_to_user(struct unwind_frame_info *info)
424{
425 int ret;
426
427 do {
428 ret = unwind_once(info);
429 } while (!ret && !(info->ip & 3));
430
431 return ret;
432}
Helge Deller11e178092009-10-25 21:48:36 +0000433
434unsigned long return_address(unsigned int level)
435{
436 struct unwind_frame_info info;
437 struct pt_regs r;
438 unsigned long sp;
439
440 /* initialize unwind info */
441 asm volatile ("copy %%r30, %0" : "=r"(sp));
442 memset(&r, 0, sizeof(struct pt_regs));
443 r.iaoq[0] = (unsigned long) current_text_addr();
444 r.gr[2] = (unsigned long) __builtin_return_address(0);
445 r.gr[30] = sp;
446 unwind_frame_init(&info, current, &r);
447
448 /* unwind stack */
449 ++level;
450 do {
451 if (unwind_once(&info) < 0 || info.ip == 0)
452 return 0;
Helge Dellerc790b412013-11-30 21:23:20 +0100453 if (!kernel_text_address(info.ip))
Helge Deller11e178092009-10-25 21:48:36 +0000454 return 0;
Helge Deller11e178092009-10-25 21:48:36 +0000455 } while (info.ip && level--);
456
457 return info.ip;
458}