[PATCH] x86_64: reliable stack trace support
[wrt350n-kernel.git] / kernel / unwind.c
blobd36bcd3ad3b5d5877f45713ab5b4710432ffc337
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, *last_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 /* Must be called with module_mutex held. */
176 void *unwind_add_table(struct module *module,
177 const void *table_start,
178 unsigned long table_size)
180 struct unwind_table *table;
182 if (table_size <= 0)
183 return NULL;
185 table = kmalloc(sizeof(*table), GFP_KERNEL);
186 if (!table)
187 return NULL;
189 init_unwind_table(table, module->name,
190 module->module_core, module->core_size,
191 module->module_init, module->init_size,
192 table_start, table_size);
194 if (last_table)
195 last_table->link = table;
196 else
197 root_table.link = table;
198 last_table = table;
200 return table;
203 struct unlink_table_info
205 struct unwind_table *table;
206 int init_only;
209 static int unlink_table(void *arg)
211 struct unlink_table_info *info = arg;
212 struct unwind_table *table = info->table, *prev;
214 for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
217 if (prev->link) {
218 if (info->init_only) {
219 table->init.pc = 0;
220 table->init.range = 0;
221 info->table = NULL;
222 } else {
223 prev->link = table->link;
224 if (!prev->link)
225 last_table = prev;
227 } else
228 info->table = NULL;
230 return 0;
233 /* Must be called with module_mutex held. */
234 void unwind_remove_table(void *handle, int init_only)
236 struct unwind_table *table = handle;
237 struct unlink_table_info info;
239 if (!table || table == &root_table)
240 return;
242 if (init_only && table == last_table) {
243 table->init.pc = 0;
244 table->init.range = 0;
245 return;
248 info.table = table;
249 info.init_only = init_only;
250 stop_machine_run(unlink_table, &info, NR_CPUS);
252 if (info.table)
253 kfree(table);
256 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
258 const u8 *cur = *pcur;
259 uleb128_t value;
260 unsigned shift;
262 for (shift = 0, value = 0; cur < end; shift += 7) {
263 if (shift + 7 > 8 * sizeof(value)
264 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
265 cur = end + 1;
266 break;
268 value |= (uleb128_t)(*cur & 0x7f) << shift;
269 if (!(*cur++ & 0x80))
270 break;
272 *pcur = cur;
274 return value;
277 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
279 const u8 *cur = *pcur;
280 sleb128_t value;
281 unsigned shift;
283 for (shift = 0, value = 0; cur < end; shift += 7) {
284 if (shift + 7 > 8 * sizeof(value)
285 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
286 cur = end + 1;
287 break;
289 value |= (sleb128_t)(*cur & 0x7f) << shift;
290 if (!(*cur & 0x80)) {
291 value |= -(*cur++ & 0x40) << shift;
292 break;
295 *pcur = cur;
297 return value;
300 static unsigned long read_pointer(const u8 **pLoc,
301 const void *end,
302 signed ptrType)
304 unsigned long value = 0;
305 union {
306 const u8 *p8;
307 const u16 *p16u;
308 const s16 *p16s;
309 const u32 *p32u;
310 const s32 *p32s;
311 const unsigned long *pul;
312 } ptr;
314 if (ptrType < 0 || ptrType == DW_EH_PE_omit)
315 return 0;
316 ptr.p8 = *pLoc;
317 switch(ptrType & DW_EH_PE_FORM) {
318 case DW_EH_PE_data2:
319 if (end < (const void *)(ptr.p16u + 1))
320 return 0;
321 if(ptrType & DW_EH_PE_signed)
322 value = get_unaligned(ptr.p16s++);
323 else
324 value = get_unaligned(ptr.p16u++);
325 break;
326 case DW_EH_PE_data4:
327 #ifdef CONFIG_64BIT
328 if (end < (const void *)(ptr.p32u + 1))
329 return 0;
330 if(ptrType & DW_EH_PE_signed)
331 value = get_unaligned(ptr.p32s++);
332 else
333 value = get_unaligned(ptr.p32u++);
334 break;
335 case DW_EH_PE_data8:
336 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
337 #else
338 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
339 #endif
340 case DW_EH_PE_native:
341 if (end < (const void *)(ptr.pul + 1))
342 return 0;
343 value = get_unaligned(ptr.pul++);
344 break;
345 case DW_EH_PE_leb128:
346 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
347 value = ptrType & DW_EH_PE_signed
348 ? get_sleb128(&ptr.p8, end)
349 : get_uleb128(&ptr.p8, end);
350 if ((const void *)ptr.p8 > end)
351 return 0;
352 break;
353 default:
354 return 0;
356 switch(ptrType & DW_EH_PE_ADJUST) {
357 case DW_EH_PE_abs:
358 break;
359 case DW_EH_PE_pcrel:
360 value += (unsigned long)*pLoc;
361 break;
362 default:
363 return 0;
365 if ((ptrType & DW_EH_PE_indirect)
366 && __get_user(value, (unsigned long *)value))
367 return 0;
368 *pLoc = ptr.p8;
370 return value;
373 static signed fde_pointer_type(const u32 *cie)
375 const u8 *ptr = (const u8 *)(cie + 2);
376 unsigned version = *ptr;
378 if (version != 1)
379 return -1; /* unsupported */
380 if (*++ptr) {
381 const char *aug;
382 const u8 *end = (const u8 *)(cie + 1) + *cie;
383 uleb128_t len;
385 /* check if augmentation size is first (and thus present) */
386 if (*ptr != 'z')
387 return -1;
388 /* check if augmentation string is nul-terminated */
389 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
390 return -1;
391 ++ptr; /* skip terminator */
392 get_uleb128(&ptr, end); /* skip code alignment */
393 get_sleb128(&ptr, end); /* skip data alignment */
394 /* skip return address column */
395 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
396 len = get_uleb128(&ptr, end); /* augmentation length */
397 if (ptr + len < ptr || ptr + len > end)
398 return -1;
399 end = ptr + len;
400 while (*++aug) {
401 if (ptr >= end)
402 return -1;
403 switch(*aug) {
404 case 'L':
405 ++ptr;
406 break;
407 case 'P': {
408 signed ptrType = *ptr++;
410 if (!read_pointer(&ptr, end, ptrType) || ptr > end)
411 return -1;
413 break;
414 case 'R':
415 return *ptr;
416 default:
417 return -1;
421 return DW_EH_PE_native|DW_EH_PE_abs;
424 static int advance_loc(unsigned long delta, struct unwind_state *state)
426 state->loc += delta * state->codeAlign;
428 return delta > 0;
431 static void set_rule(uleb128_t reg,
432 enum item_location where,
433 uleb128_t value,
434 struct unwind_state *state)
436 if (reg < ARRAY_SIZE(state->regs)) {
437 state->regs[reg].where = where;
438 state->regs[reg].value = value;
442 static int processCFI(const u8 *start,
443 const u8 *end,
444 unsigned long targetLoc,
445 signed ptrType,
446 struct unwind_state *state)
448 union {
449 const u8 *p8;
450 const u16 *p16;
451 const u32 *p32;
452 } ptr;
453 int result = 1;
455 if (start != state->cieStart) {
456 state->loc = state->org;
457 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
458 if (targetLoc == 0 && state->label == NULL)
459 return result;
461 for (ptr.p8 = start; result && ptr.p8 < end; ) {
462 switch(*ptr.p8 >> 6) {
463 uleb128_t value;
465 case 0:
466 switch(*ptr.p8++) {
467 case DW_CFA_nop:
468 break;
469 case DW_CFA_set_loc:
470 if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
471 result = 0;
472 break;
473 case DW_CFA_advance_loc1:
474 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
475 break;
476 case DW_CFA_advance_loc2:
477 result = ptr.p8 <= end + 2
478 && advance_loc(*ptr.p16++, state);
479 break;
480 case DW_CFA_advance_loc4:
481 result = ptr.p8 <= end + 4
482 && advance_loc(*ptr.p32++, state);
483 break;
484 case DW_CFA_offset_extended:
485 value = get_uleb128(&ptr.p8, end);
486 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
487 break;
488 case DW_CFA_val_offset:
489 value = get_uleb128(&ptr.p8, end);
490 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
491 break;
492 case DW_CFA_offset_extended_sf:
493 value = get_uleb128(&ptr.p8, end);
494 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
495 break;
496 case DW_CFA_val_offset_sf:
497 value = get_uleb128(&ptr.p8, end);
498 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
499 break;
500 case DW_CFA_restore_extended:
501 case DW_CFA_undefined:
502 case DW_CFA_same_value:
503 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
504 break;
505 case DW_CFA_register:
506 value = get_uleb128(&ptr.p8, end);
507 set_rule(value,
508 Register,
509 get_uleb128(&ptr.p8, end), state);
510 break;
511 case DW_CFA_remember_state:
512 if (ptr.p8 == state->label) {
513 state->label = NULL;
514 return 1;
516 if (state->stackDepth >= MAX_STACK_DEPTH)
517 return 0;
518 state->stack[state->stackDepth++] = ptr.p8;
519 break;
520 case DW_CFA_restore_state:
521 if (state->stackDepth) {
522 const uleb128_t loc = state->loc;
523 const u8 *label = state->label;
525 state->label = state->stack[state->stackDepth - 1];
526 memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
527 memset(state->regs, 0, sizeof(state->regs));
528 state->stackDepth = 0;
529 result = processCFI(start, end, 0, ptrType, state);
530 state->loc = loc;
531 state->label = label;
532 } else
533 return 0;
534 break;
535 case DW_CFA_def_cfa:
536 state->cfa.reg = get_uleb128(&ptr.p8, end);
537 /*nobreak*/
538 case DW_CFA_def_cfa_offset:
539 state->cfa.offs = get_uleb128(&ptr.p8, end);
540 break;
541 case DW_CFA_def_cfa_sf:
542 state->cfa.reg = get_uleb128(&ptr.p8, end);
543 /*nobreak*/
544 case DW_CFA_def_cfa_offset_sf:
545 state->cfa.offs = get_sleb128(&ptr.p8, end)
546 * state->dataAlign;
547 break;
548 case DW_CFA_def_cfa_register:
549 state->cfa.reg = get_uleb128(&ptr.p8, end);
550 break;
551 /*todo case DW_CFA_def_cfa_expression: */
552 /*todo case DW_CFA_expression: */
553 /*todo case DW_CFA_val_expression: */
554 case DW_CFA_GNU_args_size:
555 get_uleb128(&ptr.p8, end);
556 break;
557 case DW_CFA_GNU_negative_offset_extended:
558 value = get_uleb128(&ptr.p8, end);
559 set_rule(value,
560 Memory,
561 (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
562 break;
563 case DW_CFA_GNU_window_save:
564 default:
565 result = 0;
566 break;
568 break;
569 case 1:
570 result = advance_loc(*ptr.p8++ & 0x3f, state);
571 break;
572 case 2:
573 value = *ptr.p8++ & 0x3f;
574 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
575 break;
576 case 3:
577 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
578 break;
580 if (ptr.p8 > end)
581 result = 0;
582 if (result && targetLoc != 0 && targetLoc < state->loc)
583 return 1;
586 return result
587 && ptr.p8 == end
588 && (targetLoc == 0
589 || (/*todo While in theory this should apply, gcc in practice omits
590 everything past the function prolog, and hence the location
591 never reaches the end of the function.
592 targetLoc < state->loc &&*/ state->label == NULL));
595 /* Unwind to previous to frame. Returns 0 if successful, negative
596 * number in case of an error. */
597 int unwind(struct unwind_frame_info *frame)
599 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
600 const u32 *fde = NULL, *cie = NULL;
601 const u8 *ptr = NULL, *end = NULL;
602 unsigned long startLoc = 0, endLoc = 0, cfa;
603 unsigned i;
604 signed ptrType = -1;
605 uleb128_t retAddrReg = 0;
606 struct unwind_table *table;
607 struct unwind_state state;
609 if (UNW_PC(frame) == 0)
610 return -EINVAL;
611 if ((table = find_table(UNW_PC(frame))) != NULL
612 && !(table->size & (sizeof(*fde) - 1))) {
613 unsigned long tableSize = table->size;
615 for (fde = table->address;
616 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
617 tableSize -= sizeof(*fde) + *fde,
618 fde += 1 + *fde / sizeof(*fde)) {
619 if (!*fde || (*fde & (sizeof(*fde) - 1)))
620 break;
621 if (!fde[1])
622 continue; /* this is a CIE */
623 if ((fde[1] & (sizeof(*fde) - 1))
624 || fde[1] > (unsigned long)(fde + 1)
625 - (unsigned long)table->address)
626 continue; /* this is not a valid FDE */
627 cie = fde + 1 - fde[1] / sizeof(*fde);
628 if (*cie <= sizeof(*cie) + 4
629 || *cie >= fde[1] - sizeof(*fde)
630 || (*cie & (sizeof(*cie) - 1))
631 || cie[1]
632 || (ptrType = fde_pointer_type(cie)) < 0) {
633 cie = NULL; /* this is not a (valid) CIE */
634 continue;
636 ptr = (const u8 *)(fde + 2);
637 startLoc = read_pointer(&ptr,
638 (const u8 *)(fde + 1) + *fde,
639 ptrType);
640 endLoc = startLoc
641 + read_pointer(&ptr,
642 (const u8 *)(fde + 1) + *fde,
643 ptrType & DW_EH_PE_indirect
644 ? ptrType
645 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
646 if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
647 break;
648 cie = NULL;
651 if (cie != NULL) {
652 memset(&state, 0, sizeof(state));
653 state.cieEnd = ptr; /* keep here temporarily */
654 ptr = (const u8 *)(cie + 2);
655 end = (const u8 *)(cie + 1) + *cie;
656 if ((state.version = *ptr) != 1)
657 cie = NULL; /* unsupported version */
658 else if (*++ptr) {
659 /* check if augmentation size is first (and thus present) */
660 if (*ptr == 'z') {
661 /* check for ignorable (or already handled)
662 * nul-terminated augmentation string */
663 while (++ptr < end && *ptr)
664 if (strchr("LPR", *ptr) == NULL)
665 break;
667 if (ptr >= end || *ptr)
668 cie = NULL;
670 ++ptr;
672 if (cie != NULL) {
673 /* get code aligment factor */
674 state.codeAlign = get_uleb128(&ptr, end);
675 /* get data aligment factor */
676 state.dataAlign = get_sleb128(&ptr, end);
677 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
678 cie = NULL;
679 else {
680 retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
681 /* skip augmentation */
682 if (((const char *)(cie + 2))[1] == 'z')
683 ptr += get_uleb128(&ptr, end);
684 if (ptr > end
685 || retAddrReg >= ARRAY_SIZE(reg_info)
686 || REG_INVALID(retAddrReg)
687 || reg_info[retAddrReg].width != sizeof(unsigned long))
688 cie = NULL;
691 if (cie != NULL) {
692 state.cieStart = ptr;
693 ptr = state.cieEnd;
694 state.cieEnd = end;
695 end = (const u8 *)(fde + 1) + *fde;
696 /* skip augmentation */
697 if (((const char *)(cie + 2))[1] == 'z') {
698 uleb128_t augSize = get_uleb128(&ptr, end);
700 if ((ptr += augSize) > end)
701 fde = NULL;
704 if (cie == NULL || fde == NULL) {
705 #ifdef CONFIG_FRAME_POINTER
706 unsigned long top, bottom;
707 #endif
709 #ifdef CONFIG_FRAME_POINTER
710 top = STACK_TOP(frame->task);
711 bottom = STACK_BOTTOM(frame->task);
712 # if FRAME_RETADDR_OFFSET < 0
713 if (UNW_SP(frame) < top
714 && UNW_FP(frame) <= UNW_SP(frame)
715 && bottom < UNW_FP(frame)
716 # else
717 if (UNW_SP(frame) > top
718 && UNW_FP(frame) >= UNW_SP(frame)
719 && bottom > UNW_FP(frame)
720 # endif
721 && !((UNW_SP(frame) | UNW_FP(frame))
722 & (sizeof(unsigned long) - 1))) {
723 unsigned long link;
725 if (!__get_user(link,
726 (unsigned long *)(UNW_FP(frame)
727 + FRAME_LINK_OFFSET))
728 # if FRAME_RETADDR_OFFSET < 0
729 && link > bottom && link < UNW_FP(frame)
730 # else
731 && link > UNW_FP(frame) && link < bottom
732 # endif
733 && !(link & (sizeof(link) - 1))
734 && !__get_user(UNW_PC(frame),
735 (unsigned long *)(UNW_FP(frame)
736 + FRAME_RETADDR_OFFSET))) {
737 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
738 # if FRAME_RETADDR_OFFSET < 0
740 # else
742 # endif
743 sizeof(UNW_PC(frame));
744 UNW_FP(frame) = link;
745 return 0;
748 #endif
749 return -ENXIO;
751 state.org = startLoc;
752 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
753 /* process instructions */
754 if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
755 || state.loc > endLoc
756 || state.regs[retAddrReg].where == Nowhere
757 || state.cfa.reg >= ARRAY_SIZE(reg_info)
758 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
759 || state.cfa.offs % sizeof(unsigned long))
760 return -EIO;
761 /* update frame */
762 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
763 startLoc = min((unsigned long)UNW_SP(frame), cfa);
764 endLoc = max((unsigned long)UNW_SP(frame), cfa);
765 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
766 startLoc = min(STACK_LIMIT(cfa), cfa);
767 endLoc = max(STACK_LIMIT(cfa), cfa);
769 #ifndef CONFIG_64BIT
770 # define CASES CASE(8); CASE(16); CASE(32)
771 #else
772 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
773 #endif
774 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
775 if (REG_INVALID(i)) {
776 if (state.regs[i].where == Nowhere)
777 continue;
778 return -EIO;
780 switch(state.regs[i].where) {
781 default:
782 break;
783 case Register:
784 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
785 || REG_INVALID(state.regs[i].value)
786 || reg_info[i].width > reg_info[state.regs[i].value].width)
787 return -EIO;
788 switch(reg_info[state.regs[i].value].width) {
789 #define CASE(n) \
790 case sizeof(u##n): \
791 state.regs[i].value = FRAME_REG(state.regs[i].value, \
792 const u##n); \
793 break
794 CASES;
795 #undef CASE
796 default:
797 return -EIO;
799 break;
802 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
803 if (REG_INVALID(i))
804 continue;
805 switch(state.regs[i].where) {
806 case Nowhere:
807 if (reg_info[i].width != sizeof(UNW_SP(frame))
808 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
809 != &UNW_SP(frame))
810 continue;
811 UNW_SP(frame) = cfa;
812 break;
813 case Register:
814 switch(reg_info[i].width) {
815 #define CASE(n) case sizeof(u##n): \
816 FRAME_REG(i, u##n) = state.regs[i].value; \
817 break
818 CASES;
819 #undef CASE
820 default:
821 return -EIO;
823 break;
824 case Value:
825 if (reg_info[i].width != sizeof(unsigned long))
826 return -EIO;
827 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
828 * state.dataAlign;
829 break;
830 case Memory: {
831 unsigned long addr = cfa + state.regs[i].value
832 * state.dataAlign;
834 if ((state.regs[i].value * state.dataAlign)
835 % sizeof(unsigned long)
836 || addr < startLoc
837 || addr + sizeof(unsigned long) < addr
838 || addr + sizeof(unsigned long) > endLoc)
839 return -EIO;
840 switch(reg_info[i].width) {
841 #define CASE(n) case sizeof(u##n): \
842 __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
843 break
844 CASES;
845 #undef CASE
846 default:
847 return -EIO;
850 break;
854 return 0;
855 #undef CASES
856 #undef FRAME_REG
858 EXPORT_SYMBOL(unwind);
860 int unwind_init_frame_info(struct unwind_frame_info *info,
861 struct task_struct *tsk,
862 /*const*/ struct pt_regs *regs)
864 info->task = tsk;
865 arch_unw_init_frame_info(info, regs);
867 return 0;
869 EXPORT_SYMBOL(unwind_init_frame_info);
872 * Prepare to unwind a blocked task.
874 int unwind_init_blocked(struct unwind_frame_info *info,
875 struct task_struct *tsk)
877 info->task = tsk;
878 arch_unw_init_blocked(info);
880 return 0;
882 EXPORT_SYMBOL(unwind_init_blocked);
885 * Prepare to unwind the currently running thread.
887 int unwind_init_running(struct unwind_frame_info *info,
888 asmlinkage void (*callback)(struct unwind_frame_info *,
889 void *arg),
890 void *arg)
892 info->task = current;
893 arch_unwind_init_running(info, callback, arg);
895 return 0;
897 EXPORT_SYMBOL(unwind_init_running);
900 * Unwind until the return pointer is in user-land (or until an error
901 * occurs). Returns 0 if successful, negative number in case of
902 * error.
904 int unwind_to_user(struct unwind_frame_info *info)
906 while (!arch_unw_user_mode(info)) {
907 int err = unwind(info);
909 if (err < 0)
910 return err;
913 return 0;
915 EXPORT_SYMBOL(unwind_to_user);