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