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