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