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