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