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 */
35 #define unw_debug(fmt, ...) \
38 pr_info(fmt, ##__VA_ARGS__); \
41 #define unw_debug(fmt, ...)
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)
56 unsigned offs:BITS_PER_LONG / 2;
57 unsigned width:BITS_PER_LONG / 2;
65 #define REG_INVALID(r) (reg_info[r].width == 0)
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 {
124 const unsigned char *header;
126 struct unwind_table *link;
140 struct unwind_state {
142 const u8 *cieStart, *cieEnd;
148 struct unwind_item regs[ARRAY_SIZE(reg_info)];
149 unsigned stackDepth:8;
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))
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));
177 * wrappers for header alloc (vs. calling one vs. other at call site)
178 * to elide section mismatches warnings
180 static void *__init unw_hdr_alloc_early(unsigned long sz)
182 return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
186 static void init_unwind_table(struct unwind_table *table, const char *name,
187 const void *core_start, unsigned long core_size,
188 const void *init_start, unsigned long init_size,
189 const void *table_start, unsigned long table_size,
190 const u8 *header_start, unsigned long header_size)
192 const u8 *ptr = header_start + 4;
193 const u8 *end = header_start + header_size;
195 table->core.pc = (unsigned long)core_start;
196 table->core.range = core_size;
197 table->init.pc = (unsigned long)init_start;
198 table->init.range = init_size;
199 table->address = table_start;
200 table->size = table_size;
202 /* See if the linker provided table looks valid. */
204 || header_start[0] != 1
205 || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
206 || header_start[2] == DW_EH_PE_omit
207 || read_pointer(&ptr, end, header_start[2]) <= 0
208 || header_start[3] == DW_EH_PE_omit)
211 table->hdrsz = header_size;
213 table->header = header_start;
218 void __init arc_unwind_init(void)
220 init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
221 __start_unwind, __end_unwind - __start_unwind,
223 /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
225 init_unwind_hdr(&root_table, unw_hdr_alloc_early);
228 static const u32 bad_cie, not_fde;
229 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
230 static signed fde_pointer_type(const u32 *cie);
232 struct eh_frame_hdr_table_entry {
233 unsigned long start, fde;
236 static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
238 const struct eh_frame_hdr_table_entry *e1 = p1;
239 const struct eh_frame_hdr_table_entry *e2 = p2;
241 return (e1->start > e2->start) - (e1->start < e2->start);
244 static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
246 struct eh_frame_hdr_table_entry *e1 = p1;
247 struct eh_frame_hdr_table_entry *e2 = p2;
251 e1->start = e2->start;
258 static void init_unwind_hdr(struct unwind_table *table,
259 void *(*alloc) (unsigned long))
262 unsigned long tableSize = table->size, hdrSize;
270 unsigned long eh_frame_ptr;
271 unsigned int fde_count;
272 struct eh_frame_hdr_table_entry table[];
273 } __attribute__ ((__packed__)) *header;
279 pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
282 if (tableSize & (sizeof(*fde) - 1))
285 for (fde = table->address, n = 0;
286 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
287 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
288 const u32 *cie = cie_for_fde(fde, table);
293 if (cie == NULL || cie == &bad_cie)
295 ptrType = fde_pointer_type(cie);
299 ptr = (const u8 *)(fde + 2);
300 if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
302 /* FIXME_Rajesh We have 4 instances of null addresses
303 * instead of the initial loc addr
306 WARN(1, "unwinder: FDE->initial_location NULL %p\n",
307 (const u8 *)(fde + 1) + *fde);
315 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
316 + 2 * n * sizeof(unsigned long);
318 header = alloc(hdrSize);
323 header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
324 header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
325 header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
326 put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
327 BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
328 % __alignof(typeof(header->fde_count)));
329 header->fde_count = n;
331 BUILD_BUG_ON(offsetof(typeof(*header), table)
332 % __alignof(typeof(*header->table)));
333 for (fde = table->address, tableSize = table->size, n = 0;
335 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
336 /* const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); */
337 const u32 *cie = (const u32 *)(fde[1]);
339 if (fde[1] == 0xffffffff)
340 continue; /* this is a CIE */
341 ptr = (const u8 *)(fde + 2);
342 header->table[n].start = read_pointer(&ptr,
343 (const u8 *)(fde + 1) +
345 fde_pointer_type(cie));
346 header->table[n].fde = (unsigned long)fde;
349 WARN_ON(n != header->fde_count);
353 sizeof(*header->table),
354 cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
356 table->hdrsz = hdrSize;
358 table->header = (const void *)header;
362 panic("Attention !!! Dwarf FDE parsing errors\n");;
365 #ifdef CONFIG_MODULES
366 static void *unw_hdr_alloc(unsigned long sz)
368 return kmalloc(sz, GFP_KERNEL);
371 static struct unwind_table *last_table;
373 /* Must be called with module_mutex held. */
374 void *unwind_add_table(struct module *module, const void *table_start,
375 unsigned long table_size)
377 struct unwind_table *table;
382 table = kmalloc(sizeof(*table), GFP_KERNEL);
386 init_unwind_table(table, module->name,
387 module->module_core, module->core_size,
388 module->module_init, module->init_size,
389 table_start, table_size,
392 init_unwind_hdr(table, unw_hdr_alloc);
395 unw_debug("Table added for [%s] %lx %lx\n",
396 module->name, table->core.pc, table->core.range);
399 last_table->link = table;
401 root_table.link = table;
407 struct unlink_table_info {
408 struct unwind_table *table;
412 static int unlink_table(void *arg)
414 struct unlink_table_info *info = arg;
415 struct unwind_table *table = info->table, *prev;
417 for (prev = &root_table; prev->link && prev->link != table;
422 if (info->init_only) {
424 table->init.range = 0;
427 prev->link = table->link;
437 /* Must be called with module_mutex held. */
438 void unwind_remove_table(void *handle, int init_only)
440 struct unwind_table *table = handle;
441 struct unlink_table_info info;
443 if (!table || table == &root_table)
446 if (init_only && table == last_table) {
448 table->init.range = 0;
453 info.init_only = init_only;
455 unlink_table(&info); /* XXX: SMP */
456 kfree(table->header);
460 #endif /* CONFIG_MODULES */
462 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
464 const u8 *cur = *pcur;
468 for (shift = 0, value = 0; cur < end; shift += 7) {
469 if (shift + 7 > 8 * sizeof(value)
470 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
474 value |= (uleb128_t) (*cur & 0x7f) << shift;
475 if (!(*cur++ & 0x80))
483 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
485 const u8 *cur = *pcur;
489 for (shift = 0, value = 0; cur < end; shift += 7) {
490 if (shift + 7 > 8 * sizeof(value)
491 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
495 value |= (sleb128_t) (*cur & 0x7f) << shift;
496 if (!(*cur & 0x80)) {
497 value |= -(*cur++ & 0x40) << shift;
506 static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
510 if (!*fde || (*fde & (sizeof(*fde) - 1)))
513 if (fde[1] == 0xffffffff)
514 return ¬_fde; /* this is a CIE */
516 if ((fde[1] & (sizeof(*fde) - 1)))
517 /* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
518 return NULL; /* this is not a valid FDE */
520 /* cie = fde + 1 - fde[1] / sizeof(*fde); */
521 cie = (u32 *) fde[1];
523 if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
524 || (*cie & (sizeof(*cie) - 1))
525 || (cie[1] != 0xffffffff))
526 return NULL; /* this is not a (valid) CIE */
530 static unsigned long read_pointer(const u8 **pLoc, const void *end,
533 unsigned long value = 0;
540 const unsigned long *pul;
543 if (ptrType < 0 || ptrType == DW_EH_PE_omit)
546 switch (ptrType & DW_EH_PE_FORM) {
548 if (end < (const void *)(ptr.p16u + 1))
550 if (ptrType & DW_EH_PE_signed)
551 value = get_unaligned((u16 *) ptr.p16s++);
553 value = get_unaligned((u16 *) ptr.p16u++);
557 if (end < (const void *)(ptr.p32u + 1))
559 if (ptrType & DW_EH_PE_signed)
560 value = get_unaligned(ptr.p32s++);
562 value = get_unaligned(ptr.p32u++);
565 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
567 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
569 case DW_EH_PE_native:
570 if (end < (const void *)(ptr.pul + 1))
572 value = get_unaligned((unsigned long *)ptr.pul++);
574 case DW_EH_PE_leb128:
575 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
576 value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
577 : get_uleb128(&ptr.p8, end);
578 if ((const void *)ptr.p8 > end)
584 switch (ptrType & DW_EH_PE_ADJUST) {
588 value += (unsigned long)*pLoc;
593 if ((ptrType & DW_EH_PE_indirect)
594 && __get_user(value, (unsigned long __user *)value))
601 static signed fde_pointer_type(const u32 *cie)
603 const u8 *ptr = (const u8 *)(cie + 2);
604 unsigned version = *ptr;
608 const u8 *end = (const u8 *)(cie + 1) + *cie;
611 /* check if augmentation size is first (and thus present) */
615 /* check if augmentation string is nul-terminated */
616 aug = (const void *)ptr;
617 ptr = memchr(aug, 0, end - ptr);
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 */
628 if (ptr + len < ptr || ptr + len > end)
640 signed ptrType = *ptr++;
642 if (!read_pointer(&ptr, end, ptrType)
654 return DW_EH_PE_native | DW_EH_PE_abs;
657 static int advance_loc(unsigned long delta, struct unwind_state *state)
659 state->loc += delta * state->codeAlign;
661 /* FIXME_Rajesh: Probably we are defining for the initial range as well;
664 unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
668 static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
669 struct unwind_state *state)
671 if (reg < ARRAY_SIZE(state->regs)) {
672 state->regs[reg].where = where;
673 state->regs[reg].value = value;
676 unw_debug("r%lu: ", reg);
682 unw_debug("c(%lu) ", value);
685 unw_debug("r(%lu) ", value);
688 unw_debug("v(%lu) ", value);
697 static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
698 signed ptrType, struct unwind_state *state)
708 if (start != state->cieStart) {
709 state->loc = state->org;
711 processCFI(state->cieStart, state->cieEnd, 0, ptrType,
713 if (targetLoc == 0 && state->label == NULL)
716 for (ptr.p8 = start; result && ptr.p8 < end;) {
717 switch (*ptr.p8 >> 6) {
725 unw_debug("cfa nop ");
728 state->loc = read_pointer(&ptr.p8, end,
732 unw_debug("cfa_set_loc: 0x%lx ", state->loc);
734 case DW_CFA_advance_loc1:
735 unw_debug("\ncfa advance loc1:");
736 result = ptr.p8 < end
737 && advance_loc(*ptr.p8++, state);
739 case DW_CFA_advance_loc2:
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);
747 case DW_CFA_advance_loc4:
748 unw_debug("\ncfa advance loc4:");
749 result = ptr.p8 <= end + 4
750 && advance_loc(*ptr.p32++, state);
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);
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);
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);
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);
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,
782 case DW_CFA_register:
783 unw_debug("cfa_register: ");
784 value = get_uleb128(&ptr.p8, end);
787 get_uleb128(&ptr.p8, end), state);
789 case DW_CFA_remember_state:
790 unw_debug("cfa_remember_state: ");
791 if (ptr.p8 == state->label) {
795 if (state->stackDepth >= MAX_STACK_DEPTH)
797 state->stack[state->stackDepth++] = ptr.p8;
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;
806 state->stack[state->stackDepth - 1];
807 memcpy(&state->cfa, &badCFA,
809 memset(state->regs, 0,
810 sizeof(state->regs));
811 state->stackDepth = 0;
813 processCFI(start, end, 0, ptrType,
816 state->label = label;
821 state->cfa.reg = get_uleb128(&ptr.p8, end);
822 unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
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 ",
829 case DW_CFA_def_cfa_sf:
830 state->cfa.reg = get_uleb128(&ptr.p8, end);
832 case DW_CFA_def_cfa_offset_sf:
833 state->cfa.offs = get_sleb128(&ptr.p8, end)
836 case DW_CFA_def_cfa_register:
837 unw_debug("cfa_def_cfa_regsiter: ");
838 state->cfa.reg = get_uleb128(&ptr.p8, end);
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);
846 case DW_CFA_GNU_negative_offset_extended:
847 value = get_uleb128(&ptr.p8, end);
850 (uleb128_t) 0 - get_uleb128(&ptr.p8,
854 case DW_CFA_GNU_window_save:
856 unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
862 unw_debug("\ncfa_adv_loc: ");
863 result = advance_loc(*ptr.p8++ & 0x3f, state);
866 unw_debug("cfa_offset: ");
867 value = *ptr.p8++ & 0x3f;
868 set_rule(value, Memory, get_uleb128(&ptr.p8, end),
872 unw_debug("cfa_restore: ");
873 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
879 if (result && targetLoc != 0 && targetLoc < state->loc)
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));
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)
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;
901 uleb128_t retAddrReg = 0;
902 const struct unwind_table *table;
903 struct unwind_state state;
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),
912 if (UNW_PC(frame) == 0)
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);
925 table = find_table(pc);
927 && !(table->size & (sizeof(*fde) - 1))) {
928 const u8 *hdr = table->header;
929 unsigned long tableSize;
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);
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))) {
959 ptr + (i / 2) * (2 * tableSize);
961 startLoc = read_pointer(&cur,
967 ptr = cur - tableSize;
970 } while (startLoc && i > 1);
972 && (startLoc = read_pointer(&ptr,
976 fde = (void *)read_pointer(&ptr,
984 cie = cie_for_fde(fde, table);
985 ptr = (const u8 *)(fde + 2);
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))
995 DW_EH_PE_FORM | DW_EH_PE_signed;
997 startLoc + read_pointer(&ptr,
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;
1018 /* check if augmentation size is first (thus present) */
1020 while (++ptr < end && *ptr) {
1022 /* chk for ignorable or already handled
1023 * nul-terminated augmentation string */
1029 frame->call_frame = 0;
1037 if (ptr >= end || *ptr)
1043 /* get code aligment factor */
1044 state.codeAlign = get_uleb128(&ptr, end);
1045 /* get data aligment factor */
1046 state.dataAlign = get_sleb128(&ptr, end);
1047 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1051 state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1053 unw_debug("CIE Frame Info:\n");
1054 unw_debug("return Address register 0x%lx\n",
1056 unw_debug("data Align: %ld\n", state.dataAlign);
1057 unw_debug("code Align: %lu\n", state.codeAlign);
1058 /* skip augmentation */
1059 if (((const char *)(cie + 2))[1] == 'z') {
1060 uleb128_t augSize = get_uleb128(&ptr, end);
1064 if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1065 || REG_INVALID(retAddrReg)
1066 || reg_info[retAddrReg].width !=
1067 sizeof(unsigned long))
1072 state.cieStart = ptr;
1075 end = (const u8 *)(fde + 1) + *fde;
1076 /* skip augmentation */
1077 if (((const char *)(cie + 2))[1] == 'z') {
1078 uleb128_t augSize = get_uleb128(&ptr, end);
1080 if ((ptr += augSize) > end)
1084 if (cie == NULL || fde == NULL) {
1085 #ifdef CONFIG_FRAME_POINTER
1086 unsigned long top, bottom;
1088 top = STACK_TOP_UNW(frame->task);
1089 bottom = STACK_BOTTOM_UNW(frame->task);
1090 #if FRAME_RETADDR_OFFSET < 0
1091 if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1092 && bottom < UNW_FP(frame)
1094 if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1095 && bottom > UNW_FP(frame)
1097 && !((UNW_SP(frame) | UNW_FP(frame))
1098 & (sizeof(unsigned long) - 1))) {
1101 if (!__get_user(link, (unsigned long *)
1102 (UNW_FP(frame) + FRAME_LINK_OFFSET))
1103 #if FRAME_RETADDR_OFFSET < 0
1104 && link > bottom && link < UNW_FP(frame)
1106 && link > UNW_FP(frame) && link < bottom
1108 && !(link & (sizeof(link) - 1))
1109 && !__get_user(UNW_PC(frame),
1110 (unsigned long *)(UNW_FP(frame)
1111 + FRAME_RETADDR_OFFSET)))
1114 UNW_FP(frame) + FRAME_RETADDR_OFFSET
1115 #if FRAME_RETADDR_OFFSET < 0
1120 sizeof(UNW_PC(frame));
1121 UNW_FP(frame) = link;
1128 state.org = startLoc;
1129 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1131 unw_debug("\nProcess instructions\n");
1133 /* process instructions
1134 * For ARC, we optimize by having blink(retAddrReg) with
1135 * the sameValue in the leaf function, so we should not check
1136 * state.regs[retAddrReg].where == Nowhere
1138 if (!processCFI(ptr, end, pc, ptrType, &state)
1139 || state.loc > endLoc
1140 /* || state.regs[retAddrReg].where == Nowhere */
1141 || state.cfa.reg >= ARRAY_SIZE(reg_info)
1142 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1143 || state.cfa.offs % sizeof(unsigned long))
1149 unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1150 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1155 switch (state.regs[i].where) {
1159 unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1162 unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1165 unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1174 #ifndef CONFIG_AS_CFI_SIGNAL_FRAME
1175 if (frame->call_frame
1176 && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1177 frame->call_frame = 0;
1179 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1180 startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1181 endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1182 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1183 startLoc = min(STACK_LIMIT(cfa), cfa);
1184 endLoc = max(STACK_LIMIT(cfa), cfa);
1187 unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx => 0x%lx\n",
1188 state.cfa.reg, state.cfa.offs, cfa);
1190 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1191 if (REG_INVALID(i)) {
1192 if (state.regs[i].where == Nowhere)
1196 switch (state.regs[i].where) {
1200 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1201 || REG_INVALID(state.regs[i].value)
1202 || reg_info[i].width >
1203 reg_info[state.regs[i].value].width)
1205 switch (reg_info[state.regs[i].value].width) {
1207 state.regs[i].value =
1208 FRAME_REG(state.regs[i].value, const u8);
1211 state.regs[i].value =
1212 FRAME_REG(state.regs[i].value, const u16);
1215 state.regs[i].value =
1216 FRAME_REG(state.regs[i].value, const u32);
1220 state.regs[i].value =
1221 FRAME_REG(state.regs[i].value, const u64);
1231 unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1232 fptr = (unsigned long *)(&frame->regs);
1233 for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1237 switch (state.regs[i].where) {
1239 if (reg_info[i].width != sizeof(UNW_SP(frame))
1240 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1243 UNW_SP(frame) = cfa;
1246 switch (reg_info[i].width) {
1248 FRAME_REG(i, u8) = state.regs[i].value;
1251 FRAME_REG(i, u16) = state.regs[i].value;
1254 FRAME_REG(i, u32) = state.regs[i].value;
1258 FRAME_REG(i, u64) = state.regs[i].value;
1266 if (reg_info[i].width != sizeof(unsigned long))
1268 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1272 addr = cfa + state.regs[i].value * state.dataAlign;
1274 if ((state.regs[i].value * state.dataAlign)
1275 % sizeof(unsigned long)
1277 || addr + sizeof(unsigned long) < addr
1278 || addr + sizeof(unsigned long) > endLoc)
1281 switch (reg_info[i].width) {
1283 __get_user(FRAME_REG(i, u8),
1287 __get_user(FRAME_REG(i, u16),
1288 (u16 __user *)addr);
1291 __get_user(FRAME_REG(i, u32),
1292 (u32 __user *)addr);
1296 __get_user(FRAME_REG(i, u64),
1297 (u64 __user *)addr);
1306 unw_debug("r%d: 0x%lx ", i, *fptr);
1312 EXPORT_SYMBOL(arc_unwind);