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