xref: /linux/arch/arc/kernel/unwind.c (revision 4ac6d90867a4de2e12117e755dbd76e08d88697f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4  * Copyright (C) 2002-2006 Novell, Inc.
5  *	Jan Beulich <jbeulich@novell.com>
6  *
7  * A simple API for unwinding kernel stacks.  This is used for
8  * debugging and error reporting purposes.  The kernel doesn't need
9  * full-blown stack unwinding with all the bells and whistles, so there
10  * is not much point in implementing the full Dwarf2 unwind API.
11  */
12 
13 #include <linux/sched.h>
14 #include <linux/module.h>
15 #include <linux/memblock.h>
16 #include <linux/sort.h>
17 #include <linux/slab.h>
18 #include <linux/stop_machine.h>
19 #include <linux/uaccess.h>
20 #include <linux/ptrace.h>
21 #include <asm/sections.h>
22 #include <asm/unaligned.h>
23 #include <asm/unwind.h>
24 
25 extern char __start_unwind[], __end_unwind[];
26 /* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
27 
28 /* #define UNWIND_DEBUG */
29 
30 #ifdef UNWIND_DEBUG
31 int dbg_unw;
32 #define unw_debug(fmt, ...)			\
33 do {						\
34 	if (dbg_unw)				\
35 		pr_info(fmt, ##__VA_ARGS__);	\
36 } while (0);
37 #else
38 #define unw_debug(fmt, ...)
39 #endif
40 
41 #define MAX_STACK_DEPTH 8
42 
43 #define EXTRA_INFO(f) { \
44 		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
45 				% sizeof_field(struct unwind_frame_info, f)) \
46 				+ offsetof(struct unwind_frame_info, f) \
47 				/ sizeof_field(struct unwind_frame_info, f), \
48 				sizeof_field(struct unwind_frame_info, f) \
49 	}
50 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
51 
52 static const struct {
53 	unsigned offs:BITS_PER_LONG / 2;
54 	unsigned width:BITS_PER_LONG / 2;
55 } reg_info[] = {
56 UNW_REGISTER_INFO};
57 
58 #undef PTREGS_INFO
59 #undef EXTRA_INFO
60 
61 #ifndef REG_INVALID
62 #define REG_INVALID(r) (reg_info[r].width == 0)
63 #endif
64 
65 #define DW_CFA_nop                          0x00
66 #define DW_CFA_set_loc                      0x01
67 #define DW_CFA_advance_loc1                 0x02
68 #define DW_CFA_advance_loc2                 0x03
69 #define DW_CFA_advance_loc4                 0x04
70 #define DW_CFA_offset_extended              0x05
71 #define DW_CFA_restore_extended             0x06
72 #define DW_CFA_undefined                    0x07
73 #define DW_CFA_same_value                   0x08
74 #define DW_CFA_register                     0x09
75 #define DW_CFA_remember_state               0x0a
76 #define DW_CFA_restore_state                0x0b
77 #define DW_CFA_def_cfa                      0x0c
78 #define DW_CFA_def_cfa_register             0x0d
79 #define DW_CFA_def_cfa_offset               0x0e
80 #define DW_CFA_def_cfa_expression           0x0f
81 #define DW_CFA_expression                   0x10
82 #define DW_CFA_offset_extended_sf           0x11
83 #define DW_CFA_def_cfa_sf                   0x12
84 #define DW_CFA_def_cfa_offset_sf            0x13
85 #define DW_CFA_val_offset                   0x14
86 #define DW_CFA_val_offset_sf                0x15
87 #define DW_CFA_val_expression               0x16
88 #define DW_CFA_lo_user                      0x1c
89 #define DW_CFA_GNU_window_save              0x2d
90 #define DW_CFA_GNU_args_size                0x2e
91 #define DW_CFA_GNU_negative_offset_extended 0x2f
92 #define DW_CFA_hi_user                      0x3f
93 
94 #define DW_EH_PE_FORM     0x07
95 #define DW_EH_PE_native   0x00
96 #define DW_EH_PE_leb128   0x01
97 #define DW_EH_PE_data2    0x02
98 #define DW_EH_PE_data4    0x03
99 #define DW_EH_PE_data8    0x04
100 #define DW_EH_PE_signed   0x08
101 #define DW_EH_PE_ADJUST   0x70
102 #define DW_EH_PE_abs      0x00
103 #define DW_EH_PE_pcrel    0x10
104 #define DW_EH_PE_textrel  0x20
105 #define DW_EH_PE_datarel  0x30
106 #define DW_EH_PE_funcrel  0x40
107 #define DW_EH_PE_aligned  0x50
108 #define DW_EH_PE_indirect 0x80
109 #define DW_EH_PE_omit     0xff
110 
111 #define CIE_ID	0
112 
113 typedef unsigned long uleb128_t;
114 typedef signed long sleb128_t;
115 
116 static struct unwind_table {
117 	struct {
118 		unsigned long pc;
119 		unsigned long range;
120 	} core, init;
121 	const void *address;
122 	unsigned long size;
123 	const unsigned char *header;
124 	unsigned long hdrsz;
125 	struct unwind_table *link;
126 	const char *name;
127 } root_table;
128 
129 struct unwind_item {
130 	enum item_location {
131 		Nowhere,
132 		Memory,
133 		Register,
134 		Value
135 	} where;
136 	uleb128_t value;
137 };
138 
139 struct unwind_state {
140 	uleb128_t loc, org;
141 	const u8 *cieStart, *cieEnd;
142 	uleb128_t codeAlign;
143 	sleb128_t dataAlign;
144 	struct cfa {
145 		uleb128_t reg, offs;
146 	} cfa;
147 	struct unwind_item regs[ARRAY_SIZE(reg_info)];
148 	unsigned stackDepth:8;
149 	unsigned version:8;
150 	const u8 *label;
151 	const u8 *stack[MAX_STACK_DEPTH];
152 };
153 
154 static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
155 
156 static struct unwind_table *find_table(unsigned long pc)
157 {
158 	struct unwind_table *table;
159 
160 	for (table = &root_table; table; table = table->link)
161 		if ((pc >= table->core.pc
162 		     && pc < table->core.pc + table->core.range)
163 		    || (pc >= table->init.pc
164 			&& pc < table->init.pc + table->init.range))
165 			break;
166 
167 	return table;
168 }
169 
170 static unsigned long read_pointer(const u8 **pLoc,
171 				  const void *end, signed ptrType);
172 static void init_unwind_hdr(struct unwind_table *table,
173 			    void *(*alloc) (unsigned long));
174 
175 /*
176  * wrappers for header alloc (vs. calling one vs. other at call site)
177  * to elide section mismatches warnings
178  */
179 static void *__init unw_hdr_alloc_early(unsigned long sz)
180 {
181 	return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
182 }
183 
184 static void init_unwind_table(struct unwind_table *table, const char *name,
185 			      const void *core_start, unsigned long core_size,
186 			      const void *init_start, unsigned long init_size,
187 			      const void *table_start, unsigned long table_size,
188 			      const u8 *header_start, unsigned long header_size)
189 {
190 	table->core.pc = (unsigned long)core_start;
191 	table->core.range = core_size;
192 	table->init.pc = (unsigned long)init_start;
193 	table->init.range = init_size;
194 	table->address = table_start;
195 	table->size = table_size;
196 	/* To avoid the pointer addition with NULL pointer.*/
197 	if (header_start != NULL) {
198 		const u8 *ptr = header_start + 4;
199 		const u8 *end = header_start + header_size;
200 		/* See if the linker provided table looks valid. */
201 		if (header_size <= 4
202 		|| header_start[0] != 1
203 		|| (void *)read_pointer(&ptr, end, header_start[1])
204 				!= table_start
205 		|| header_start[2] == DW_EH_PE_omit
206 		|| read_pointer(&ptr, end, header_start[2]) <= 0
207 		|| header_start[3] == DW_EH_PE_omit)
208 			header_start = NULL;
209 	}
210 	table->hdrsz = header_size;
211 	smp_wmb();
212 	table->header = header_start;
213 	table->link = NULL;
214 	table->name = name;
215 }
216 
217 void __init arc_unwind_init(void)
218 {
219 	init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
220 			  __start_unwind, __end_unwind - __start_unwind,
221 			  NULL, 0);
222 	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
223 
224 	init_unwind_hdr(&root_table, unw_hdr_alloc_early);
225 }
226 
227 static const u32 bad_cie, not_fde;
228 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
229 static const u32 *__cie_for_fde(const u32 *fde);
230 static signed fde_pointer_type(const u32 *cie);
231 
232 struct eh_frame_hdr_table_entry {
233 	unsigned long start, fde;
234 };
235 
236 static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
237 {
238 	const struct eh_frame_hdr_table_entry *e1 = p1;
239 	const struct eh_frame_hdr_table_entry *e2 = p2;
240 
241 	return (e1->start > e2->start) - (e1->start < e2->start);
242 }
243 
244 static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
245 {
246 	struct eh_frame_hdr_table_entry *e1 = p1;
247 	struct eh_frame_hdr_table_entry *e2 = p2;
248 	unsigned long v;
249 
250 	v = e1->start;
251 	e1->start = e2->start;
252 	e2->start = v;
253 	v = e1->fde;
254 	e1->fde = e2->fde;
255 	e2->fde = v;
256 }
257 
258 static void init_unwind_hdr(struct unwind_table *table,
259 			    void *(*alloc) (unsigned long))
260 {
261 	const u8 *ptr;
262 	unsigned long tableSize = table->size, hdrSize;
263 	unsigned int n;
264 	const u32 *fde;
265 	struct {
266 		u8 version;
267 		u8 eh_frame_ptr_enc;
268 		u8 fde_count_enc;
269 		u8 table_enc;
270 		unsigned long eh_frame_ptr;
271 		unsigned int fde_count;
272 		struct eh_frame_hdr_table_entry table[];
273 	} __attribute__ ((__packed__)) *header;
274 
275 	if (table->header)
276 		return;
277 
278 	if (table->hdrsz)
279 		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
280 			table->name);
281 
282 	if (tableSize & (sizeof(*fde) - 1))
283 		return;
284 
285 	for (fde = table->address, n = 0;
286 	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
287 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
288 		const u32 *cie = cie_for_fde(fde, table);
289 		signed ptrType;
290 
291 		if (cie == &not_fde)
292 			continue;
293 		if (cie == NULL || cie == &bad_cie)
294 			goto ret_err;
295 		ptrType = fde_pointer_type(cie);
296 		if (ptrType < 0)
297 			goto ret_err;
298 
299 		ptr = (const u8 *)(fde + 2);
300 		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
301 								ptrType)) {
302 			/* FIXME_Rajesh We have 4 instances of null addresses
303 			 * instead of the initial loc addr
304 			 * return;
305 			 */
306 			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
307 				(const u8 *)(fde + 1) + *fde);
308 		}
309 		++n;
310 	}
311 
312 	if (tableSize || !n)
313 		goto ret_err;
314 
315 	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
316 	    + 2 * n * sizeof(unsigned long);
317 
318 	header = alloc(hdrSize);
319 	if (!header)
320 		goto ret_err;
321 
322 	header->version = 1;
323 	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
324 	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
325 	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
326 	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
327 	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
328 		     % __alignof(typeof(header->fde_count)));
329 	header->fde_count = n;
330 
331 	BUILD_BUG_ON(offsetof(typeof(*header), table)
332 		     % __alignof(typeof(*header->table)));
333 	for (fde = table->address, tableSize = table->size, n = 0;
334 	     tableSize;
335 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
336 		const u32 *cie = __cie_for_fde(fde);
337 
338 		if (fde[1] == CIE_ID)
339 			continue;	/* this is a CIE */
340 		ptr = (const u8 *)(fde + 2);
341 		header->table[n].start = read_pointer(&ptr,
342 						      (const u8 *)(fde + 1) +
343 						      *fde,
344 						      fde_pointer_type(cie));
345 		header->table[n].fde = (unsigned long)fde;
346 		++n;
347 	}
348 	WARN_ON(n != header->fde_count);
349 
350 	sort(header->table,
351 	     n,
352 	     sizeof(*header->table),
353 	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
354 
355 	table->hdrsz = hdrSize;
356 	smp_wmb();
357 	table->header = (const void *)header;
358 	return;
359 
360 ret_err:
361 	panic("Attention !!! Dwarf FDE parsing errors\n");
362 }
363 
364 #ifdef CONFIG_MODULES
365 static void *unw_hdr_alloc(unsigned long sz)
366 {
367 	return kmalloc(sz, GFP_KERNEL);
368 }
369 
370 static struct unwind_table *last_table;
371 
372 /* Must be called with module_mutex held. */
373 void *unwind_add_table(struct module *module, const void *table_start,
374 		       unsigned long table_size)
375 {
376 	struct unwind_table *table;
377 
378 	if (table_size <= 0)
379 		return NULL;
380 
381 	table = kmalloc(sizeof(*table), GFP_KERNEL);
382 	if (!table)
383 		return NULL;
384 
385 	init_unwind_table(table, module->name,
386 			  module->core_layout.base, module->core_layout.size,
387 			  module->init_layout.base, module->init_layout.size,
388 			  table_start, table_size,
389 			  NULL, 0);
390 
391 	init_unwind_hdr(table, unw_hdr_alloc);
392 
393 #ifdef UNWIND_DEBUG
394 	unw_debug("Table added for [%s] %lx %lx\n",
395 		module->name, table->core.pc, table->core.range);
396 #endif
397 	if (last_table)
398 		last_table->link = table;
399 	else
400 		root_table.link = table;
401 	last_table = table;
402 
403 	return table;
404 }
405 
406 struct unlink_table_info {
407 	struct unwind_table *table;
408 	int init_only;
409 };
410 
411 static int unlink_table(void *arg)
412 {
413 	struct unlink_table_info *info = arg;
414 	struct unwind_table *table = info->table, *prev;
415 
416 	for (prev = &root_table; prev->link && prev->link != table;
417 	     prev = prev->link)
418 		;
419 
420 	if (prev->link) {
421 		if (info->init_only) {
422 			table->init.pc = 0;
423 			table->init.range = 0;
424 			info->table = NULL;
425 		} else {
426 			prev->link = table->link;
427 			if (!prev->link)
428 				last_table = prev;
429 		}
430 	} else
431 		info->table = NULL;
432 
433 	return 0;
434 }
435 
436 /* Must be called with module_mutex held. */
437 void unwind_remove_table(void *handle, int init_only)
438 {
439 	struct unwind_table *table = handle;
440 	struct unlink_table_info info;
441 
442 	if (!table || table == &root_table)
443 		return;
444 
445 	if (init_only && table == last_table) {
446 		table->init.pc = 0;
447 		table->init.range = 0;
448 		return;
449 	}
450 
451 	info.table = table;
452 	info.init_only = init_only;
453 
454 	unlink_table(&info); /* XXX: SMP */
455 	kfree(table->header);
456 	kfree(table);
457 }
458 
459 #endif /* CONFIG_MODULES */
460 
461 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
462 {
463 	const u8 *cur = *pcur;
464 	uleb128_t value;
465 	unsigned int shift;
466 
467 	for (shift = 0, value = 0; cur < end; shift += 7) {
468 		if (shift + 7 > 8 * sizeof(value)
469 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
470 			cur = end + 1;
471 			break;
472 		}
473 		value |= (uleb128_t) (*cur & 0x7f) << shift;
474 		if (!(*cur++ & 0x80))
475 			break;
476 	}
477 	*pcur = cur;
478 
479 	return value;
480 }
481 
482 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
483 {
484 	const u8 *cur = *pcur;
485 	sleb128_t value;
486 	unsigned int shift;
487 
488 	for (shift = 0, value = 0; cur < end; shift += 7) {
489 		if (shift + 7 > 8 * sizeof(value)
490 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
491 			cur = end + 1;
492 			break;
493 		}
494 		value |= (sleb128_t) (*cur & 0x7f) << shift;
495 		if (!(*cur & 0x80)) {
496 			value |= -(*cur++ & 0x40) << shift;
497 			break;
498 		}
499 	}
500 	*pcur = cur;
501 
502 	return value;
503 }
504 
505 static const u32 *__cie_for_fde(const u32 *fde)
506 {
507 	const u32 *cie;
508 
509 	cie = fde + 1 - fde[1] / sizeof(*fde);
510 
511 	return cie;
512 }
513 
514 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
515 {
516 	const u32 *cie;
517 
518 	if (!*fde || (*fde & (sizeof(*fde) - 1)))
519 		return &bad_cie;
520 
521 	if (fde[1] == CIE_ID)
522 		return &not_fde;	/* this is a CIE */
523 
524 	if ((fde[1] & (sizeof(*fde) - 1)))
525 /* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
526 		return NULL;	/* this is not a valid FDE */
527 
528 	cie = __cie_for_fde(fde);
529 
530 	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
531 	    || (*cie & (sizeof(*cie) - 1))
532 	    || (cie[1] != CIE_ID))
533 		return NULL;	/* this is not a (valid) CIE */
534 	return cie;
535 }
536 
537 static unsigned long read_pointer(const u8 **pLoc, const void *end,
538 				  signed ptrType)
539 {
540 	unsigned long value = 0;
541 	union {
542 		const u8 *p8;
543 		const u16 *p16u;
544 		const s16 *p16s;
545 		const u32 *p32u;
546 		const s32 *p32s;
547 		const unsigned long *pul;
548 	} ptr;
549 
550 	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
551 		return 0;
552 	ptr.p8 = *pLoc;
553 	switch (ptrType & DW_EH_PE_FORM) {
554 	case DW_EH_PE_data2:
555 		if (end < (const void *)(ptr.p16u + 1))
556 			return 0;
557 		if (ptrType & DW_EH_PE_signed)
558 			value = get_unaligned((u16 *) ptr.p16s++);
559 		else
560 			value = get_unaligned((u16 *) ptr.p16u++);
561 		break;
562 	case DW_EH_PE_data4:
563 #ifdef CONFIG_64BIT
564 		if (end < (const void *)(ptr.p32u + 1))
565 			return 0;
566 		if (ptrType & DW_EH_PE_signed)
567 			value = get_unaligned(ptr.p32s++);
568 		else
569 			value = get_unaligned(ptr.p32u++);
570 		break;
571 	case DW_EH_PE_data8:
572 		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
573 #else
574 		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
575 #endif
576 		fallthrough;
577 	case DW_EH_PE_native:
578 		if (end < (const void *)(ptr.pul + 1))
579 			return 0;
580 		value = get_unaligned((unsigned long *)ptr.pul++);
581 		break;
582 	case DW_EH_PE_leb128:
583 		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
584 		value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
585 		    : get_uleb128(&ptr.p8, end);
586 		if ((const void *)ptr.p8 > end)
587 			return 0;
588 		break;
589 	default:
590 		return 0;
591 	}
592 	switch (ptrType & DW_EH_PE_ADJUST) {
593 	case DW_EH_PE_abs:
594 		break;
595 	case DW_EH_PE_pcrel:
596 		value += (unsigned long)*pLoc;
597 		break;
598 	default:
599 		return 0;
600 	}
601 	if ((ptrType & DW_EH_PE_indirect)
602 	    && __get_user(value, (unsigned long __user *)value))
603 		return 0;
604 	*pLoc = ptr.p8;
605 
606 	return value;
607 }
608 
609 static signed fde_pointer_type(const u32 *cie)
610 {
611 	const u8 *ptr = (const u8 *)(cie + 2);
612 	unsigned int version = *ptr;
613 
614 	if (*++ptr) {
615 		const char *aug;
616 		const u8 *end = (const u8 *)(cie + 1) + *cie;
617 		uleb128_t len;
618 
619 		/* check if augmentation size is first (and thus present) */
620 		if (*ptr != 'z')
621 			return -1;
622 
623 		/* check if augmentation string is nul-terminated */
624 		aug = (const void *)ptr;
625 		ptr = memchr(aug, 0, end - ptr);
626 		if (ptr == NULL)
627 			return -1;
628 
629 		++ptr;		/* skip terminator */
630 		get_uleb128(&ptr, end);	/* skip code alignment */
631 		get_sleb128(&ptr, end);	/* skip data alignment */
632 		/* skip return address column */
633 		version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
634 		len = get_uleb128(&ptr, end);	/* augmentation length */
635 
636 		if (ptr + len < ptr || ptr + len > end)
637 			return -1;
638 
639 		end = ptr + len;
640 		while (*++aug) {
641 			if (ptr >= end)
642 				return -1;
643 			switch (*aug) {
644 			case 'L':
645 				++ptr;
646 				break;
647 			case 'P':{
648 					signed ptrType = *ptr++;
649 
650 					if (!read_pointer(&ptr, end, ptrType)
651 					    || ptr > end)
652 						return -1;
653 				}
654 				break;
655 			case 'R':
656 				return *ptr;
657 			default:
658 				return -1;
659 			}
660 		}
661 	}
662 	return DW_EH_PE_native | DW_EH_PE_abs;
663 }
664 
665 static int advance_loc(unsigned long delta, struct unwind_state *state)
666 {
667 	state->loc += delta * state->codeAlign;
668 
669 	/* FIXME_Rajesh: Probably we are defining for the initial range as well;
670 	   return delta > 0;
671 	 */
672 	unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
673 	return 1;
674 }
675 
676 static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
677 		     struct unwind_state *state)
678 {
679 	if (reg < ARRAY_SIZE(state->regs)) {
680 		state->regs[reg].where = where;
681 		state->regs[reg].value = value;
682 
683 #ifdef UNWIND_DEBUG
684 		unw_debug("r%lu: ", reg);
685 		switch (where) {
686 		case Nowhere:
687 			unw_debug("s ");
688 			break;
689 		case Memory:
690 			unw_debug("c(%lu) ", value);
691 			break;
692 		case Register:
693 			unw_debug("r(%lu) ", value);
694 			break;
695 		case Value:
696 			unw_debug("v(%lu) ", value);
697 			break;
698 		default:
699 			break;
700 		}
701 #endif
702 	}
703 }
704 
705 static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
706 		      signed ptrType, struct unwind_state *state)
707 {
708 	union {
709 		const u8 *p8;
710 		const u16 *p16;
711 		const u32 *p32;
712 	} ptr;
713 	int result = 1;
714 	u8 opcode;
715 
716 	if (start != state->cieStart) {
717 		state->loc = state->org;
718 		result =
719 		    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
720 			       state);
721 		if (targetLoc == 0 && state->label == NULL)
722 			return result;
723 	}
724 	for (ptr.p8 = start; result && ptr.p8 < end;) {
725 		switch (*ptr.p8 >> 6) {
726 			uleb128_t value;
727 
728 		case 0:
729 			opcode = *ptr.p8++;
730 
731 			switch (opcode) {
732 			case DW_CFA_nop:
733 				unw_debug("cfa nop ");
734 				break;
735 			case DW_CFA_set_loc:
736 				state->loc = read_pointer(&ptr.p8, end,
737 							  ptrType);
738 				if (state->loc == 0)
739 					result = 0;
740 				unw_debug("cfa_set_loc: 0x%lx ", state->loc);
741 				break;
742 			case DW_CFA_advance_loc1:
743 				unw_debug("\ncfa advance loc1:");
744 				result = ptr.p8 < end
745 				    && advance_loc(*ptr.p8++, state);
746 				break;
747 			case DW_CFA_advance_loc2:
748 				value = *ptr.p8++;
749 				value += *ptr.p8++ << 8;
750 				unw_debug("\ncfa advance loc2:");
751 				result = ptr.p8 <= end + 2
752 				    /* && advance_loc(*ptr.p16++, state); */
753 				    && advance_loc(value, state);
754 				break;
755 			case DW_CFA_advance_loc4:
756 				unw_debug("\ncfa advance loc4:");
757 				result = ptr.p8 <= end + 4
758 				    && advance_loc(*ptr.p32++, state);
759 				break;
760 			case DW_CFA_offset_extended:
761 				value = get_uleb128(&ptr.p8, end);
762 				unw_debug("cfa_offset_extended: ");
763 				set_rule(value, Memory,
764 					 get_uleb128(&ptr.p8, end), state);
765 				break;
766 			case DW_CFA_val_offset:
767 				value = get_uleb128(&ptr.p8, end);
768 				set_rule(value, Value,
769 					 get_uleb128(&ptr.p8, end), state);
770 				break;
771 			case DW_CFA_offset_extended_sf:
772 				value = get_uleb128(&ptr.p8, end);
773 				set_rule(value, Memory,
774 					 get_sleb128(&ptr.p8, end), state);
775 				break;
776 			case DW_CFA_val_offset_sf:
777 				value = get_uleb128(&ptr.p8, end);
778 				set_rule(value, Value,
779 					 get_sleb128(&ptr.p8, end), state);
780 				break;
781 			case DW_CFA_restore_extended:
782 				unw_debug("cfa_restore_extended: ");
783 			case DW_CFA_undefined:
784 				unw_debug("cfa_undefined: ");
785 			case DW_CFA_same_value:
786 				unw_debug("cfa_same_value: ");
787 				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
788 					 state);
789 				break;
790 			case DW_CFA_register:
791 				unw_debug("cfa_register: ");
792 				value = get_uleb128(&ptr.p8, end);
793 				set_rule(value,
794 					 Register,
795 					 get_uleb128(&ptr.p8, end), state);
796 				break;
797 			case DW_CFA_remember_state:
798 				unw_debug("cfa_remember_state: ");
799 				if (ptr.p8 == state->label) {
800 					state->label = NULL;
801 					return 1;
802 				}
803 				if (state->stackDepth >= MAX_STACK_DEPTH)
804 					return 0;
805 				state->stack[state->stackDepth++] = ptr.p8;
806 				break;
807 			case DW_CFA_restore_state:
808 				unw_debug("cfa_restore_state: ");
809 				if (state->stackDepth) {
810 					const uleb128_t loc = state->loc;
811 					const u8 *label = state->label;
812 
813 					state->label =
814 					    state->stack[state->stackDepth - 1];
815 					memcpy(&state->cfa, &badCFA,
816 					       sizeof(state->cfa));
817 					memset(state->regs, 0,
818 					       sizeof(state->regs));
819 					state->stackDepth = 0;
820 					result =
821 					    processCFI(start, end, 0, ptrType,
822 						       state);
823 					state->loc = loc;
824 					state->label = label;
825 				} else
826 					return 0;
827 				break;
828 			case DW_CFA_def_cfa:
829 				state->cfa.reg = get_uleb128(&ptr.p8, end);
830 				unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
831 				fallthrough;
832 			case DW_CFA_def_cfa_offset:
833 				state->cfa.offs = get_uleb128(&ptr.p8, end);
834 				unw_debug("cfa_def_cfa_offset: 0x%lx ",
835 					  state->cfa.offs);
836 				break;
837 			case DW_CFA_def_cfa_sf:
838 				state->cfa.reg = get_uleb128(&ptr.p8, end);
839 				fallthrough;
840 			case DW_CFA_def_cfa_offset_sf:
841 				state->cfa.offs = get_sleb128(&ptr.p8, end)
842 				    * state->dataAlign;
843 				break;
844 			case DW_CFA_def_cfa_register:
845 				unw_debug("cfa_def_cfa_register: ");
846 				state->cfa.reg = get_uleb128(&ptr.p8, end);
847 				break;
848 				/*todo case DW_CFA_def_cfa_expression: */
849 				/*todo case DW_CFA_expression: */
850 				/*todo case DW_CFA_val_expression: */
851 			case DW_CFA_GNU_args_size:
852 				get_uleb128(&ptr.p8, end);
853 				break;
854 			case DW_CFA_GNU_negative_offset_extended:
855 				value = get_uleb128(&ptr.p8, end);
856 				set_rule(value,
857 					 Memory,
858 					 (uleb128_t) 0 - get_uleb128(&ptr.p8,
859 								     end),
860 					 state);
861 				break;
862 			case DW_CFA_GNU_window_save:
863 			default:
864 				unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
865 				result = 0;
866 				break;
867 			}
868 			break;
869 		case 1:
870 			unw_debug("\ncfa_adv_loc: ");
871 			result = advance_loc(*ptr.p8++ & 0x3f, state);
872 			break;
873 		case 2:
874 			unw_debug("cfa_offset: ");
875 			value = *ptr.p8++ & 0x3f;
876 			set_rule(value, Memory, get_uleb128(&ptr.p8, end),
877 				 state);
878 			break;
879 		case 3:
880 			unw_debug("cfa_restore: ");
881 			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
882 			break;
883 		}
884 
885 		if (ptr.p8 > end)
886 			result = 0;
887 		if (result && targetLoc != 0 && targetLoc < state->loc)
888 			return 1;
889 	}
890 
891 	return result && ptr.p8 == end && (targetLoc == 0 || (
892 		/*todo While in theory this should apply, gcc in practice omits
893 		  everything past the function prolog, and hence the location
894 		  never reaches the end of the function.
895 		targetLoc < state->loc && */  state->label == NULL));
896 }
897 
898 /* Unwind to previous to frame.  Returns 0 if successful, negative
899  * number in case of an error. */
900 int arc_unwind(struct unwind_frame_info *frame)
901 {
902 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
903 	const u32 *fde = NULL, *cie = NULL;
904 	const u8 *ptr = NULL, *end = NULL;
905 	unsigned long pc = UNW_PC(frame) - frame->call_frame;
906 	unsigned long startLoc = 0, endLoc = 0, cfa;
907 	unsigned int i;
908 	signed ptrType = -1;
909 	uleb128_t retAddrReg = 0;
910 	const struct unwind_table *table;
911 	struct unwind_state state;
912 	unsigned long *fptr;
913 	unsigned long addr;
914 
915 	unw_debug("\n\nUNWIND FRAME:\n");
916 	unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
917 		  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
918 		  UNW_FP(frame));
919 
920 	if (UNW_PC(frame) == 0)
921 		return -EINVAL;
922 
923 #ifdef UNWIND_DEBUG
924 	{
925 		unsigned long *sptr = (unsigned long *)UNW_SP(frame);
926 		unw_debug("\nStack Dump:\n");
927 		for (i = 0; i < 20; i++, sptr++)
928 			unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
929 		unw_debug("\n");
930 	}
931 #endif
932 
933 	table = find_table(pc);
934 	if (table != NULL
935 	    && !(table->size & (sizeof(*fde) - 1))) {
936 		const u8 *hdr = table->header;
937 		unsigned long tableSize;
938 
939 		smp_rmb();
940 		if (hdr && hdr[0] == 1) {
941 			switch (hdr[3] & DW_EH_PE_FORM) {
942 			case DW_EH_PE_native:
943 				tableSize = sizeof(unsigned long);
944 				break;
945 			case DW_EH_PE_data2:
946 				tableSize = 2;
947 				break;
948 			case DW_EH_PE_data4:
949 				tableSize = 4;
950 				break;
951 			case DW_EH_PE_data8:
952 				tableSize = 8;
953 				break;
954 			default:
955 				tableSize = 0;
956 				break;
957 			}
958 			ptr = hdr + 4;
959 			end = hdr + table->hdrsz;
960 			if (tableSize && read_pointer(&ptr, end, hdr[1])
961 			    == (unsigned long)table->address
962 			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
963 			    && i == (end - ptr) / (2 * tableSize)
964 			    && !((end - ptr) % (2 * tableSize))) {
965 				do {
966 					const u8 *cur =
967 					    ptr + (i / 2) * (2 * tableSize);
968 
969 					startLoc = read_pointer(&cur,
970 								cur + tableSize,
971 								hdr[3]);
972 					if (pc < startLoc)
973 						i /= 2;
974 					else {
975 						ptr = cur - tableSize;
976 						i = (i + 1) / 2;
977 					}
978 				} while (startLoc && i > 1);
979 				if (i == 1
980 				    && (startLoc = read_pointer(&ptr,
981 								ptr + tableSize,
982 								hdr[3])) != 0
983 				    && pc >= startLoc)
984 					fde = (void *)read_pointer(&ptr,
985 								   ptr +
986 								   tableSize,
987 								   hdr[3]);
988 			}
989 		}
990 
991 		if (fde != NULL) {
992 			cie = cie_for_fde(fde, table);
993 			ptr = (const u8 *)(fde + 2);
994 			if (cie != NULL
995 			    && cie != &bad_cie
996 			    && cie != &not_fde
997 			    && (ptrType = fde_pointer_type(cie)) >= 0
998 			    && read_pointer(&ptr,
999 					    (const u8 *)(fde + 1) + *fde,
1000 					    ptrType) == startLoc) {
1001 				if (!(ptrType & DW_EH_PE_indirect))
1002 					ptrType &=
1003 					    DW_EH_PE_FORM | DW_EH_PE_signed;
1004 				endLoc =
1005 				    startLoc + read_pointer(&ptr,
1006 							    (const u8 *)(fde +
1007 									 1) +
1008 							    *fde, ptrType);
1009 				if (pc >= endLoc) {
1010 					fde = NULL;
1011 					cie = NULL;
1012 				}
1013 			} else {
1014 				fde = NULL;
1015 				cie = NULL;
1016 			}
1017 		}
1018 	}
1019 	if (cie != NULL) {
1020 		memset(&state, 0, sizeof(state));
1021 		state.cieEnd = ptr;	/* keep here temporarily */
1022 		ptr = (const u8 *)(cie + 2);
1023 		end = (const u8 *)(cie + 1) + *cie;
1024 		frame->call_frame = 1;
1025 		if (*++ptr) {
1026 			/* check if augmentation size is first (thus present) */
1027 			if (*ptr == 'z') {
1028 				while (++ptr < end && *ptr) {
1029 					switch (*ptr) {
1030 					/* chk for ignorable or already handled
1031 					 * nul-terminated augmentation string */
1032 					case 'L':
1033 					case 'P':
1034 					case 'R':
1035 						continue;
1036 					case 'S':
1037 						frame->call_frame = 0;
1038 						continue;
1039 					default:
1040 						break;
1041 					}
1042 					break;
1043 				}
1044 			}
1045 			if (ptr >= end || *ptr)
1046 				cie = NULL;
1047 		}
1048 		++ptr;
1049 	}
1050 	if (cie != NULL) {
1051 		/* get code alignment factor */
1052 		state.codeAlign = get_uleb128(&ptr, end);
1053 		/* get data alignment factor */
1054 		state.dataAlign = get_sleb128(&ptr, end);
1055 		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1056 			cie = NULL;
1057 		else {
1058 			retAddrReg =
1059 			    state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1060 								      end);
1061 			unw_debug("CIE Frame Info:\n");
1062 			unw_debug("return Address register 0x%lx\n",
1063 				  retAddrReg);
1064 			unw_debug("data Align: %ld\n", state.dataAlign);
1065 			unw_debug("code Align: %lu\n", state.codeAlign);
1066 			/* skip augmentation */
1067 			if (((const char *)(cie + 2))[1] == 'z') {
1068 				uleb128_t augSize = get_uleb128(&ptr, end);
1069 
1070 				ptr += augSize;
1071 			}
1072 			if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1073 			    || REG_INVALID(retAddrReg)
1074 			    || reg_info[retAddrReg].width !=
1075 			    sizeof(unsigned long))
1076 				cie = NULL;
1077 		}
1078 	}
1079 	if (cie != NULL) {
1080 		state.cieStart = ptr;
1081 		ptr = state.cieEnd;
1082 		state.cieEnd = end;
1083 		end = (const u8 *)(fde + 1) + *fde;
1084 		/* skip augmentation */
1085 		if (((const char *)(cie + 2))[1] == 'z') {
1086 			uleb128_t augSize = get_uleb128(&ptr, end);
1087 
1088 			if ((ptr += augSize) > end)
1089 				fde = NULL;
1090 		}
1091 	}
1092 	if (cie == NULL || fde == NULL) {
1093 #ifdef CONFIG_FRAME_POINTER
1094 		unsigned long top, bottom;
1095 
1096 		top = STACK_TOP_UNW(frame->task);
1097 		bottom = STACK_BOTTOM_UNW(frame->task);
1098 #if FRAME_RETADDR_OFFSET < 0
1099 		if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1100 		    && bottom < UNW_FP(frame)
1101 #else
1102 		if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1103 		    && bottom > UNW_FP(frame)
1104 #endif
1105 		    && !((UNW_SP(frame) | UNW_FP(frame))
1106 			 & (sizeof(unsigned long) - 1))) {
1107 			unsigned long link;
1108 
1109 			if (!__get_user(link, (unsigned long *)
1110 					(UNW_FP(frame) + FRAME_LINK_OFFSET))
1111 #if FRAME_RETADDR_OFFSET < 0
1112 			    && link > bottom && link < UNW_FP(frame)
1113 #else
1114 			    && link > UNW_FP(frame) && link < bottom
1115 #endif
1116 			    && !(link & (sizeof(link) - 1))
1117 			    && !__get_user(UNW_PC(frame),
1118 					   (unsigned long *)(UNW_FP(frame)
1119 						+ FRAME_RETADDR_OFFSET)))
1120 			{
1121 				UNW_SP(frame) =
1122 				    UNW_FP(frame) + FRAME_RETADDR_OFFSET
1123 #if FRAME_RETADDR_OFFSET < 0
1124 				    -
1125 #else
1126 				    +
1127 #endif
1128 				    sizeof(UNW_PC(frame));
1129 				UNW_FP(frame) = link;
1130 				return 0;
1131 			}
1132 		}
1133 #endif
1134 		return -ENXIO;
1135 	}
1136 	state.org = startLoc;
1137 	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1138 
1139 	unw_debug("\nProcess instructions\n");
1140 
1141 	/* process instructions
1142 	 * For ARC, we optimize by having blink(retAddrReg) with
1143 	 * the sameValue in the leaf function, so we should not check
1144 	 * state.regs[retAddrReg].where == Nowhere
1145 	 */
1146 	if (!processCFI(ptr, end, pc, ptrType, &state)
1147 	    || state.loc > endLoc
1148 /*	   || state.regs[retAddrReg].where == Nowhere */
1149 	    || state.cfa.reg >= ARRAY_SIZE(reg_info)
1150 	    || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1151 	    || state.cfa.offs % sizeof(unsigned long))
1152 		return -EIO;
1153 
1154 #ifdef UNWIND_DEBUG
1155 	unw_debug("\n");
1156 
1157 	unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1158 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1159 
1160 		if (REG_INVALID(i))
1161 			continue;
1162 
1163 		switch (state.regs[i].where) {
1164 		case Nowhere:
1165 			break;
1166 		case Memory:
1167 			unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1168 			break;
1169 		case Register:
1170 			unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1171 			break;
1172 		case Value:
1173 			unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1174 			break;
1175 		}
1176 	}
1177 
1178 	unw_debug("\n");
1179 #endif
1180 
1181 	/* update frame */
1182 	if (frame->call_frame
1183 	    && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1184 		frame->call_frame = 0;
1185 	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1186 	startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1187 	endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1188 	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1189 		startLoc = min(STACK_LIMIT(cfa), cfa);
1190 		endLoc = max(STACK_LIMIT(cfa), cfa);
1191 	}
1192 
1193 	unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
1194 		  state.cfa.reg, state.cfa.offs, cfa);
1195 
1196 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1197 		if (REG_INVALID(i)) {
1198 			if (state.regs[i].where == Nowhere)
1199 				continue;
1200 			return -EIO;
1201 		}
1202 		switch (state.regs[i].where) {
1203 		default:
1204 			break;
1205 		case Register:
1206 			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1207 			    || REG_INVALID(state.regs[i].value)
1208 			    || reg_info[i].width >
1209 			    reg_info[state.regs[i].value].width)
1210 				return -EIO;
1211 			switch (reg_info[state.regs[i].value].width) {
1212 			case sizeof(u8):
1213 				state.regs[i].value =
1214 				FRAME_REG(state.regs[i].value, const u8);
1215 				break;
1216 			case sizeof(u16):
1217 				state.regs[i].value =
1218 				FRAME_REG(state.regs[i].value, const u16);
1219 				break;
1220 			case sizeof(u32):
1221 				state.regs[i].value =
1222 				FRAME_REG(state.regs[i].value, const u32);
1223 				break;
1224 #ifdef CONFIG_64BIT
1225 			case sizeof(u64):
1226 				state.regs[i].value =
1227 				FRAME_REG(state.regs[i].value, const u64);
1228 				break;
1229 #endif
1230 			default:
1231 				return -EIO;
1232 			}
1233 			break;
1234 		}
1235 	}
1236 
1237 	unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1238 	fptr = (unsigned long *)(&frame->regs);
1239 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1240 
1241 		if (REG_INVALID(i))
1242 			continue;
1243 		switch (state.regs[i].where) {
1244 		case Nowhere:
1245 			if (reg_info[i].width != sizeof(UNW_SP(frame))
1246 			    || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1247 			    != &UNW_SP(frame))
1248 				continue;
1249 			UNW_SP(frame) = cfa;
1250 			break;
1251 		case Register:
1252 			switch (reg_info[i].width) {
1253 			case sizeof(u8):
1254 				FRAME_REG(i, u8) = state.regs[i].value;
1255 				break;
1256 			case sizeof(u16):
1257 				FRAME_REG(i, u16) = state.regs[i].value;
1258 				break;
1259 			case sizeof(u32):
1260 				FRAME_REG(i, u32) = state.regs[i].value;
1261 				break;
1262 #ifdef CONFIG_64BIT
1263 			case sizeof(u64):
1264 				FRAME_REG(i, u64) = state.regs[i].value;
1265 				break;
1266 #endif
1267 			default:
1268 				return -EIO;
1269 			}
1270 			break;
1271 		case Value:
1272 			if (reg_info[i].width != sizeof(unsigned long))
1273 				return -EIO;
1274 			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1275 			    * state.dataAlign;
1276 			break;
1277 		case Memory:
1278 			addr = cfa + state.regs[i].value * state.dataAlign;
1279 
1280 			if ((state.regs[i].value * state.dataAlign)
1281 			    % sizeof(unsigned long)
1282 			    || addr < startLoc
1283 			    || addr + sizeof(unsigned long) < addr
1284 			    || addr + sizeof(unsigned long) > endLoc)
1285 					return -EIO;
1286 
1287 			switch (reg_info[i].width) {
1288 			case sizeof(u8):
1289 				__get_user(FRAME_REG(i, u8),
1290 					   (u8 __user *)addr);
1291 				break;
1292 			case sizeof(u16):
1293 				__get_user(FRAME_REG(i, u16),
1294 					   (u16 __user *)addr);
1295 				break;
1296 			case sizeof(u32):
1297 				__get_user(FRAME_REG(i, u32),
1298 					   (u32 __user *)addr);
1299 				break;
1300 #ifdef CONFIG_64BIT
1301 			case sizeof(u64):
1302 				__get_user(FRAME_REG(i, u64),
1303 					   (u64 __user *)addr);
1304 				break;
1305 #endif
1306 			default:
1307 				return -EIO;
1308 			}
1309 
1310 			break;
1311 		}
1312 		unw_debug("r%d: 0x%lx ", i, *fptr);
1313 	}
1314 
1315 	return 0;
1316 #undef FRAME_REG
1317 }
1318 EXPORT_SYMBOL(arc_unwind);
1319