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