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