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