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