• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
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 
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/slab.h>
16 #include <linux/sort.h>
17 
18 #include <linux/uaccess.h>
19 #include <asm/assembly.h>
20 #include <asm/asm-offsets.h>
21 #include <asm/ptrace.h>
22 
23 #include <asm/unwind.h>
24 #include <asm/switch_to.h>
25 #include <asm/sections.h>
26 
27 /* #define DEBUG 1 */
28 #ifdef DEBUG
29 #define dbg(x...) pr_debug(x)
30 #else
31 #define dbg(x...)
32 #endif
33 
34 #define KERNEL_START (KERNEL_BINARY_TEXT_START)
35 
36 extern struct unwind_table_entry __start___unwind[];
37 extern struct unwind_table_entry __stop___unwind[];
38 
39 static DEFINE_SPINLOCK(unwind_lock);
40 /*
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  */
45 static struct unwind_table kernel_unwind_table __ro_after_init;
46 static LIST_HEAD(unwind_tables);
47 
48 static inline const struct unwind_table_entry *
find_unwind_entry_in_table(const struct unwind_table * table,unsigned long addr)49 find_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 
71 static const struct unwind_table_entry *
find_unwind_entry(unsigned long addr)72 find_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);
80 	else {
81 		unsigned long flags;
82 
83 		spin_lock_irqsave(&unwind_lock, flags);
84 		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);
88 			if (e) {
89 				/* Move-to-front to exploit common traces */
90 				list_move(&table->list, &unwind_tables);
91 				break;
92 			}
93 		}
94 		spin_unlock_irqrestore(&unwind_lock, flags);
95 	}
96 
97 	return e;
98 }
99 
100 static void
unwind_table_init(struct unwind_table * table,const char * name,unsigned long base_addr,unsigned long gp,void * table_start,void * table_end)101 unwind_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 			pr_warn("Out of order unwind entry! %px and %px\n",
122 				start, start+1);
123 		}
124 
125 		start->region_start += base_addr;
126 		start->region_end += base_addr;
127 	}
128 }
129 
cmp_unwind_table_entry(const void * a,const void * b)130 static int cmp_unwind_table_entry(const void *a, const void *b)
131 {
132 	return ((const struct unwind_table_entry *)a)->region_start
133 	     - ((const struct unwind_table_entry *)b)->region_start;
134 }
135 
136 static void
unwind_table_sort(struct unwind_table_entry * start,struct unwind_table_entry * finish)137 unwind_table_sort(struct unwind_table_entry *start,
138 		  struct unwind_table_entry *finish)
139 {
140 	sort(start, finish - start, sizeof(struct unwind_table_entry),
141 	     cmp_unwind_table_entry, NULL);
142 }
143 
144 struct unwind_table *
unwind_table_add(const char * name,unsigned long base_addr,unsigned long gp,void * start,void * end)145 unwind_table_add(const char *name, unsigned long base_addr,
146 		 unsigned long gp,
147                  void *start, void *end)
148 {
149 	struct unwind_table *table;
150 	unsigned long flags;
151 	struct unwind_table_entry *s = (struct unwind_table_entry *)start;
152 	struct unwind_table_entry *e = (struct unwind_table_entry *)end;
153 
154 	unwind_table_sort(s, e);
155 
156 	table = kmalloc(sizeof(struct unwind_table), GFP_USER);
157 	if (table == NULL)
158 		return NULL;
159 	unwind_table_init(table, name, base_addr, gp, start, end);
160 	spin_lock_irqsave(&unwind_lock, flags);
161 	list_add_tail(&table->list, &unwind_tables);
162 	spin_unlock_irqrestore(&unwind_lock, flags);
163 
164 	return table;
165 }
166 
unwind_table_remove(struct unwind_table * table)167 void unwind_table_remove(struct unwind_table *table)
168 {
169 	unsigned long flags;
170 
171 	spin_lock_irqsave(&unwind_lock, flags);
172 	list_del(&table->list);
173 	spin_unlock_irqrestore(&unwind_lock, flags);
174 
175 	kfree(table);
176 }
177 
178 /* Called from setup_arch to import the kernel unwind info */
unwind_init(void)179 int __init unwind_init(void)
180 {
181 	long start, stop;
182 	register unsigned long gp __asm__ ("r27");
183 
184 	start = (long)&__start___unwind[0];
185 	stop = (long)&__stop___unwind[0];
186 
187 	dbg("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
188 	    start, stop,
189 	    (stop - start) / sizeof(struct unwind_table_entry));
190 
191 	unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
192 			  gp,
193 			  &__start___unwind[0], &__stop___unwind[0]);
194 #if 0
195 	{
196 		int i;
197 		for (i = 0; i < 10; i++)
198 		{
199 			printk("region 0x%x-0x%x\n",
200 				__start___unwind[i].region_start,
201 				__start___unwind[i].region_end);
202 		}
203 	}
204 #endif
205 	return 0;
206 }
207 
pc_is_kernel_fn(unsigned long pc,void * fn)208 static bool pc_is_kernel_fn(unsigned long pc, void *fn)
209 {
210 	return (unsigned long)dereference_kernel_function_descriptor(fn) == pc;
211 }
212 
unwind_special(struct unwind_frame_info * info,unsigned long pc,int frame_size)213 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
214 {
215 	/*
216 	 * We have to use void * instead of a function pointer, because
217 	 * function pointers aren't a pointer to the function on 64-bit.
218 	 * Make them const so the compiler knows they live in .text
219 	 * Note: We could use dereference_kernel_function_descriptor()
220 	 * instead but we want to keep it simple here.
221 	 */
222 	extern void * const handle_interruption;
223 	extern void * const ret_from_kernel_thread;
224 	extern void * const syscall_exit;
225 	extern void * const intr_return;
226 	extern void * const _switch_to_ret;
227 #ifdef CONFIG_IRQSTACKS
228 	extern void * const _call_on_stack;
229 #endif /* CONFIG_IRQSTACKS */
230 
231 	if (pc_is_kernel_fn(pc, handle_interruption)) {
232 		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
233 		dbg("Unwinding through handle_interruption()\n");
234 		info->prev_sp = regs->gr[30];
235 		info->prev_ip = regs->iaoq[0];
236 		return 1;
237 	}
238 
239 	if (pc_is_kernel_fn(pc, ret_from_kernel_thread) ||
240 	    pc_is_kernel_fn(pc, syscall_exit)) {
241 		info->prev_sp = info->prev_ip = 0;
242 		return 1;
243 	}
244 
245 	if (pc_is_kernel_fn(pc, intr_return)) {
246 		struct pt_regs *regs;
247 
248 		dbg("Found intr_return()\n");
249 		regs = (struct pt_regs *)(info->sp - PT_SZ_ALGN);
250 		info->prev_sp = regs->gr[30];
251 		info->prev_ip = regs->iaoq[0];
252 		info->rp = regs->gr[2];
253 		return 1;
254 	}
255 
256 	if (pc_is_kernel_fn(pc, _switch_to) ||
257 	    pc_is_kernel_fn(pc, _switch_to_ret)) {
258 		info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
259 		info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
260 		return 1;
261 	}
262 
263 #ifdef CONFIG_IRQSTACKS
264 	if (pc_is_kernel_fn(pc, _call_on_stack)) {
265 		info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
266 		info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
267 		return 1;
268 	}
269 #endif
270 	return 0;
271 }
272 
unwind_frame_regs(struct unwind_frame_info * info)273 static void unwind_frame_regs(struct unwind_frame_info *info)
274 {
275 	const struct unwind_table_entry *e;
276 	unsigned long npc;
277 	unsigned int insn;
278 	long frame_size = 0;
279 	int looking_for_rp, rpoffset = 0;
280 
281 	e = find_unwind_entry(info->ip);
282 	if (e == NULL) {
283 		unsigned long sp;
284 
285 		dbg("Cannot find unwind entry for %pS; forced unwinding\n",
286 			(void *) info->ip);
287 
288 		/* Since we are doing the unwinding blind, we don't know if
289 		   we are adjusting the stack correctly or extracting the rp
290 		   correctly. The rp is checked to see if it belongs to the
291 		   kernel text section, if not we assume we don't have a
292 		   correct stack frame and we continue to unwind the stack.
293 		   This is not quite correct, and will fail for loadable
294 		   modules. */
295 		sp = info->sp & ~63;
296 		do {
297 			unsigned long tmp;
298 
299 			info->prev_sp = sp - 64;
300 			info->prev_ip = 0;
301 
302 			/* The stack is at the end inside the thread_union
303 			 * struct. If we reach data, we have reached the
304 			 * beginning of the stack and should stop unwinding. */
305 			if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
306 			    info->prev_sp < ((unsigned long) task_thread_info(info->t)
307 						+ THREAD_SZ_ALGN)) {
308 				info->prev_sp = 0;
309 				break;
310 			}
311 
312 			if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
313 				break;
314 			info->prev_ip = tmp;
315 			sp = info->prev_sp;
316 		} while (!kernel_text_address(info->prev_ip));
317 
318 		info->rp = 0;
319 
320 		dbg("analyzing func @ %lx with no unwind info, setting "
321 		    "prev_sp=%lx prev_ip=%lx\n", info->ip,
322 		    info->prev_sp, info->prev_ip);
323 	} else {
324 		dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
325 		    "Save_RP = %d, Millicode = %d size = %u\n",
326 		    e->region_start, e->region_end, e->Save_SP, e->Save_RP,
327 		    e->Millicode, e->Total_frame_size);
328 
329 		looking_for_rp = e->Save_RP;
330 
331 		for (npc = e->region_start;
332 		     (frame_size < (e->Total_frame_size << 3) ||
333 		      looking_for_rp) &&
334 		     npc < info->ip;
335 		     npc += 4) {
336 
337 			insn = *(unsigned int *)npc;
338 
339 			if ((insn & 0xffffc001) == 0x37de0000 ||
340 			    (insn & 0xffe00001) == 0x6fc00000) {
341 				/* ldo X(sp), sp, or stwm X,D(sp) */
342 				frame_size += (insn & 0x3fff) >> 1;
343 				dbg("analyzing func @ %lx, insn=%08x @ "
344 				    "%lx, frame_size = %ld\n", info->ip,
345 				    insn, npc, frame_size);
346 			} else if ((insn & 0xffe00009) == 0x73c00008) {
347 				/* std,ma X,D(sp) */
348 				frame_size += ((insn >> 4) & 0x3ff) << 3;
349 				dbg("analyzing func @ %lx, insn=%08x @ "
350 				    "%lx, frame_size = %ld\n", info->ip,
351 				    insn, npc, frame_size);
352 			} else if (insn == 0x6bc23fd9) {
353 				/* stw rp,-20(sp) */
354 				rpoffset = 20;
355 				looking_for_rp = 0;
356 				dbg("analyzing func @ %lx, insn=stw rp,"
357 				    "-20(sp) @ %lx\n", info->ip, npc);
358 			} else if (insn == 0x0fc212c1) {
359 				/* std rp,-16(sr0,sp) */
360 				rpoffset = 16;
361 				looking_for_rp = 0;
362 				dbg("analyzing func @ %lx, insn=std rp,"
363 				    "-16(sp) @ %lx\n", info->ip, npc);
364 			}
365 		}
366 
367 		if (frame_size > e->Total_frame_size << 3)
368 			frame_size = e->Total_frame_size << 3;
369 
370 		if (!unwind_special(info, e->region_start, frame_size)) {
371 			info->prev_sp = info->sp - frame_size;
372 			if (e->Millicode)
373 				info->rp = info->r31;
374 			else if (rpoffset)
375 				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
376 			info->prev_ip = info->rp;
377 			info->rp = 0;
378 		}
379 
380 		dbg("analyzing func @ %lx, setting prev_sp=%lx "
381 		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
382 		    info->prev_ip, npc);
383 	}
384 }
385 
unwind_frame_init(struct unwind_frame_info * info,struct task_struct * t,struct pt_regs * regs)386 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
387 		       struct pt_regs *regs)
388 {
389 	memset(info, 0, sizeof(struct unwind_frame_info));
390 	info->t = t;
391 	info->sp = regs->gr[30];
392 	info->ip = regs->iaoq[0];
393 	info->rp = regs->gr[2];
394 	info->r31 = regs->gr[31];
395 
396 	dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
397 	    t ? (int)t->pid : -1, info->sp, info->ip);
398 }
399 
unwind_frame_init_from_blocked_task(struct unwind_frame_info * info,struct task_struct * t)400 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
401 {
402 	struct pt_regs *r = &t->thread.regs;
403 	struct pt_regs *r2;
404 
405 	r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
406 	if (!r2)
407 		return;
408 	*r2 = *r;
409 	r2->gr[30] = r->ksp;
410 	r2->iaoq[0] = r->kpc;
411 	unwind_frame_init(info, t, r2);
412 	kfree(r2);
413 }
414 
415 #define get_parisc_stackpointer() ({ \
416 	unsigned long sp; \
417 	__asm__("copy %%r30, %0" : "=r"(sp)); \
418 	(sp); \
419 })
420 
unwind_frame_init_task(struct unwind_frame_info * info,struct task_struct * task,struct pt_regs * regs)421 void unwind_frame_init_task(struct unwind_frame_info *info,
422 	struct task_struct *task, struct pt_regs *regs)
423 {
424 	task = task ? task : current;
425 
426 	if (task == current) {
427 		struct pt_regs r;
428 
429 		if (!regs) {
430 			memset(&r, 0, sizeof(r));
431 			r.iaoq[0] =  _THIS_IP_;
432 			r.gr[2] = _RET_IP_;
433 			r.gr[30] = get_parisc_stackpointer();
434 			regs = &r;
435 		}
436 		unwind_frame_init(info, task, regs);
437 	} else {
438 		unwind_frame_init_from_blocked_task(info, task);
439 	}
440 }
441 
unwind_once(struct unwind_frame_info * next_frame)442 int unwind_once(struct unwind_frame_info *next_frame)
443 {
444 	unwind_frame_regs(next_frame);
445 
446 	if (next_frame->prev_sp == 0 ||
447 	    next_frame->prev_ip == 0)
448 		return -1;
449 
450 	next_frame->sp = next_frame->prev_sp;
451 	next_frame->ip = next_frame->prev_ip;
452 	next_frame->prev_sp = 0;
453 	next_frame->prev_ip = 0;
454 
455 	dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
456 	    next_frame->t ? (int)next_frame->t->pid : -1,
457 	    next_frame->sp, next_frame->ip);
458 
459 	return 0;
460 }
461 
unwind_to_user(struct unwind_frame_info * info)462 int unwind_to_user(struct unwind_frame_info *info)
463 {
464 	int ret;
465 
466 	do {
467 		ret = unwind_once(info);
468 	} while (!ret && !(info->ip & 3));
469 
470 	return ret;
471 }
472 
return_address(unsigned int level)473 unsigned long return_address(unsigned int level)
474 {
475 	struct unwind_frame_info info;
476 
477 	/* initialize unwind info */
478 	unwind_frame_init_task(&info, current, NULL);
479 
480 	/* unwind stack */
481 	level += 2;
482 	do {
483 		if (unwind_once(&info) < 0 || info.ip == 0)
484 			return 0;
485 		if (!kernel_text_address(info.ip))
486 			return 0;
487 	} while (info.ip && level--);
488 
489 	return info.ip;
490 }
491