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