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