[PATCH] ioc4: Remove SN2 feature and config dependencies
[linux-2.6/mini2440.git] / kernel / unwind.c
blob2e2368607aab1a8293739315d832c608463d8d5f
1 /*
2 * Copyright (C) 2002-2006 Novell, Inc.
3 * Jan Beulich <jbeulich@novell.com>
4 * This code is released under version 2 of the GNU GPL.
6 * A simple API for unwinding kernel stacks. This is used for
7 * debugging and error reporting purposes. The kernel doesn't need
8 * full-blown stack unwinding with all the bells and whistles, so there
9 * is not much point in implementing the full Dwarf2 unwind API.
12 #include <linux/unwind.h>
13 #include <linux/module.h>
14 #include <linux/delay.h>
15 #include <linux/stop_machine.h>
16 #include <asm/sections.h>
17 #include <asm/uaccess.h>
18 #include <asm/unaligned.h>
20 extern char __start_unwind[], __end_unwind[];
22 #define MAX_STACK_DEPTH 8
24 #define EXTRA_INFO(f) { \
25 BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
26 % FIELD_SIZEOF(struct unwind_frame_info, f)) \
27 + offsetof(struct unwind_frame_info, f) \
28 / FIELD_SIZEOF(struct unwind_frame_info, f), \
29 FIELD_SIZEOF(struct unwind_frame_info, f) \
31 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
33 static const struct {
34 unsigned offs:BITS_PER_LONG / 2;
35 unsigned width:BITS_PER_LONG / 2;
36 } reg_info[] = {
37 UNW_REGISTER_INFO
40 #undef PTREGS_INFO
41 #undef EXTRA_INFO
43 #ifndef REG_INVALID
44 #define REG_INVALID(r) (reg_info[r].width == 0)
45 #endif
47 #define DW_CFA_nop 0x00
48 #define DW_CFA_set_loc 0x01
49 #define DW_CFA_advance_loc1 0x02
50 #define DW_CFA_advance_loc2 0x03
51 #define DW_CFA_advance_loc4 0x04
52 #define DW_CFA_offset_extended 0x05
53 #define DW_CFA_restore_extended 0x06
54 #define DW_CFA_undefined 0x07
55 #define DW_CFA_same_value 0x08
56 #define DW_CFA_register 0x09
57 #define DW_CFA_remember_state 0x0a
58 #define DW_CFA_restore_state 0x0b
59 #define DW_CFA_def_cfa 0x0c
60 #define DW_CFA_def_cfa_register 0x0d
61 #define DW_CFA_def_cfa_offset 0x0e
62 #define DW_CFA_def_cfa_expression 0x0f
63 #define DW_CFA_expression 0x10
64 #define DW_CFA_offset_extended_sf 0x11
65 #define DW_CFA_def_cfa_sf 0x12
66 #define DW_CFA_def_cfa_offset_sf 0x13
67 #define DW_CFA_val_offset 0x14
68 #define DW_CFA_val_offset_sf 0x15
69 #define DW_CFA_val_expression 0x16
70 #define DW_CFA_lo_user 0x1c
71 #define DW_CFA_GNU_window_save 0x2d
72 #define DW_CFA_GNU_args_size 0x2e
73 #define DW_CFA_GNU_negative_offset_extended 0x2f
74 #define DW_CFA_hi_user 0x3f
76 #define DW_EH_PE_FORM 0x07
77 #define DW_EH_PE_native 0x00
78 #define DW_EH_PE_leb128 0x01
79 #define DW_EH_PE_data2 0x02
80 #define DW_EH_PE_data4 0x03
81 #define DW_EH_PE_data8 0x04
82 #define DW_EH_PE_signed 0x08
83 #define DW_EH_PE_ADJUST 0x70
84 #define DW_EH_PE_abs 0x00
85 #define DW_EH_PE_pcrel 0x10
86 #define DW_EH_PE_textrel 0x20
87 #define DW_EH_PE_datarel 0x30
88 #define DW_EH_PE_funcrel 0x40
89 #define DW_EH_PE_aligned 0x50
90 #define DW_EH_PE_indirect 0x80
91 #define DW_EH_PE_omit 0xff
93 typedef unsigned long uleb128_t;
94 typedef signed long sleb128_t;
96 static struct unwind_table {
97 struct {
98 unsigned long pc;
99 unsigned long range;
100 } core, init;
101 const void *address;
102 unsigned long size;
103 struct unwind_table *link;
104 const char *name;
105 } root_table;
107 struct unwind_item {
108 enum item_location {
109 Nowhere,
110 Memory,
111 Register,
112 Value
113 } where;
114 uleb128_t value;
117 struct unwind_state {
118 uleb128_t loc, org;
119 const u8 *cieStart, *cieEnd;
120 uleb128_t codeAlign;
121 sleb128_t dataAlign;
122 struct cfa {
123 uleb128_t reg, offs;
124 } cfa;
125 struct unwind_item regs[ARRAY_SIZE(reg_info)];
126 unsigned stackDepth:8;
127 unsigned version:8;
128 const u8 *label;
129 const u8 *stack[MAX_STACK_DEPTH];
132 static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
134 static struct unwind_table *find_table(unsigned long pc)
136 struct unwind_table *table;
138 for (table = &root_table; table; table = table->link)
139 if ((pc >= table->core.pc
140 && pc < table->core.pc + table->core.range)
141 || (pc >= table->init.pc
142 && pc < table->init.pc + table->init.range))
143 break;
145 return table;
148 static void init_unwind_table(struct unwind_table *table,
149 const char *name,
150 const void *core_start,
151 unsigned long core_size,
152 const void *init_start,
153 unsigned long init_size,
154 const void *table_start,
155 unsigned long table_size)
157 table->core.pc = (unsigned long)core_start;
158 table->core.range = core_size;
159 table->init.pc = (unsigned long)init_start;
160 table->init.range = init_size;
161 table->address = table_start;
162 table->size = table_size;
163 table->link = NULL;
164 table->name = name;
167 void __init unwind_init(void)
169 init_unwind_table(&root_table, "kernel",
170 _text, _end - _text,
171 NULL, 0,
172 __start_unwind, __end_unwind - __start_unwind);
175 #ifdef CONFIG_MODULES
177 static struct unwind_table *last_table;
179 /* Must be called with module_mutex held. */
180 void *unwind_add_table(struct module *module,
181 const void *table_start,
182 unsigned long table_size)
184 struct unwind_table *table;
186 if (table_size <= 0)
187 return NULL;
189 table = kmalloc(sizeof(*table), GFP_KERNEL);
190 if (!table)
191 return NULL;
193 init_unwind_table(table, module->name,
194 module->module_core, module->core_size,
195 module->module_init, module->init_size,
196 table_start, table_size);
198 if (last_table)
199 last_table->link = table;
200 else
201 root_table.link = table;
202 last_table = table;
204 return table;
207 struct unlink_table_info
209 struct unwind_table *table;
210 int init_only;
213 static int unlink_table(void *arg)
215 struct unlink_table_info *info = arg;
216 struct unwind_table *table = info->table, *prev;
218 for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
221 if (prev->link) {
222 if (info->init_only) {
223 table->init.pc = 0;
224 table->init.range = 0;
225 info->table = NULL;
226 } else {
227 prev->link = table->link;
228 if (!prev->link)
229 last_table = prev;
231 } else
232 info->table = NULL;
234 return 0;
237 /* Must be called with module_mutex held. */
238 void unwind_remove_table(void *handle, int init_only)
240 struct unwind_table *table = handle;
241 struct unlink_table_info info;
243 if (!table || table == &root_table)
244 return;
246 if (init_only && table == last_table) {
247 table->init.pc = 0;
248 table->init.range = 0;
249 return;
252 info.table = table;
253 info.init_only = init_only;
254 stop_machine_run(unlink_table, &info, NR_CPUS);
256 if (info.table)
257 kfree(table);
260 #endif /* CONFIG_MODULES */
262 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
264 const u8 *cur = *pcur;
265 uleb128_t value;
266 unsigned shift;
268 for (shift = 0, value = 0; cur < end; shift += 7) {
269 if (shift + 7 > 8 * sizeof(value)
270 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
271 cur = end + 1;
272 break;
274 value |= (uleb128_t)(*cur & 0x7f) << shift;
275 if (!(*cur++ & 0x80))
276 break;
278 *pcur = cur;
280 return value;
283 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
285 const u8 *cur = *pcur;
286 sleb128_t value;
287 unsigned shift;
289 for (shift = 0, value = 0; cur < end; shift += 7) {
290 if (shift + 7 > 8 * sizeof(value)
291 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
292 cur = end + 1;
293 break;
295 value |= (sleb128_t)(*cur & 0x7f) << shift;
296 if (!(*cur & 0x80)) {
297 value |= -(*cur++ & 0x40) << shift;
298 break;
301 *pcur = cur;
303 return value;
306 static unsigned long read_pointer(const u8 **pLoc,
307 const void *end,
308 signed ptrType)
310 unsigned long value = 0;
311 union {
312 const u8 *p8;
313 const u16 *p16u;
314 const s16 *p16s;
315 const u32 *p32u;
316 const s32 *p32s;
317 const unsigned long *pul;
318 } ptr;
320 if (ptrType < 0 || ptrType == DW_EH_PE_omit)
321 return 0;
322 ptr.p8 = *pLoc;
323 switch(ptrType & DW_EH_PE_FORM) {
324 case DW_EH_PE_data2:
325 if (end < (const void *)(ptr.p16u + 1))
326 return 0;
327 if(ptrType & DW_EH_PE_signed)
328 value = get_unaligned(ptr.p16s++);
329 else
330 value = get_unaligned(ptr.p16u++);
331 break;
332 case DW_EH_PE_data4:
333 #ifdef CONFIG_64BIT
334 if (end < (const void *)(ptr.p32u + 1))
335 return 0;
336 if(ptrType & DW_EH_PE_signed)
337 value = get_unaligned(ptr.p32s++);
338 else
339 value = get_unaligned(ptr.p32u++);
340 break;
341 case DW_EH_PE_data8:
342 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
343 #else
344 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
345 #endif
346 case DW_EH_PE_native:
347 if (end < (const void *)(ptr.pul + 1))
348 return 0;
349 value = get_unaligned(ptr.pul++);
350 break;
351 case DW_EH_PE_leb128:
352 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
353 value = ptrType & DW_EH_PE_signed
354 ? get_sleb128(&ptr.p8, end)
355 : get_uleb128(&ptr.p8, end);
356 if ((const void *)ptr.p8 > end)
357 return 0;
358 break;
359 default:
360 return 0;
362 switch(ptrType & DW_EH_PE_ADJUST) {
363 case DW_EH_PE_abs:
364 break;
365 case DW_EH_PE_pcrel:
366 value += (unsigned long)*pLoc;
367 break;
368 default:
369 return 0;
371 if ((ptrType & DW_EH_PE_indirect)
372 && __get_user(value, (unsigned long *)value))
373 return 0;
374 *pLoc = ptr.p8;
376 return value;
379 static signed fde_pointer_type(const u32 *cie)
381 const u8 *ptr = (const u8 *)(cie + 2);
382 unsigned version = *ptr;
384 if (version != 1)
385 return -1; /* unsupported */
386 if (*++ptr) {
387 const char *aug;
388 const u8 *end = (const u8 *)(cie + 1) + *cie;
389 uleb128_t len;
391 /* check if augmentation size is first (and thus present) */
392 if (*ptr != 'z')
393 return -1;
394 /* check if augmentation string is nul-terminated */
395 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
396 return -1;
397 ++ptr; /* skip terminator */
398 get_uleb128(&ptr, end); /* skip code alignment */
399 get_sleb128(&ptr, end); /* skip data alignment */
400 /* skip return address column */
401 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
402 len = get_uleb128(&ptr, end); /* augmentation length */
403 if (ptr + len < ptr || ptr + len > end)
404 return -1;
405 end = ptr + len;
406 while (*++aug) {
407 if (ptr >= end)
408 return -1;
409 switch(*aug) {
410 case 'L':
411 ++ptr;
412 break;
413 case 'P': {
414 signed ptrType = *ptr++;
416 if (!read_pointer(&ptr, end, ptrType) || ptr > end)
417 return -1;
419 break;
420 case 'R':
421 return *ptr;
422 default:
423 return -1;
427 return DW_EH_PE_native|DW_EH_PE_abs;
430 static int advance_loc(unsigned long delta, struct unwind_state *state)
432 state->loc += delta * state->codeAlign;
434 return delta > 0;
437 static void set_rule(uleb128_t reg,
438 enum item_location where,
439 uleb128_t value,
440 struct unwind_state *state)
442 if (reg < ARRAY_SIZE(state->regs)) {
443 state->regs[reg].where = where;
444 state->regs[reg].value = value;
448 static int processCFI(const u8 *start,
449 const u8 *end,
450 unsigned long targetLoc,
451 signed ptrType,
452 struct unwind_state *state)
454 union {
455 const u8 *p8;
456 const u16 *p16;
457 const u32 *p32;
458 } ptr;
459 int result = 1;
461 if (start != state->cieStart) {
462 state->loc = state->org;
463 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
464 if (targetLoc == 0 && state->label == NULL)
465 return result;
467 for (ptr.p8 = start; result && ptr.p8 < end; ) {
468 switch(*ptr.p8 >> 6) {
469 uleb128_t value;
471 case 0:
472 switch(*ptr.p8++) {
473 case DW_CFA_nop:
474 break;
475 case DW_CFA_set_loc:
476 if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
477 result = 0;
478 break;
479 case DW_CFA_advance_loc1:
480 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
481 break;
482 case DW_CFA_advance_loc2:
483 result = ptr.p8 <= end + 2
484 && advance_loc(*ptr.p16++, state);
485 break;
486 case DW_CFA_advance_loc4:
487 result = ptr.p8 <= end + 4
488 && advance_loc(*ptr.p32++, state);
489 break;
490 case DW_CFA_offset_extended:
491 value = get_uleb128(&ptr.p8, end);
492 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
493 break;
494 case DW_CFA_val_offset:
495 value = get_uleb128(&ptr.p8, end);
496 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
497 break;
498 case DW_CFA_offset_extended_sf:
499 value = get_uleb128(&ptr.p8, end);
500 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
501 break;
502 case DW_CFA_val_offset_sf:
503 value = get_uleb128(&ptr.p8, end);
504 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
505 break;
506 case DW_CFA_restore_extended:
507 case DW_CFA_undefined:
508 case DW_CFA_same_value:
509 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
510 break;
511 case DW_CFA_register:
512 value = get_uleb128(&ptr.p8, end);
513 set_rule(value,
514 Register,
515 get_uleb128(&ptr.p8, end), state);
516 break;
517 case DW_CFA_remember_state:
518 if (ptr.p8 == state->label) {
519 state->label = NULL;
520 return 1;
522 if (state->stackDepth >= MAX_STACK_DEPTH)
523 return 0;
524 state->stack[state->stackDepth++] = ptr.p8;
525 break;
526 case DW_CFA_restore_state:
527 if (state->stackDepth) {
528 const uleb128_t loc = state->loc;
529 const u8 *label = state->label;
531 state->label = state->stack[state->stackDepth - 1];
532 memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
533 memset(state->regs, 0, sizeof(state->regs));
534 state->stackDepth = 0;
535 result = processCFI(start, end, 0, ptrType, state);
536 state->loc = loc;
537 state->label = label;
538 } else
539 return 0;
540 break;
541 case DW_CFA_def_cfa:
542 state->cfa.reg = get_uleb128(&ptr.p8, end);
543 /*nobreak*/
544 case DW_CFA_def_cfa_offset:
545 state->cfa.offs = get_uleb128(&ptr.p8, end);
546 break;
547 case DW_CFA_def_cfa_sf:
548 state->cfa.reg = get_uleb128(&ptr.p8, end);
549 /*nobreak*/
550 case DW_CFA_def_cfa_offset_sf:
551 state->cfa.offs = get_sleb128(&ptr.p8, end)
552 * state->dataAlign;
553 break;
554 case DW_CFA_def_cfa_register:
555 state->cfa.reg = get_uleb128(&ptr.p8, end);
556 break;
557 /*todo case DW_CFA_def_cfa_expression: */
558 /*todo case DW_CFA_expression: */
559 /*todo case DW_CFA_val_expression: */
560 case DW_CFA_GNU_args_size:
561 get_uleb128(&ptr.p8, end);
562 break;
563 case DW_CFA_GNU_negative_offset_extended:
564 value = get_uleb128(&ptr.p8, end);
565 set_rule(value,
566 Memory,
567 (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
568 break;
569 case DW_CFA_GNU_window_save:
570 default:
571 result = 0;
572 break;
574 break;
575 case 1:
576 result = advance_loc(*ptr.p8++ & 0x3f, state);
577 break;
578 case 2:
579 value = *ptr.p8++ & 0x3f;
580 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
581 break;
582 case 3:
583 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
584 break;
586 if (ptr.p8 > end)
587 result = 0;
588 if (result && targetLoc != 0 && targetLoc < state->loc)
589 return 1;
592 return result
593 && ptr.p8 == end
594 && (targetLoc == 0
595 || (/*todo While in theory this should apply, gcc in practice omits
596 everything past the function prolog, and hence the location
597 never reaches the end of the function.
598 targetLoc < state->loc &&*/ state->label == NULL));
601 /* Unwind to previous to frame. Returns 0 if successful, negative
602 * number in case of an error. */
603 int unwind(struct unwind_frame_info *frame)
605 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
606 const u32 *fde = NULL, *cie = NULL;
607 const u8 *ptr = NULL, *end = NULL;
608 unsigned long pc = UNW_PC(frame) - frame->call_frame;
609 unsigned long startLoc = 0, endLoc = 0, cfa;
610 unsigned i;
611 signed ptrType = -1;
612 uleb128_t retAddrReg = 0;
613 struct unwind_table *table;
614 struct unwind_state state;
616 if (UNW_PC(frame) == 0)
617 return -EINVAL;
618 if ((table = find_table(pc)) != NULL
619 && !(table->size & (sizeof(*fde) - 1))) {
620 unsigned long tableSize = table->size;
622 for (fde = table->address;
623 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
624 tableSize -= sizeof(*fde) + *fde,
625 fde += 1 + *fde / sizeof(*fde)) {
626 if (!*fde || (*fde & (sizeof(*fde) - 1)))
627 break;
628 if (!fde[1])
629 continue; /* this is a CIE */
630 if ((fde[1] & (sizeof(*fde) - 1))
631 || fde[1] > (unsigned long)(fde + 1)
632 - (unsigned long)table->address)
633 continue; /* this is not a valid FDE */
634 cie = fde + 1 - fde[1] / sizeof(*fde);
635 if (*cie <= sizeof(*cie) + 4
636 || *cie >= fde[1] - sizeof(*fde)
637 || (*cie & (sizeof(*cie) - 1))
638 || cie[1]
639 || (ptrType = fde_pointer_type(cie)) < 0) {
640 cie = NULL; /* this is not a (valid) CIE */
641 continue;
643 ptr = (const u8 *)(fde + 2);
644 startLoc = read_pointer(&ptr,
645 (const u8 *)(fde + 1) + *fde,
646 ptrType);
647 endLoc = startLoc
648 + read_pointer(&ptr,
649 (const u8 *)(fde + 1) + *fde,
650 ptrType & DW_EH_PE_indirect
651 ? ptrType
652 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
653 if (pc >= startLoc && pc < endLoc)
654 break;
655 cie = NULL;
658 if (cie != NULL) {
659 memset(&state, 0, sizeof(state));
660 state.cieEnd = ptr; /* keep here temporarily */
661 ptr = (const u8 *)(cie + 2);
662 end = (const u8 *)(cie + 1) + *cie;
663 frame->call_frame = 1;
664 if ((state.version = *ptr) != 1)
665 cie = NULL; /* unsupported version */
666 else if (*++ptr) {
667 /* check if augmentation size is first (and thus present) */
668 if (*ptr == 'z') {
669 while (++ptr < end && *ptr) {
670 switch(*ptr) {
671 /* check for ignorable (or already handled)
672 * nul-terminated augmentation string */
673 case 'L':
674 case 'P':
675 case 'R':
676 continue;
677 case 'S':
678 frame->call_frame = 0;
679 continue;
680 default:
681 break;
683 break;
686 if (ptr >= end || *ptr)
687 cie = NULL;
689 ++ptr;
691 if (cie != NULL) {
692 /* get code aligment factor */
693 state.codeAlign = get_uleb128(&ptr, end);
694 /* get data aligment factor */
695 state.dataAlign = get_sleb128(&ptr, end);
696 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
697 cie = NULL;
698 else {
699 retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
700 /* skip augmentation */
701 if (((const char *)(cie + 2))[1] == 'z')
702 ptr += get_uleb128(&ptr, end);
703 if (ptr > end
704 || retAddrReg >= ARRAY_SIZE(reg_info)
705 || REG_INVALID(retAddrReg)
706 || reg_info[retAddrReg].width != sizeof(unsigned long))
707 cie = NULL;
710 if (cie != NULL) {
711 state.cieStart = ptr;
712 ptr = state.cieEnd;
713 state.cieEnd = end;
714 end = (const u8 *)(fde + 1) + *fde;
715 /* skip augmentation */
716 if (((const char *)(cie + 2))[1] == 'z') {
717 uleb128_t augSize = get_uleb128(&ptr, end);
719 if ((ptr += augSize) > end)
720 fde = NULL;
723 if (cie == NULL || fde == NULL) {
724 #ifdef CONFIG_FRAME_POINTER
725 unsigned long top, bottom;
726 #endif
728 #ifdef CONFIG_FRAME_POINTER
729 top = STACK_TOP(frame->task);
730 bottom = STACK_BOTTOM(frame->task);
731 # if FRAME_RETADDR_OFFSET < 0
732 if (UNW_SP(frame) < top
733 && UNW_FP(frame) <= UNW_SP(frame)
734 && bottom < UNW_FP(frame)
735 # else
736 if (UNW_SP(frame) > top
737 && UNW_FP(frame) >= UNW_SP(frame)
738 && bottom > UNW_FP(frame)
739 # endif
740 && !((UNW_SP(frame) | UNW_FP(frame))
741 & (sizeof(unsigned long) - 1))) {
742 unsigned long link;
744 if (!__get_user(link,
745 (unsigned long *)(UNW_FP(frame)
746 + FRAME_LINK_OFFSET))
747 # if FRAME_RETADDR_OFFSET < 0
748 && link > bottom && link < UNW_FP(frame)
749 # else
750 && link > UNW_FP(frame) && link < bottom
751 # endif
752 && !(link & (sizeof(link) - 1))
753 && !__get_user(UNW_PC(frame),
754 (unsigned long *)(UNW_FP(frame)
755 + FRAME_RETADDR_OFFSET))) {
756 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
757 # if FRAME_RETADDR_OFFSET < 0
759 # else
761 # endif
762 sizeof(UNW_PC(frame));
763 UNW_FP(frame) = link;
764 return 0;
767 #endif
768 return -ENXIO;
770 state.org = startLoc;
771 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
772 /* process instructions */
773 if (!processCFI(ptr, end, pc, ptrType, &state)
774 || state.loc > endLoc
775 || state.regs[retAddrReg].where == Nowhere
776 || state.cfa.reg >= ARRAY_SIZE(reg_info)
777 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
778 || state.cfa.offs % sizeof(unsigned long))
779 return -EIO;
780 /* update frame */
781 #ifndef CONFIG_AS_CFI_SIGNAL_FRAME
782 if(frame->call_frame
783 && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
784 frame->call_frame = 0;
785 #endif
786 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
787 startLoc = min((unsigned long)UNW_SP(frame), cfa);
788 endLoc = max((unsigned long)UNW_SP(frame), cfa);
789 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
790 startLoc = min(STACK_LIMIT(cfa), cfa);
791 endLoc = max(STACK_LIMIT(cfa), cfa);
793 #ifndef CONFIG_64BIT
794 # define CASES CASE(8); CASE(16); CASE(32)
795 #else
796 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
797 #endif
798 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
799 if (REG_INVALID(i)) {
800 if (state.regs[i].where == Nowhere)
801 continue;
802 return -EIO;
804 switch(state.regs[i].where) {
805 default:
806 break;
807 case Register:
808 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
809 || REG_INVALID(state.regs[i].value)
810 || reg_info[i].width > reg_info[state.regs[i].value].width)
811 return -EIO;
812 switch(reg_info[state.regs[i].value].width) {
813 #define CASE(n) \
814 case sizeof(u##n): \
815 state.regs[i].value = FRAME_REG(state.regs[i].value, \
816 const u##n); \
817 break
818 CASES;
819 #undef CASE
820 default:
821 return -EIO;
823 break;
826 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
827 if (REG_INVALID(i))
828 continue;
829 switch(state.regs[i].where) {
830 case Nowhere:
831 if (reg_info[i].width != sizeof(UNW_SP(frame))
832 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
833 != &UNW_SP(frame))
834 continue;
835 UNW_SP(frame) = cfa;
836 break;
837 case Register:
838 switch(reg_info[i].width) {
839 #define CASE(n) case sizeof(u##n): \
840 FRAME_REG(i, u##n) = state.regs[i].value; \
841 break
842 CASES;
843 #undef CASE
844 default:
845 return -EIO;
847 break;
848 case Value:
849 if (reg_info[i].width != sizeof(unsigned long))
850 return -EIO;
851 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
852 * state.dataAlign;
853 break;
854 case Memory: {
855 unsigned long addr = cfa + state.regs[i].value
856 * state.dataAlign;
858 if ((state.regs[i].value * state.dataAlign)
859 % sizeof(unsigned long)
860 || addr < startLoc
861 || addr + sizeof(unsigned long) < addr
862 || addr + sizeof(unsigned long) > endLoc)
863 return -EIO;
864 switch(reg_info[i].width) {
865 #define CASE(n) case sizeof(u##n): \
866 __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
867 break
868 CASES;
869 #undef CASE
870 default:
871 return -EIO;
874 break;
878 return 0;
879 #undef CASES
880 #undef FRAME_REG
882 EXPORT_SYMBOL(unwind);
884 int unwind_init_frame_info(struct unwind_frame_info *info,
885 struct task_struct *tsk,
886 /*const*/ struct pt_regs *regs)
888 info->task = tsk;
889 info->call_frame = 0;
890 arch_unw_init_frame_info(info, regs);
892 return 0;
894 EXPORT_SYMBOL(unwind_init_frame_info);
897 * Prepare to unwind a blocked task.
899 int unwind_init_blocked(struct unwind_frame_info *info,
900 struct task_struct *tsk)
902 info->task = tsk;
903 info->call_frame = 0;
904 arch_unw_init_blocked(info);
906 return 0;
908 EXPORT_SYMBOL(unwind_init_blocked);
911 * Prepare to unwind the currently running thread.
913 int unwind_init_running(struct unwind_frame_info *info,
914 asmlinkage int (*callback)(struct unwind_frame_info *,
915 void *arg),
916 void *arg)
918 info->task = current;
919 info->call_frame = 0;
921 return arch_unwind_init_running(info, callback, arg);
923 EXPORT_SYMBOL(unwind_init_running);
926 * Unwind until the return pointer is in user-land (or until an error
927 * occurs). Returns 0 if successful, negative number in case of
928 * error.
930 int unwind_to_user(struct unwind_frame_info *info)
932 while (!arch_unw_user_mode(info)) {
933 int err = unwind(info);
935 if (err < 0)
936 return err;
939 return 0;
941 EXPORT_SYMBOL(unwind_to_user);