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