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