xref: /openbmc/linux/arch/arc/kernel/unwind.c (revision 173940b3)
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 
249 	swap(e1->start, e2->start);
250 	swap(e1->fde, e2->fde);
251 }
252 
253 static void init_unwind_hdr(struct unwind_table *table,
254 			    void *(*alloc) (unsigned long))
255 {
256 	const u8 *ptr;
257 	unsigned long tableSize = table->size, hdrSize;
258 	unsigned int n;
259 	const u32 *fde;
260 	struct {
261 		u8 version;
262 		u8 eh_frame_ptr_enc;
263 		u8 fde_count_enc;
264 		u8 table_enc;
265 		unsigned long eh_frame_ptr;
266 		unsigned int fde_count;
267 		struct eh_frame_hdr_table_entry table[];
268 	} __attribute__ ((__packed__)) *header;
269 
270 	if (table->header)
271 		return;
272 
273 	if (table->hdrsz)
274 		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
275 			table->name);
276 
277 	if (tableSize & (sizeof(*fde) - 1))
278 		return;
279 
280 	for (fde = table->address, n = 0;
281 	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
282 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
283 		const u32 *cie = cie_for_fde(fde, table);
284 		signed ptrType;
285 
286 		if (cie == &not_fde)
287 			continue;
288 		if (cie == NULL || cie == &bad_cie)
289 			goto ret_err;
290 		ptrType = fde_pointer_type(cie);
291 		if (ptrType < 0)
292 			goto ret_err;
293 
294 		ptr = (const u8 *)(fde + 2);
295 		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
296 								ptrType)) {
297 			/* FIXME_Rajesh We have 4 instances of null addresses
298 			 * instead of the initial loc addr
299 			 * return;
300 			 */
301 			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
302 				(const u8 *)(fde + 1) + *fde);
303 		}
304 		++n;
305 	}
306 
307 	if (tableSize || !n)
308 		goto ret_err;
309 
310 	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
311 	    + 2 * n * sizeof(unsigned long);
312 
313 	header = alloc(hdrSize);
314 	if (!header)
315 		goto ret_err;
316 
317 	header->version = 1;
318 	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
319 	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
320 	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
321 	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
322 	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
323 		     % __alignof(typeof(header->fde_count)));
324 	header->fde_count = n;
325 
326 	BUILD_BUG_ON(offsetof(typeof(*header), table)
327 		     % __alignof(typeof(*header->table)));
328 	for (fde = table->address, tableSize = table->size, n = 0;
329 	     tableSize;
330 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
331 		const u32 *cie = __cie_for_fde(fde);
332 
333 		if (fde[1] == CIE_ID)
334 			continue;	/* this is a CIE */
335 		ptr = (const u8 *)(fde + 2);
336 		header->table[n].start = read_pointer(&ptr,
337 						      (const u8 *)(fde + 1) +
338 						      *fde,
339 						      fde_pointer_type(cie));
340 		header->table[n].fde = (unsigned long)fde;
341 		++n;
342 	}
343 	WARN_ON(n != header->fde_count);
344 
345 	sort(header->table,
346 	     n,
347 	     sizeof(*header->table),
348 	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
349 
350 	table->hdrsz = hdrSize;
351 	smp_wmb();
352 	table->header = (const void *)header;
353 	return;
354 
355 ret_err:
356 	panic("Attention !!! Dwarf FDE parsing errors\n");
357 }
358 
359 #ifdef CONFIG_MODULES
360 static void *unw_hdr_alloc(unsigned long sz)
361 {
362 	return kmalloc(sz, GFP_KERNEL);
363 }
364 
365 static struct unwind_table *last_table;
366 
367 /* Must be called with module_mutex held. */
368 void *unwind_add_table(struct module *module, const void *table_start,
369 		       unsigned long table_size)
370 {
371 	struct unwind_table *table;
372 
373 	if (table_size <= 0)
374 		return NULL;
375 
376 	table = kmalloc(sizeof(*table), GFP_KERNEL);
377 	if (!table)
378 		return NULL;
379 
380 	init_unwind_table(table, module->name,
381 			  module->core_layout.base, module->core_layout.size,
382 			  module->init_layout.base, module->init_layout.size,
383 			  table_start, table_size,
384 			  NULL, 0);
385 
386 	init_unwind_hdr(table, unw_hdr_alloc);
387 
388 #ifdef UNWIND_DEBUG
389 	unw_debug("Table added for [%s] %lx %lx\n",
390 		module->name, table->core.pc, table->core.range);
391 #endif
392 	if (last_table)
393 		last_table->link = table;
394 	else
395 		root_table.link = table;
396 	last_table = table;
397 
398 	return table;
399 }
400 
401 struct unlink_table_info {
402 	struct unwind_table *table;
403 	int init_only;
404 };
405 
406 static int unlink_table(void *arg)
407 {
408 	struct unlink_table_info *info = arg;
409 	struct unwind_table *table = info->table, *prev;
410 
411 	for (prev = &root_table; prev->link && prev->link != table;
412 	     prev = prev->link)
413 		;
414 
415 	if (prev->link) {
416 		if (info->init_only) {
417 			table->init.pc = 0;
418 			table->init.range = 0;
419 			info->table = NULL;
420 		} else {
421 			prev->link = table->link;
422 			if (!prev->link)
423 				last_table = prev;
424 		}
425 	} else
426 		info->table = NULL;
427 
428 	return 0;
429 }
430 
431 /* Must be called with module_mutex held. */
432 void unwind_remove_table(void *handle, int init_only)
433 {
434 	struct unwind_table *table = handle;
435 	struct unlink_table_info info;
436 
437 	if (!table || table == &root_table)
438 		return;
439 
440 	if (init_only && table == last_table) {
441 		table->init.pc = 0;
442 		table->init.range = 0;
443 		return;
444 	}
445 
446 	info.table = table;
447 	info.init_only = init_only;
448 
449 	unlink_table(&info); /* XXX: SMP */
450 	kfree(table->header);
451 	kfree(table);
452 }
453 
454 #endif /* CONFIG_MODULES */
455 
456 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
457 {
458 	const u8 *cur = *pcur;
459 	uleb128_t value;
460 	unsigned int shift;
461 
462 	for (shift = 0, value = 0; cur < end; shift += 7) {
463 		if (shift + 7 > 8 * sizeof(value)
464 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
465 			cur = end + 1;
466 			break;
467 		}
468 		value |= (uleb128_t) (*cur & 0x7f) << shift;
469 		if (!(*cur++ & 0x80))
470 			break;
471 	}
472 	*pcur = cur;
473 
474 	return value;
475 }
476 
477 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
478 {
479 	const u8 *cur = *pcur;
480 	sleb128_t value;
481 	unsigned int shift;
482 
483 	for (shift = 0, value = 0; cur < end; shift += 7) {
484 		if (shift + 7 > 8 * sizeof(value)
485 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
486 			cur = end + 1;
487 			break;
488 		}
489 		value |= (sleb128_t) (*cur & 0x7f) << shift;
490 		if (!(*cur & 0x80)) {
491 			value |= -(*cur++ & 0x40) << shift;
492 			break;
493 		}
494 	}
495 	*pcur = cur;
496 
497 	return value;
498 }
499 
500 static const u32 *__cie_for_fde(const u32 *fde)
501 {
502 	const u32 *cie;
503 
504 	cie = fde + 1 - fde[1] / sizeof(*fde);
505 
506 	return cie;
507 }
508 
509 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
510 {
511 	const u32 *cie;
512 
513 	if (!*fde || (*fde & (sizeof(*fde) - 1)))
514 		return &bad_cie;
515 
516 	if (fde[1] == CIE_ID)
517 		return &not_fde;	/* this is a CIE */
518 
519 	if ((fde[1] & (sizeof(*fde) - 1)))
520 /* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
521 		return NULL;	/* this is not a valid FDE */
522 
523 	cie = __cie_for_fde(fde);
524 
525 	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
526 	    || (*cie & (sizeof(*cie) - 1))
527 	    || (cie[1] != CIE_ID))
528 		return NULL;	/* this is not a (valid) CIE */
529 	return cie;
530 }
531 
532 static unsigned long read_pointer(const u8 **pLoc, const void *end,
533 				  signed ptrType)
534 {
535 	unsigned long value = 0;
536 	union {
537 		const u8 *p8;
538 		const u16 *p16u;
539 		const s16 *p16s;
540 		const u32 *p32u;
541 		const s32 *p32s;
542 		const unsigned long *pul;
543 	} ptr;
544 
545 	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
546 		return 0;
547 	ptr.p8 = *pLoc;
548 	switch (ptrType & DW_EH_PE_FORM) {
549 	case DW_EH_PE_data2:
550 		if (end < (const void *)(ptr.p16u + 1))
551 			return 0;
552 		if (ptrType & DW_EH_PE_signed)
553 			value = get_unaligned((u16 *) ptr.p16s++);
554 		else
555 			value = get_unaligned((u16 *) ptr.p16u++);
556 		break;
557 	case DW_EH_PE_data4:
558 #ifdef CONFIG_64BIT
559 		if (end < (const void *)(ptr.p32u + 1))
560 			return 0;
561 		if (ptrType & DW_EH_PE_signed)
562 			value = get_unaligned(ptr.p32s++);
563 		else
564 			value = get_unaligned(ptr.p32u++);
565 		break;
566 	case DW_EH_PE_data8:
567 		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
568 #else
569 		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
570 #endif
571 		fallthrough;
572 	case DW_EH_PE_native:
573 		if (end < (const void *)(ptr.pul + 1))
574 			return 0;
575 		value = get_unaligned((unsigned long *)ptr.pul++);
576 		break;
577 	case DW_EH_PE_leb128:
578 		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
579 		value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
580 		    : get_uleb128(&ptr.p8, end);
581 		if ((const void *)ptr.p8 > end)
582 			return 0;
583 		break;
584 	default:
585 		return 0;
586 	}
587 	switch (ptrType & DW_EH_PE_ADJUST) {
588 	case DW_EH_PE_abs:
589 		break;
590 	case DW_EH_PE_pcrel:
591 		value += (unsigned long)*pLoc;
592 		break;
593 	default:
594 		return 0;
595 	}
596 	if ((ptrType & DW_EH_PE_indirect)
597 	    && __get_user(value, (unsigned long __user *)value))
598 		return 0;
599 	*pLoc = ptr.p8;
600 
601 	return value;
602 }
603 
604 static signed fde_pointer_type(const u32 *cie)
605 {
606 	const u8 *ptr = (const u8 *)(cie + 2);
607 	unsigned int version = *ptr;
608 
609 	if (*++ptr) {
610 		const char *aug;
611 		const u8 *end = (const u8 *)(cie + 1) + *cie;
612 		uleb128_t len;
613 
614 		/* check if augmentation size is first (and thus present) */
615 		if (*ptr != 'z')
616 			return -1;
617 
618 		/* check if augmentation string is nul-terminated */
619 		aug = (const void *)ptr;
620 		ptr = memchr(aug, 0, end - ptr);
621 		if (ptr == NULL)
622 			return -1;
623 
624 		++ptr;		/* skip terminator */
625 		get_uleb128(&ptr, end);	/* skip code alignment */
626 		get_sleb128(&ptr, end);	/* skip data alignment */
627 		/* skip return address column */
628 		version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
629 		len = get_uleb128(&ptr, end);	/* augmentation length */
630 
631 		if (ptr + len < ptr || ptr + len > end)
632 			return -1;
633 
634 		end = ptr + len;
635 		while (*++aug) {
636 			if (ptr >= end)
637 				return -1;
638 			switch (*aug) {
639 			case 'L':
640 				++ptr;
641 				break;
642 			case 'P':{
643 					signed ptrType = *ptr++;
644 
645 					if (!read_pointer(&ptr, end, ptrType)
646 					    || ptr > end)
647 						return -1;
648 				}
649 				break;
650 			case 'R':
651 				return *ptr;
652 			default:
653 				return -1;
654 			}
655 		}
656 	}
657 	return DW_EH_PE_native | DW_EH_PE_abs;
658 }
659 
660 static int advance_loc(unsigned long delta, struct unwind_state *state)
661 {
662 	state->loc += delta * state->codeAlign;
663 
664 	/* FIXME_Rajesh: Probably we are defining for the initial range as well;
665 	   return delta > 0;
666 	 */
667 	unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
668 	return 1;
669 }
670 
671 static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
672 		     struct unwind_state *state)
673 {
674 	if (reg < ARRAY_SIZE(state->regs)) {
675 		state->regs[reg].where = where;
676 		state->regs[reg].value = value;
677 
678 #ifdef UNWIND_DEBUG
679 		unw_debug("r%lu: ", reg);
680 		switch (where) {
681 		case Nowhere:
682 			unw_debug("s ");
683 			break;
684 		case Memory:
685 			unw_debug("c(%lu) ", value);
686 			break;
687 		case Register:
688 			unw_debug("r(%lu) ", value);
689 			break;
690 		case Value:
691 			unw_debug("v(%lu) ", value);
692 			break;
693 		default:
694 			break;
695 		}
696 #endif
697 	}
698 }
699 
700 static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
701 		      signed ptrType, struct unwind_state *state)
702 {
703 	union {
704 		const u8 *p8;
705 		const u16 *p16;
706 		const u32 *p32;
707 	} ptr;
708 	int result = 1;
709 	u8 opcode;
710 
711 	if (start != state->cieStart) {
712 		state->loc = state->org;
713 		result =
714 		    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
715 			       state);
716 		if (targetLoc == 0 && state->label == NULL)
717 			return result;
718 	}
719 	for (ptr.p8 = start; result && ptr.p8 < end;) {
720 		switch (*ptr.p8 >> 6) {
721 			uleb128_t value;
722 
723 		case 0:
724 			opcode = *ptr.p8++;
725 
726 			switch (opcode) {
727 			case DW_CFA_nop:
728 				unw_debug("cfa nop ");
729 				break;
730 			case DW_CFA_set_loc:
731 				state->loc = read_pointer(&ptr.p8, end,
732 							  ptrType);
733 				if (state->loc == 0)
734 					result = 0;
735 				unw_debug("cfa_set_loc: 0x%lx ", state->loc);
736 				break;
737 			case DW_CFA_advance_loc1:
738 				unw_debug("\ncfa advance loc1:");
739 				result = ptr.p8 < end
740 				    && advance_loc(*ptr.p8++, state);
741 				break;
742 			case DW_CFA_advance_loc2:
743 				value = *ptr.p8++;
744 				value += *ptr.p8++ << 8;
745 				unw_debug("\ncfa advance loc2:");
746 				result = ptr.p8 <= end + 2
747 				    /* && advance_loc(*ptr.p16++, state); */
748 				    && advance_loc(value, state);
749 				break;
750 			case DW_CFA_advance_loc4:
751 				unw_debug("\ncfa advance loc4:");
752 				result = ptr.p8 <= end + 4
753 				    && advance_loc(*ptr.p32++, state);
754 				break;
755 			case DW_CFA_offset_extended:
756 				value = get_uleb128(&ptr.p8, end);
757 				unw_debug("cfa_offset_extended: ");
758 				set_rule(value, Memory,
759 					 get_uleb128(&ptr.p8, end), state);
760 				break;
761 			case DW_CFA_val_offset:
762 				value = get_uleb128(&ptr.p8, end);
763 				set_rule(value, Value,
764 					 get_uleb128(&ptr.p8, end), state);
765 				break;
766 			case DW_CFA_offset_extended_sf:
767 				value = get_uleb128(&ptr.p8, end);
768 				set_rule(value, Memory,
769 					 get_sleb128(&ptr.p8, end), state);
770 				break;
771 			case DW_CFA_val_offset_sf:
772 				value = get_uleb128(&ptr.p8, end);
773 				set_rule(value, Value,
774 					 get_sleb128(&ptr.p8, end), state);
775 				break;
776 			case DW_CFA_restore_extended:
777 				unw_debug("cfa_restore_extended: ");
778 			case DW_CFA_undefined:
779 				unw_debug("cfa_undefined: ");
780 			case DW_CFA_same_value:
781 				unw_debug("cfa_same_value: ");
782 				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
783 					 state);
784 				break;
785 			case DW_CFA_register:
786 				unw_debug("cfa_register: ");
787 				value = get_uleb128(&ptr.p8, end);
788 				set_rule(value,
789 					 Register,
790 					 get_uleb128(&ptr.p8, end), state);
791 				break;
792 			case DW_CFA_remember_state:
793 				unw_debug("cfa_remember_state: ");
794 				if (ptr.p8 == state->label) {
795 					state->label = NULL;
796 					return 1;
797 				}
798 				if (state->stackDepth >= MAX_STACK_DEPTH)
799 					return 0;
800 				state->stack[state->stackDepth++] = ptr.p8;
801 				break;
802 			case DW_CFA_restore_state:
803 				unw_debug("cfa_restore_state: ");
804 				if (state->stackDepth) {
805 					const uleb128_t loc = state->loc;
806 					const u8 *label = state->label;
807 
808 					state->label =
809 					    state->stack[state->stackDepth - 1];
810 					memcpy(&state->cfa, &badCFA,
811 					       sizeof(state->cfa));
812 					memset(state->regs, 0,
813 					       sizeof(state->regs));
814 					state->stackDepth = 0;
815 					result =
816 					    processCFI(start, end, 0, ptrType,
817 						       state);
818 					state->loc = loc;
819 					state->label = label;
820 				} else
821 					return 0;
822 				break;
823 			case DW_CFA_def_cfa:
824 				state->cfa.reg = get_uleb128(&ptr.p8, end);
825 				unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
826 				fallthrough;
827 			case DW_CFA_def_cfa_offset:
828 				state->cfa.offs = get_uleb128(&ptr.p8, end);
829 				unw_debug("cfa_def_cfa_offset: 0x%lx ",
830 					  state->cfa.offs);
831 				break;
832 			case DW_CFA_def_cfa_sf:
833 				state->cfa.reg = get_uleb128(&ptr.p8, end);
834 				fallthrough;
835 			case DW_CFA_def_cfa_offset_sf:
836 				state->cfa.offs = get_sleb128(&ptr.p8, end)
837 				    * state->dataAlign;
838 				break;
839 			case DW_CFA_def_cfa_register:
840 				unw_debug("cfa_def_cfa_register: ");
841 				state->cfa.reg = get_uleb128(&ptr.p8, end);
842 				break;
843 				/*todo case DW_CFA_def_cfa_expression: */
844 				/*todo case DW_CFA_expression: */
845 				/*todo case DW_CFA_val_expression: */
846 			case DW_CFA_GNU_args_size:
847 				get_uleb128(&ptr.p8, end);
848 				break;
849 			case DW_CFA_GNU_negative_offset_extended:
850 				value = get_uleb128(&ptr.p8, end);
851 				set_rule(value,
852 					 Memory,
853 					 (uleb128_t) 0 - get_uleb128(&ptr.p8,
854 								     end),
855 					 state);
856 				break;
857 			case DW_CFA_GNU_window_save:
858 			default:
859 				unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
860 				result = 0;
861 				break;
862 			}
863 			break;
864 		case 1:
865 			unw_debug("\ncfa_adv_loc: ");
866 			result = advance_loc(*ptr.p8++ & 0x3f, state);
867 			break;
868 		case 2:
869 			unw_debug("cfa_offset: ");
870 			value = *ptr.p8++ & 0x3f;
871 			set_rule(value, Memory, get_uleb128(&ptr.p8, end),
872 				 state);
873 			break;
874 		case 3:
875 			unw_debug("cfa_restore: ");
876 			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
877 			break;
878 		}
879 
880 		if (ptr.p8 > end)
881 			result = 0;
882 		if (result && targetLoc != 0 && targetLoc < state->loc)
883 			return 1;
884 	}
885 
886 	return result && ptr.p8 == end && (targetLoc == 0 || (
887 		/*todo While in theory this should apply, gcc in practice omits
888 		  everything past the function prolog, and hence the location
889 		  never reaches the end of the function.
890 		targetLoc < state->loc && */  state->label == NULL));
891 }
892 
893 /* Unwind to previous to frame.  Returns 0 if successful, negative
894  * number in case of an error. */
895 int arc_unwind(struct unwind_frame_info *frame)
896 {
897 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
898 	const u32 *fde = NULL, *cie = NULL;
899 	const u8 *ptr = NULL, *end = NULL;
900 	unsigned long pc = UNW_PC(frame) - frame->call_frame;
901 	unsigned long startLoc = 0, endLoc = 0, cfa;
902 	unsigned int i;
903 	signed ptrType = -1;
904 	uleb128_t retAddrReg = 0;
905 	const struct unwind_table *table;
906 	struct unwind_state state;
907 	unsigned long *fptr;
908 	unsigned long addr;
909 
910 	unw_debug("\n\nUNWIND FRAME:\n");
911 	unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
912 		  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
913 		  UNW_FP(frame));
914 
915 	if (UNW_PC(frame) == 0)
916 		return -EINVAL;
917 
918 #ifdef UNWIND_DEBUG
919 	{
920 		unsigned long *sptr = (unsigned long *)UNW_SP(frame);
921 		unw_debug("\nStack Dump:\n");
922 		for (i = 0; i < 20; i++, sptr++)
923 			unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
924 		unw_debug("\n");
925 	}
926 #endif
927 
928 	table = find_table(pc);
929 	if (table != NULL
930 	    && !(table->size & (sizeof(*fde) - 1))) {
931 		const u8 *hdr = table->header;
932 		unsigned long tableSize;
933 
934 		smp_rmb();
935 		if (hdr && hdr[0] == 1) {
936 			switch (hdr[3] & DW_EH_PE_FORM) {
937 			case DW_EH_PE_native:
938 				tableSize = sizeof(unsigned long);
939 				break;
940 			case DW_EH_PE_data2:
941 				tableSize = 2;
942 				break;
943 			case DW_EH_PE_data4:
944 				tableSize = 4;
945 				break;
946 			case DW_EH_PE_data8:
947 				tableSize = 8;
948 				break;
949 			default:
950 				tableSize = 0;
951 				break;
952 			}
953 			ptr = hdr + 4;
954 			end = hdr + table->hdrsz;
955 			if (tableSize && read_pointer(&ptr, end, hdr[1])
956 			    == (unsigned long)table->address
957 			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
958 			    && i == (end - ptr) / (2 * tableSize)
959 			    && !((end - ptr) % (2 * tableSize))) {
960 				do {
961 					const u8 *cur =
962 					    ptr + (i / 2) * (2 * tableSize);
963 
964 					startLoc = read_pointer(&cur,
965 								cur + tableSize,
966 								hdr[3]);
967 					if (pc < startLoc)
968 						i /= 2;
969 					else {
970 						ptr = cur - tableSize;
971 						i = (i + 1) / 2;
972 					}
973 				} while (startLoc && i > 1);
974 				if (i == 1
975 				    && (startLoc = read_pointer(&ptr,
976 								ptr + tableSize,
977 								hdr[3])) != 0
978 				    && pc >= startLoc)
979 					fde = (void *)read_pointer(&ptr,
980 								   ptr +
981 								   tableSize,
982 								   hdr[3]);
983 			}
984 		}
985 
986 		if (fde != NULL) {
987 			cie = cie_for_fde(fde, table);
988 			ptr = (const u8 *)(fde + 2);
989 			if (cie != NULL
990 			    && cie != &bad_cie
991 			    && cie != &not_fde
992 			    && (ptrType = fde_pointer_type(cie)) >= 0
993 			    && read_pointer(&ptr,
994 					    (const u8 *)(fde + 1) + *fde,
995 					    ptrType) == startLoc) {
996 				if (!(ptrType & DW_EH_PE_indirect))
997 					ptrType &=
998 					    DW_EH_PE_FORM | DW_EH_PE_signed;
999 				endLoc =
1000 				    startLoc + read_pointer(&ptr,
1001 							    (const u8 *)(fde +
1002 									 1) +
1003 							    *fde, ptrType);
1004 				if (pc >= endLoc) {
1005 					fde = NULL;
1006 					cie = NULL;
1007 				}
1008 			} else {
1009 				fde = NULL;
1010 				cie = NULL;
1011 			}
1012 		}
1013 	}
1014 	if (cie != NULL) {
1015 		memset(&state, 0, sizeof(state));
1016 		state.cieEnd = ptr;	/* keep here temporarily */
1017 		ptr = (const u8 *)(cie + 2);
1018 		end = (const u8 *)(cie + 1) + *cie;
1019 		frame->call_frame = 1;
1020 		if (*++ptr) {
1021 			/* check if augmentation size is first (thus present) */
1022 			if (*ptr == 'z') {
1023 				while (++ptr < end && *ptr) {
1024 					switch (*ptr) {
1025 					/* chk for ignorable or already handled
1026 					 * nul-terminated augmentation string */
1027 					case 'L':
1028 					case 'P':
1029 					case 'R':
1030 						continue;
1031 					case 'S':
1032 						frame->call_frame = 0;
1033 						continue;
1034 					default:
1035 						break;
1036 					}
1037 					break;
1038 				}
1039 			}
1040 			if (ptr >= end || *ptr)
1041 				cie = NULL;
1042 		}
1043 		++ptr;
1044 	}
1045 	if (cie != NULL) {
1046 		/* get code alignment factor */
1047 		state.codeAlign = get_uleb128(&ptr, end);
1048 		/* get data alignment factor */
1049 		state.dataAlign = get_sleb128(&ptr, end);
1050 		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1051 			cie = NULL;
1052 		else {
1053 			retAddrReg =
1054 			    state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1055 								      end);
1056 			unw_debug("CIE Frame Info:\n");
1057 			unw_debug("return Address register 0x%lx\n",
1058 				  retAddrReg);
1059 			unw_debug("data Align: %ld\n", state.dataAlign);
1060 			unw_debug("code Align: %lu\n", state.codeAlign);
1061 			/* skip augmentation */
1062 			if (((const char *)(cie + 2))[1] == 'z') {
1063 				uleb128_t augSize = get_uleb128(&ptr, end);
1064 
1065 				ptr += augSize;
1066 			}
1067 			if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1068 			    || REG_INVALID(retAddrReg)
1069 			    || reg_info[retAddrReg].width !=
1070 			    sizeof(unsigned long))
1071 				cie = NULL;
1072 		}
1073 	}
1074 	if (cie != NULL) {
1075 		state.cieStart = ptr;
1076 		ptr = state.cieEnd;
1077 		state.cieEnd = end;
1078 		end = (const u8 *)(fde + 1) + *fde;
1079 		/* skip augmentation */
1080 		if (((const char *)(cie + 2))[1] == 'z') {
1081 			uleb128_t augSize = get_uleb128(&ptr, end);
1082 
1083 			if ((ptr += augSize) > end)
1084 				fde = NULL;
1085 		}
1086 	}
1087 	if (cie == NULL || fde == NULL) {
1088 #ifdef CONFIG_FRAME_POINTER
1089 		unsigned long top, bottom;
1090 
1091 		top = STACK_TOP_UNW(frame->task);
1092 		bottom = STACK_BOTTOM_UNW(frame->task);
1093 #if FRAME_RETADDR_OFFSET < 0
1094 		if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1095 		    && bottom < UNW_FP(frame)
1096 #else
1097 		if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1098 		    && bottom > UNW_FP(frame)
1099 #endif
1100 		    && !((UNW_SP(frame) | UNW_FP(frame))
1101 			 & (sizeof(unsigned long) - 1))) {
1102 			unsigned long link;
1103 
1104 			if (!__get_user(link, (unsigned long *)
1105 					(UNW_FP(frame) + FRAME_LINK_OFFSET))
1106 #if FRAME_RETADDR_OFFSET < 0
1107 			    && link > bottom && link < UNW_FP(frame)
1108 #else
1109 			    && link > UNW_FP(frame) && link < bottom
1110 #endif
1111 			    && !(link & (sizeof(link) - 1))
1112 			    && !__get_user(UNW_PC(frame),
1113 					   (unsigned long *)(UNW_FP(frame)
1114 						+ FRAME_RETADDR_OFFSET)))
1115 			{
1116 				UNW_SP(frame) =
1117 				    UNW_FP(frame) + FRAME_RETADDR_OFFSET
1118 #if FRAME_RETADDR_OFFSET < 0
1119 				    -
1120 #else
1121 				    +
1122 #endif
1123 				    sizeof(UNW_PC(frame));
1124 				UNW_FP(frame) = link;
1125 				return 0;
1126 			}
1127 		}
1128 #endif
1129 		return -ENXIO;
1130 	}
1131 	state.org = startLoc;
1132 	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1133 
1134 	unw_debug("\nProcess instructions\n");
1135 
1136 	/* process instructions
1137 	 * For ARC, we optimize by having blink(retAddrReg) with
1138 	 * the sameValue in the leaf function, so we should not check
1139 	 * state.regs[retAddrReg].where == Nowhere
1140 	 */
1141 	if (!processCFI(ptr, end, pc, ptrType, &state)
1142 	    || state.loc > endLoc
1143 /*	   || state.regs[retAddrReg].where == Nowhere */
1144 	    || state.cfa.reg >= ARRAY_SIZE(reg_info)
1145 	    || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1146 	    || state.cfa.offs % sizeof(unsigned long))
1147 		return -EIO;
1148 
1149 #ifdef UNWIND_DEBUG
1150 	unw_debug("\n");
1151 
1152 	unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1153 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1154 
1155 		if (REG_INVALID(i))
1156 			continue;
1157 
1158 		switch (state.regs[i].where) {
1159 		case Nowhere:
1160 			break;
1161 		case Memory:
1162 			unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1163 			break;
1164 		case Register:
1165 			unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1166 			break;
1167 		case Value:
1168 			unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1169 			break;
1170 		}
1171 	}
1172 
1173 	unw_debug("\n");
1174 #endif
1175 
1176 	/* update frame */
1177 	if (frame->call_frame
1178 	    && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1179 		frame->call_frame = 0;
1180 	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1181 	startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1182 	endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1183 	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1184 		startLoc = min(STACK_LIMIT(cfa), cfa);
1185 		endLoc = max(STACK_LIMIT(cfa), cfa);
1186 	}
1187 
1188 	unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
1189 		  state.cfa.reg, state.cfa.offs, cfa);
1190 
1191 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1192 		if (REG_INVALID(i)) {
1193 			if (state.regs[i].where == Nowhere)
1194 				continue;
1195 			return -EIO;
1196 		}
1197 		switch (state.regs[i].where) {
1198 		default:
1199 			break;
1200 		case Register:
1201 			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1202 			    || REG_INVALID(state.regs[i].value)
1203 			    || reg_info[i].width >
1204 			    reg_info[state.regs[i].value].width)
1205 				return -EIO;
1206 			switch (reg_info[state.regs[i].value].width) {
1207 			case sizeof(u8):
1208 				state.regs[i].value =
1209 				FRAME_REG(state.regs[i].value, const u8);
1210 				break;
1211 			case sizeof(u16):
1212 				state.regs[i].value =
1213 				FRAME_REG(state.regs[i].value, const u16);
1214 				break;
1215 			case sizeof(u32):
1216 				state.regs[i].value =
1217 				FRAME_REG(state.regs[i].value, const u32);
1218 				break;
1219 #ifdef CONFIG_64BIT
1220 			case sizeof(u64):
1221 				state.regs[i].value =
1222 				FRAME_REG(state.regs[i].value, const u64);
1223 				break;
1224 #endif
1225 			default:
1226 				return -EIO;
1227 			}
1228 			break;
1229 		}
1230 	}
1231 
1232 	unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1233 	fptr = (unsigned long *)(&frame->regs);
1234 	for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1235 
1236 		if (REG_INVALID(i))
1237 			continue;
1238 		switch (state.regs[i].where) {
1239 		case Nowhere:
1240 			if (reg_info[i].width != sizeof(UNW_SP(frame))
1241 			    || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1242 			    != &UNW_SP(frame))
1243 				continue;
1244 			UNW_SP(frame) = cfa;
1245 			break;
1246 		case Register:
1247 			switch (reg_info[i].width) {
1248 			case sizeof(u8):
1249 				FRAME_REG(i, u8) = state.regs[i].value;
1250 				break;
1251 			case sizeof(u16):
1252 				FRAME_REG(i, u16) = state.regs[i].value;
1253 				break;
1254 			case sizeof(u32):
1255 				FRAME_REG(i, u32) = state.regs[i].value;
1256 				break;
1257 #ifdef CONFIG_64BIT
1258 			case sizeof(u64):
1259 				FRAME_REG(i, u64) = state.regs[i].value;
1260 				break;
1261 #endif
1262 			default:
1263 				return -EIO;
1264 			}
1265 			break;
1266 		case Value:
1267 			if (reg_info[i].width != sizeof(unsigned long))
1268 				return -EIO;
1269 			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1270 			    * state.dataAlign;
1271 			break;
1272 		case Memory:
1273 			addr = cfa + state.regs[i].value * state.dataAlign;
1274 
1275 			if ((state.regs[i].value * state.dataAlign)
1276 			    % sizeof(unsigned long)
1277 			    || addr < startLoc
1278 			    || addr + sizeof(unsigned long) < addr
1279 			    || addr + sizeof(unsigned long) > endLoc)
1280 					return -EIO;
1281 
1282 			switch (reg_info[i].width) {
1283 			case sizeof(u8):
1284 				__get_user(FRAME_REG(i, u8),
1285 					   (u8 __user *)addr);
1286 				break;
1287 			case sizeof(u16):
1288 				__get_user(FRAME_REG(i, u16),
1289 					   (u16 __user *)addr);
1290 				break;
1291 			case sizeof(u32):
1292 				__get_user(FRAME_REG(i, u32),
1293 					   (u32 __user *)addr);
1294 				break;
1295 #ifdef CONFIG_64BIT
1296 			case sizeof(u64):
1297 				__get_user(FRAME_REG(i, u64),
1298 					   (u64 __user *)addr);
1299 				break;
1300 #endif
1301 			default:
1302 				return -EIO;
1303 			}
1304 
1305 			break;
1306 		}
1307 		unw_debug("r%d: 0x%lx ", i, *fptr);
1308 	}
1309 
1310 	return 0;
1311 #undef FRAME_REG
1312 }
1313 EXPORT_SYMBOL(arc_unwind);
1314