xref: /openbmc/linux/arch/arc/kernel/unwind.c (revision 03638e62)
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 
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  */
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 
184 static void *unw_hdr_alloc(unsigned long sz)
185 {
186 	return kmalloc(sz, GFP_KERNEL);
187 }
188 
189 static void init_unwind_table(struct unwind_table *table, const char *name,
190 			      const void *core_start, unsigned long core_size,
191 			      const void *init_start, unsigned long init_size,
192 			      const void *table_start, unsigned long table_size,
193 			      const u8 *header_start, unsigned long header_size)
194 {
195 	const u8 *ptr = header_start + 4;
196 	const u8 *end = header_start + header_size;
197 
198 	table->core.pc = (unsigned long)core_start;
199 	table->core.range = core_size;
200 	table->init.pc = (unsigned long)init_start;
201 	table->init.range = init_size;
202 	table->address = table_start;
203 	table->size = table_size;
204 
205 	/* See if the linker provided table looks valid. */
206 	if (header_size <= 4
207 	    || header_start[0] != 1
208 	    || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
209 	    || header_start[2] == DW_EH_PE_omit
210 	    || read_pointer(&ptr, end, header_start[2]) <= 0
211 	    || header_start[3] == DW_EH_PE_omit)
212 		header_start = NULL;
213 
214 	table->hdrsz = header_size;
215 	smp_wmb();
216 	table->header = header_start;
217 	table->link = NULL;
218 	table->name = name;
219 }
220 
221 void __init arc_unwind_init(void)
222 {
223 	init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
224 			  __start_unwind, __end_unwind - __start_unwind,
225 			  NULL, 0);
226 	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
227 
228 	init_unwind_hdr(&root_table, unw_hdr_alloc_early);
229 }
230 
231 static const u32 bad_cie, not_fde;
232 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
233 static const u32 *__cie_for_fde(const u32 *fde);
234 static signed fde_pointer_type(const u32 *cie);
235 
236 struct eh_frame_hdr_table_entry {
237 	unsigned long start, fde;
238 };
239 
240 static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
241 {
242 	const struct eh_frame_hdr_table_entry *e1 = p1;
243 	const struct eh_frame_hdr_table_entry *e2 = p2;
244 
245 	return (e1->start > e2->start) - (e1->start < e2->start);
246 }
247 
248 static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
249 {
250 	struct eh_frame_hdr_table_entry *e1 = p1;
251 	struct eh_frame_hdr_table_entry *e2 = p2;
252 	unsigned long v;
253 
254 	v = e1->start;
255 	e1->start = e2->start;
256 	e2->start = v;
257 	v = e1->fde;
258 	e1->fde = e2->fde;
259 	e2->fde = v;
260 }
261 
262 static void init_unwind_hdr(struct unwind_table *table,
263 			    void *(*alloc) (unsigned long))
264 {
265 	const u8 *ptr;
266 	unsigned long tableSize = table->size, hdrSize;
267 	unsigned n;
268 	const u32 *fde;
269 	struct {
270 		u8 version;
271 		u8 eh_frame_ptr_enc;
272 		u8 fde_count_enc;
273 		u8 table_enc;
274 		unsigned long eh_frame_ptr;
275 		unsigned int fde_count;
276 		struct eh_frame_hdr_table_entry table[];
277 	} __attribute__ ((__packed__)) *header;
278 
279 	if (table->header)
280 		return;
281 
282 	if (table->hdrsz)
283 		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
284 			table->name);
285 
286 	if (tableSize & (sizeof(*fde) - 1))
287 		return;
288 
289 	for (fde = table->address, n = 0;
290 	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
291 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
292 		const u32 *cie = cie_for_fde(fde, table);
293 		signed ptrType;
294 
295 		if (cie == &not_fde)
296 			continue;
297 		if (cie == NULL || cie == &bad_cie)
298 			goto ret_err;
299 		ptrType = fde_pointer_type(cie);
300 		if (ptrType < 0)
301 			goto ret_err;
302 
303 		ptr = (const u8 *)(fde + 2);
304 		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
305 								ptrType)) {
306 			/* FIXME_Rajesh We have 4 instances of null addresses
307 			 * instead of the initial loc addr
308 			 * return;
309 			 */
310 			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
311 				(const u8 *)(fde + 1) + *fde);
312 		}
313 		++n;
314 	}
315 
316 	if (tableSize || !n)
317 		goto ret_err;
318 
319 	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
320 	    + 2 * n * sizeof(unsigned long);
321 
322 	header = alloc(hdrSize);
323 	if (!header)
324 		goto ret_err;
325 
326 	header->version = 1;
327 	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
328 	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
329 	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
330 	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
331 	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
332 		     % __alignof(typeof(header->fde_count)));
333 	header->fde_count = n;
334 
335 	BUILD_BUG_ON(offsetof(typeof(*header), table)
336 		     % __alignof(typeof(*header->table)));
337 	for (fde = table->address, tableSize = table->size, n = 0;
338 	     tableSize;
339 	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
340 		const u32 *cie = __cie_for_fde(fde);
341 
342 		if (fde[1] == CIE_ID)
343 			continue;	/* this is a CIE */
344 		ptr = (const u8 *)(fde + 2);
345 		header->table[n].start = read_pointer(&ptr,
346 						      (const u8 *)(fde + 1) +
347 						      *fde,
348 						      fde_pointer_type(cie));
349 		header->table[n].fde = (unsigned long)fde;
350 		++n;
351 	}
352 	WARN_ON(n != header->fde_count);
353 
354 	sort(header->table,
355 	     n,
356 	     sizeof(*header->table),
357 	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
358 
359 	table->hdrsz = hdrSize;
360 	smp_wmb();
361 	table->header = (const void *)header;
362 	return;
363 
364 ret_err:
365 	panic("Attention !!! Dwarf FDE parsing errors\n");
366 }
367 
368 #ifdef CONFIG_MODULES
369 
370 static struct unwind_table *last_table;
371 
372 /* Must be called with module_mutex held. */
373 void *unwind_add_table(struct module *module, const void *table_start,
374 		       unsigned long table_size)
375 {
376 	struct unwind_table *table;
377 
378 	if (table_size <= 0)
379 		return NULL;
380 
381 	table = kmalloc(sizeof(*table), GFP_KERNEL);
382 	if (!table)
383 		return NULL;
384 
385 	init_unwind_table(table, module->name,
386 			  module->core_layout.base, module->core_layout.size,
387 			  module->init_layout.base, module->init_layout.size,
388 			  table_start, table_size,
389 			  NULL, 0);
390 
391 	init_unwind_hdr(table, unw_hdr_alloc);
392 
393 #ifdef UNWIND_DEBUG
394 	unw_debug("Table added for [%s] %lx %lx\n",
395 		module->name, table->core.pc, table->core.range);
396 #endif
397 	if (last_table)
398 		last_table->link = table;
399 	else
400 		root_table.link = table;
401 	last_table = table;
402 
403 	return table;
404 }
405 
406 struct unlink_table_info {
407 	struct unwind_table *table;
408 	int init_only;
409 };
410 
411 static int unlink_table(void *arg)
412 {
413 	struct unlink_table_info *info = arg;
414 	struct unwind_table *table = info->table, *prev;
415 
416 	for (prev = &root_table; prev->link && prev->link != table;
417 	     prev = prev->link)
418 		;
419 
420 	if (prev->link) {
421 		if (info->init_only) {
422 			table->init.pc = 0;
423 			table->init.range = 0;
424 			info->table = NULL;
425 		} else {
426 			prev->link = table->link;
427 			if (!prev->link)
428 				last_table = prev;
429 		}
430 	} else
431 		info->table = NULL;
432 
433 	return 0;
434 }
435 
436 /* Must be called with module_mutex held. */
437 void unwind_remove_table(void *handle, int init_only)
438 {
439 	struct unwind_table *table = handle;
440 	struct unlink_table_info info;
441 
442 	if (!table || table == &root_table)
443 		return;
444 
445 	if (init_only && table == last_table) {
446 		table->init.pc = 0;
447 		table->init.range = 0;
448 		return;
449 	}
450 
451 	info.table = table;
452 	info.init_only = init_only;
453 
454 	unlink_table(&info); /* XXX: SMP */
455 	kfree(table->header);
456 	kfree(table);
457 }
458 
459 #endif /* CONFIG_MODULES */
460 
461 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
462 {
463 	const u8 *cur = *pcur;
464 	uleb128_t value;
465 	unsigned shift;
466 
467 	for (shift = 0, value = 0; cur < end; shift += 7) {
468 		if (shift + 7 > 8 * sizeof(value)
469 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
470 			cur = end + 1;
471 			break;
472 		}
473 		value |= (uleb128_t) (*cur & 0x7f) << shift;
474 		if (!(*cur++ & 0x80))
475 			break;
476 	}
477 	*pcur = cur;
478 
479 	return value;
480 }
481 
482 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
483 {
484 	const u8 *cur = *pcur;
485 	sleb128_t value;
486 	unsigned shift;
487 
488 	for (shift = 0, value = 0; cur < end; shift += 7) {
489 		if (shift + 7 > 8 * sizeof(value)
490 		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
491 			cur = end + 1;
492 			break;
493 		}
494 		value |= (sleb128_t) (*cur & 0x7f) << shift;
495 		if (!(*cur & 0x80)) {
496 			value |= -(*cur++ & 0x40) << shift;
497 			break;
498 		}
499 	}
500 	*pcur = cur;
501 
502 	return value;
503 }
504 
505 static const u32 *__cie_for_fde(const u32 *fde)
506 {
507 	const u32 *cie;
508 
509 	cie = fde + 1 - fde[1] / sizeof(*fde);
510 
511 	return cie;
512 }
513 
514 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
515 {
516 	const u32 *cie;
517 
518 	if (!*fde || (*fde & (sizeof(*fde) - 1)))
519 		return &bad_cie;
520 
521 	if (fde[1] == CIE_ID)
522 		return &not_fde;	/* this is a CIE */
523 
524 	if ((fde[1] & (sizeof(*fde) - 1)))
525 /* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
526 		return NULL;	/* this is not a valid FDE */
527 
528 	cie = __cie_for_fde(fde);
529 
530 	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
531 	    || (*cie & (sizeof(*cie) - 1))
532 	    || (cie[1] != CIE_ID))
533 		return NULL;	/* this is not a (valid) CIE */
534 	return cie;
535 }
536 
537 static unsigned long read_pointer(const u8 **pLoc, const void *end,
538 				  signed ptrType)
539 {
540 	unsigned long value = 0;
541 	union {
542 		const u8 *p8;
543 		const u16 *p16u;
544 		const s16 *p16s;
545 		const u32 *p32u;
546 		const s32 *p32s;
547 		const unsigned long *pul;
548 	} ptr;
549 
550 	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
551 		return 0;
552 	ptr.p8 = *pLoc;
553 	switch (ptrType & DW_EH_PE_FORM) {
554 	case DW_EH_PE_data2:
555 		if (end < (const void *)(ptr.p16u + 1))
556 			return 0;
557 		if (ptrType & DW_EH_PE_signed)
558 			value = get_unaligned((u16 *) ptr.p16s++);
559 		else
560 			value = get_unaligned((u16 *) ptr.p16u++);
561 		break;
562 	case DW_EH_PE_data4:
563 #ifdef CONFIG_64BIT
564 		if (end < (const void *)(ptr.p32u + 1))
565 			return 0;
566 		if (ptrType & DW_EH_PE_signed)
567 			value = get_unaligned(ptr.p32s++);
568 		else
569 			value = get_unaligned(ptr.p32u++);
570 		break;
571 	case DW_EH_PE_data8:
572 		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
573 #else
574 		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
575 #endif
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 
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 
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 
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 
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 				/*nobreak*/
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 				/*nobreak */
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. */
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