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