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