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