Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[deliverable/linux.git] / kernel / unwind.c
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.
5 *
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.
10 */
11
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>
19
20 extern char __start_unwind[], __end_unwind[];
21
22 #define MAX_STACK_DEPTH 8
23
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) \
30 }
31 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
32
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
38 };
39
40 #undef PTREGS_INFO
41 #undef EXTRA_INFO
42
43 #ifndef REG_INVALID
44 #define REG_INVALID(r) (reg_info[r].width == 0)
45 #endif
46
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
75
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
92
93 typedef unsigned long uleb128_t;
94 typedef signed long sleb128_t;
95
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;
106
107 struct unwind_item {
108 enum item_location {
109 Nowhere,
110 Memory,
111 Register,
112 Value
113 } where;
114 uleb128_t value;
115 };
116
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];
130 };
131
132 static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
133
134 static struct unwind_table *find_table(unsigned long pc)
135 {
136 struct unwind_table *table;
137
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;
144
145 return table;
146 }
147
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)
156 {
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;
165 }
166
167 void __init unwind_init(void)
168 {
169 init_unwind_table(&root_table, "kernel",
170 _text, _end - _text,
171 NULL, 0,
172 __start_unwind, __end_unwind - __start_unwind);
173 }
174
175 #ifdef CONFIG_MODULES
176
177 /* Must be called with module_mutex held. */
178 void *unwind_add_table(struct module *module,
179 const void *table_start,
180 unsigned long table_size)
181 {
182 struct unwind_table *table;
183
184 if (table_size <= 0)
185 return NULL;
186
187 table = kmalloc(sizeof(*table), GFP_KERNEL);
188 if (!table)
189 return NULL;
190
191 init_unwind_table(table, module->name,
192 module->module_core, module->core_size,
193 module->module_init, module->init_size,
194 table_start, table_size);
195
196 if (last_table)
197 last_table->link = table;
198 else
199 root_table.link = table;
200 last_table = table;
201
202 return table;
203 }
204
205 struct unlink_table_info
206 {
207 struct unwind_table *table;
208 int init_only;
209 };
210
211 static int unlink_table(void *arg)
212 {
213 struct unlink_table_info *info = arg;
214 struct unwind_table *table = info->table, *prev;
215
216 for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
217 ;
218
219 if (prev->link) {
220 if (info->init_only) {
221 table->init.pc = 0;
222 table->init.range = 0;
223 info->table = NULL;
224 } else {
225 prev->link = table->link;
226 if (!prev->link)
227 last_table = prev;
228 }
229 } else
230 info->table = NULL;
231
232 return 0;
233 }
234
235 /* Must be called with module_mutex held. */
236 void unwind_remove_table(void *handle, int init_only)
237 {
238 struct unwind_table *table = handle;
239 struct unlink_table_info info;
240
241 if (!table || table == &root_table)
242 return;
243
244 if (init_only && table == last_table) {
245 table->init.pc = 0;
246 table->init.range = 0;
247 return;
248 }
249
250 info.table = table;
251 info.init_only = init_only;
252 stop_machine_run(unlink_table, &info, NR_CPUS);
253
254 if (info.table)
255 kfree(table);
256 }
257
258 #endif /* CONFIG_MODULES */
259
260 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
261 {
262 const u8 *cur = *pcur;
263 uleb128_t value;
264 unsigned shift;
265
266 for (shift = 0, value = 0; cur < end; shift += 7) {
267 if (shift + 7 > 8 * sizeof(value)
268 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
269 cur = end + 1;
270 break;
271 }
272 value |= (uleb128_t)(*cur & 0x7f) << shift;
273 if (!(*cur++ & 0x80))
274 break;
275 }
276 *pcur = cur;
277
278 return value;
279 }
280
281 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
282 {
283 const u8 *cur = *pcur;
284 sleb128_t value;
285 unsigned shift;
286
287 for (shift = 0, value = 0; cur < end; shift += 7) {
288 if (shift + 7 > 8 * sizeof(value)
289 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
290 cur = end + 1;
291 break;
292 }
293 value |= (sleb128_t)(*cur & 0x7f) << shift;
294 if (!(*cur & 0x80)) {
295 value |= -(*cur++ & 0x40) << shift;
296 break;
297 }
298 }
299 *pcur = cur;
300
301 return value;
302 }
303
304 static unsigned long read_pointer(const u8 **pLoc,
305 const void *end,
306 signed ptrType)
307 {
308 unsigned long value = 0;
309 union {
310 const u8 *p8;
311 const u16 *p16u;
312 const s16 *p16s;
313 const u32 *p32u;
314 const s32 *p32s;
315 const unsigned long *pul;
316 } ptr;
317
318 if (ptrType < 0 || ptrType == DW_EH_PE_omit)
319 return 0;
320 ptr.p8 = *pLoc;
321 switch(ptrType & DW_EH_PE_FORM) {
322 case DW_EH_PE_data2:
323 if (end < (const void *)(ptr.p16u + 1))
324 return 0;
325 if(ptrType & DW_EH_PE_signed)
326 value = get_unaligned(ptr.p16s++);
327 else
328 value = get_unaligned(ptr.p16u++);
329 break;
330 case DW_EH_PE_data4:
331 #ifdef CONFIG_64BIT
332 if (end < (const void *)(ptr.p32u + 1))
333 return 0;
334 if(ptrType & DW_EH_PE_signed)
335 value = get_unaligned(ptr.p32s++);
336 else
337 value = get_unaligned(ptr.p32u++);
338 break;
339 case DW_EH_PE_data8:
340 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
341 #else
342 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
343 #endif
344 case DW_EH_PE_native:
345 if (end < (const void *)(ptr.pul + 1))
346 return 0;
347 value = get_unaligned(ptr.pul++);
348 break;
349 case DW_EH_PE_leb128:
350 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
351 value = ptrType & DW_EH_PE_signed
352 ? get_sleb128(&ptr.p8, end)
353 : get_uleb128(&ptr.p8, end);
354 if ((const void *)ptr.p8 > end)
355 return 0;
356 break;
357 default:
358 return 0;
359 }
360 switch(ptrType & DW_EH_PE_ADJUST) {
361 case DW_EH_PE_abs:
362 break;
363 case DW_EH_PE_pcrel:
364 value += (unsigned long)*pLoc;
365 break;
366 default:
367 return 0;
368 }
369 if ((ptrType & DW_EH_PE_indirect)
370 && __get_user(value, (unsigned long *)value))
371 return 0;
372 *pLoc = ptr.p8;
373
374 return value;
375 }
376
377 static signed fde_pointer_type(const u32 *cie)
378 {
379 const u8 *ptr = (const u8 *)(cie + 2);
380 unsigned version = *ptr;
381
382 if (version != 1)
383 return -1; /* unsupported */
384 if (*++ptr) {
385 const char *aug;
386 const u8 *end = (const u8 *)(cie + 1) + *cie;
387 uleb128_t len;
388
389 /* check if augmentation size is first (and thus present) */
390 if (*ptr != 'z')
391 return -1;
392 /* check if augmentation string is nul-terminated */
393 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
394 return -1;
395 ++ptr; /* skip terminator */
396 get_uleb128(&ptr, end); /* skip code alignment */
397 get_sleb128(&ptr, end); /* skip data alignment */
398 /* skip return address column */
399 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
400 len = get_uleb128(&ptr, end); /* augmentation length */
401 if (ptr + len < ptr || ptr + len > end)
402 return -1;
403 end = ptr + len;
404 while (*++aug) {
405 if (ptr >= end)
406 return -1;
407 switch(*aug) {
408 case 'L':
409 ++ptr;
410 break;
411 case 'P': {
412 signed ptrType = *ptr++;
413
414 if (!read_pointer(&ptr, end, ptrType) || ptr > end)
415 return -1;
416 }
417 break;
418 case 'R':
419 return *ptr;
420 default:
421 return -1;
422 }
423 }
424 }
425 return DW_EH_PE_native|DW_EH_PE_abs;
426 }
427
428 static int advance_loc(unsigned long delta, struct unwind_state *state)
429 {
430 state->loc += delta * state->codeAlign;
431
432 return delta > 0;
433 }
434
435 static void set_rule(uleb128_t reg,
436 enum item_location where,
437 uleb128_t value,
438 struct unwind_state *state)
439 {
440 if (reg < ARRAY_SIZE(state->regs)) {
441 state->regs[reg].where = where;
442 state->regs[reg].value = value;
443 }
444 }
445
446 static int processCFI(const u8 *start,
447 const u8 *end,
448 unsigned long targetLoc,
449 signed ptrType,
450 struct unwind_state *state)
451 {
452 union {
453 const u8 *p8;
454 const u16 *p16;
455 const u32 *p32;
456 } ptr;
457 int result = 1;
458
459 if (start != state->cieStart) {
460 state->loc = state->org;
461 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
462 if (targetLoc == 0 && state->label == NULL)
463 return result;
464 }
465 for (ptr.p8 = start; result && ptr.p8 < end; ) {
466 switch(*ptr.p8 >> 6) {
467 uleb128_t value;
468
469 case 0:
470 switch(*ptr.p8++) {
471 case DW_CFA_nop:
472 break;
473 case DW_CFA_set_loc:
474 if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
475 result = 0;
476 break;
477 case DW_CFA_advance_loc1:
478 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
479 break;
480 case DW_CFA_advance_loc2:
481 result = ptr.p8 <= end + 2
482 && advance_loc(*ptr.p16++, state);
483 break;
484 case DW_CFA_advance_loc4:
485 result = ptr.p8 <= end + 4
486 && advance_loc(*ptr.p32++, state);
487 break;
488 case DW_CFA_offset_extended:
489 value = get_uleb128(&ptr.p8, end);
490 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
491 break;
492 case DW_CFA_val_offset:
493 value = get_uleb128(&ptr.p8, end);
494 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
495 break;
496 case DW_CFA_offset_extended_sf:
497 value = get_uleb128(&ptr.p8, end);
498 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
499 break;
500 case DW_CFA_val_offset_sf:
501 value = get_uleb128(&ptr.p8, end);
502 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
503 break;
504 case DW_CFA_restore_extended:
505 case DW_CFA_undefined:
506 case DW_CFA_same_value:
507 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
508 break;
509 case DW_CFA_register:
510 value = get_uleb128(&ptr.p8, end);
511 set_rule(value,
512 Register,
513 get_uleb128(&ptr.p8, end), state);
514 break;
515 case DW_CFA_remember_state:
516 if (ptr.p8 == state->label) {
517 state->label = NULL;
518 return 1;
519 }
520 if (state->stackDepth >= MAX_STACK_DEPTH)
521 return 0;
522 state->stack[state->stackDepth++] = ptr.p8;
523 break;
524 case DW_CFA_restore_state:
525 if (state->stackDepth) {
526 const uleb128_t loc = state->loc;
527 const u8 *label = state->label;
528
529 state->label = state->stack[state->stackDepth - 1];
530 memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
531 memset(state->regs, 0, sizeof(state->regs));
532 state->stackDepth = 0;
533 result = processCFI(start, end, 0, ptrType, state);
534 state->loc = loc;
535 state->label = label;
536 } else
537 return 0;
538 break;
539 case DW_CFA_def_cfa:
540 state->cfa.reg = get_uleb128(&ptr.p8, end);
541 /*nobreak*/
542 case DW_CFA_def_cfa_offset:
543 state->cfa.offs = get_uleb128(&ptr.p8, end);
544 break;
545 case DW_CFA_def_cfa_sf:
546 state->cfa.reg = get_uleb128(&ptr.p8, end);
547 /*nobreak*/
548 case DW_CFA_def_cfa_offset_sf:
549 state->cfa.offs = get_sleb128(&ptr.p8, end)
550 * state->dataAlign;
551 break;
552 case DW_CFA_def_cfa_register:
553 state->cfa.reg = get_uleb128(&ptr.p8, end);
554 break;
555 /*todo case DW_CFA_def_cfa_expression: */
556 /*todo case DW_CFA_expression: */
557 /*todo case DW_CFA_val_expression: */
558 case DW_CFA_GNU_args_size:
559 get_uleb128(&ptr.p8, end);
560 break;
561 case DW_CFA_GNU_negative_offset_extended:
562 value = get_uleb128(&ptr.p8, end);
563 set_rule(value,
564 Memory,
565 (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
566 break;
567 case DW_CFA_GNU_window_save:
568 default:
569 result = 0;
570 break;
571 }
572 break;
573 case 1:
574 result = advance_loc(*ptr.p8++ & 0x3f, state);
575 break;
576 case 2:
577 value = *ptr.p8++ & 0x3f;
578 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
579 break;
580 case 3:
581 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
582 break;
583 }
584 if (ptr.p8 > end)
585 result = 0;
586 if (result && targetLoc != 0 && targetLoc < state->loc)
587 return 1;
588 }
589
590 return result
591 && ptr.p8 == end
592 && (targetLoc == 0
593 || (/*todo While in theory this should apply, gcc in practice omits
594 everything past the function prolog, and hence the location
595 never reaches the end of the function.
596 targetLoc < state->loc &&*/ state->label == NULL));
597 }
598
599 /* Unwind to previous to frame. Returns 0 if successful, negative
600 * number in case of an error. */
601 int unwind(struct unwind_frame_info *frame)
602 {
603 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
604 const u32 *fde = NULL, *cie = NULL;
605 const u8 *ptr = NULL, *end = NULL;
606 unsigned long pc = UNW_PC(frame) - frame->call_frame;
607 unsigned long startLoc = 0, endLoc = 0, cfa;
608 unsigned i;
609 signed ptrType = -1;
610 uleb128_t retAddrReg = 0;
611 struct unwind_table *table;
612 struct unwind_state state;
613
614 if (UNW_PC(frame) == 0)
615 return -EINVAL;
616 if ((table = find_table(pc)) != NULL
617 && !(table->size & (sizeof(*fde) - 1))) {
618 unsigned long tableSize = table->size;
619
620 for (fde = table->address;
621 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
622 tableSize -= sizeof(*fde) + *fde,
623 fde += 1 + *fde / sizeof(*fde)) {
624 if (!*fde || (*fde & (sizeof(*fde) - 1)))
625 break;
626 if (!fde[1])
627 continue; /* this is a CIE */
628 if ((fde[1] & (sizeof(*fde) - 1))
629 || fde[1] > (unsigned long)(fde + 1)
630 - (unsigned long)table->address)
631 continue; /* this is not a valid FDE */
632 cie = fde + 1 - fde[1] / sizeof(*fde);
633 if (*cie <= sizeof(*cie) + 4
634 || *cie >= fde[1] - sizeof(*fde)
635 || (*cie & (sizeof(*cie) - 1))
636 || cie[1]
637 || (ptrType = fde_pointer_type(cie)) < 0) {
638 cie = NULL; /* this is not a (valid) CIE */
639 continue;
640 }
641 ptr = (const u8 *)(fde + 2);
642 startLoc = read_pointer(&ptr,
643 (const u8 *)(fde + 1) + *fde,
644 ptrType);
645 endLoc = startLoc
646 + read_pointer(&ptr,
647 (const u8 *)(fde + 1) + *fde,
648 ptrType & DW_EH_PE_indirect
649 ? ptrType
650 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
651 if (pc >= startLoc && pc < endLoc)
652 break;
653 cie = NULL;
654 }
655 }
656 if (cie != NULL) {
657 memset(&state, 0, sizeof(state));
658 state.cieEnd = ptr; /* keep here temporarily */
659 ptr = (const u8 *)(cie + 2);
660 end = (const u8 *)(cie + 1) + *cie;
661 frame->call_frame = 1;
662 if ((state.version = *ptr) != 1)
663 cie = NULL; /* unsupported version */
664 else if (*++ptr) {
665 /* check if augmentation size is first (and thus present) */
666 if (*ptr == 'z') {
667 while (++ptr < end && *ptr) {
668 switch(*ptr) {
669 /* check for ignorable (or already handled)
670 * nul-terminated augmentation string */
671 case 'L':
672 case 'P':
673 case 'R':
674 continue;
675 case 'S':
676 frame->call_frame = 0;
677 continue;
678 default:
679 break;
680 }
681 break;
682 }
683 }
684 if (ptr >= end || *ptr)
685 cie = NULL;
686 }
687 ++ptr;
688 }
689 if (cie != NULL) {
690 /* get code aligment factor */
691 state.codeAlign = get_uleb128(&ptr, end);
692 /* get data aligment factor */
693 state.dataAlign = get_sleb128(&ptr, end);
694 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
695 cie = NULL;
696 else {
697 retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
698 /* skip augmentation */
699 if (((const char *)(cie + 2))[1] == 'z')
700 ptr += get_uleb128(&ptr, end);
701 if (ptr > end
702 || retAddrReg >= ARRAY_SIZE(reg_info)
703 || REG_INVALID(retAddrReg)
704 || reg_info[retAddrReg].width != sizeof(unsigned long))
705 cie = NULL;
706 }
707 }
708 if (cie != NULL) {
709 state.cieStart = ptr;
710 ptr = state.cieEnd;
711 state.cieEnd = end;
712 end = (const u8 *)(fde + 1) + *fde;
713 /* skip augmentation */
714 if (((const char *)(cie + 2))[1] == 'z') {
715 uleb128_t augSize = get_uleb128(&ptr, end);
716
717 if ((ptr += augSize) > end)
718 fde = NULL;
719 }
720 }
721 if (cie == NULL || fde == NULL) {
722 #ifdef CONFIG_FRAME_POINTER
723 unsigned long top, bottom;
724 #endif
725
726 #ifdef CONFIG_FRAME_POINTER
727 top = STACK_TOP(frame->task);
728 bottom = STACK_BOTTOM(frame->task);
729 # if FRAME_RETADDR_OFFSET < 0
730 if (UNW_SP(frame) < top
731 && UNW_FP(frame) <= UNW_SP(frame)
732 && bottom < UNW_FP(frame)
733 # else
734 if (UNW_SP(frame) > top
735 && UNW_FP(frame) >= UNW_SP(frame)
736 && bottom > UNW_FP(frame)
737 # endif
738 && !((UNW_SP(frame) | UNW_FP(frame))
739 & (sizeof(unsigned long) - 1))) {
740 unsigned long link;
741
742 if (!__get_user(link,
743 (unsigned long *)(UNW_FP(frame)
744 + FRAME_LINK_OFFSET))
745 # if FRAME_RETADDR_OFFSET < 0
746 && link > bottom && link < UNW_FP(frame)
747 # else
748 && link > UNW_FP(frame) && link < bottom
749 # endif
750 && !(link & (sizeof(link) - 1))
751 && !__get_user(UNW_PC(frame),
752 (unsigned long *)(UNW_FP(frame)
753 + FRAME_RETADDR_OFFSET))) {
754 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
755 # if FRAME_RETADDR_OFFSET < 0
756 -
757 # else
758 +
759 # endif
760 sizeof(UNW_PC(frame));
761 UNW_FP(frame) = link;
762 return 0;
763 }
764 }
765 #endif
766 return -ENXIO;
767 }
768 state.org = startLoc;
769 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
770 /* process instructions */
771 if (!processCFI(ptr, end, pc, ptrType, &state)
772 || state.loc > endLoc
773 || state.regs[retAddrReg].where == Nowhere
774 || state.cfa.reg >= ARRAY_SIZE(reg_info)
775 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
776 || state.cfa.offs % sizeof(unsigned long))
777 return -EIO;
778 /* update frame */
779 #ifndef CONFIG_AS_CFI_SIGNAL_FRAME
780 if(frame->call_frame
781 && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
782 frame->call_frame = 0;
783 #endif
784 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
785 startLoc = min((unsigned long)UNW_SP(frame), cfa);
786 endLoc = max((unsigned long)UNW_SP(frame), cfa);
787 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
788 startLoc = min(STACK_LIMIT(cfa), cfa);
789 endLoc = max(STACK_LIMIT(cfa), cfa);
790 }
791 #ifndef CONFIG_64BIT
792 # define CASES CASE(8); CASE(16); CASE(32)
793 #else
794 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
795 #endif
796 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
797 if (REG_INVALID(i)) {
798 if (state.regs[i].where == Nowhere)
799 continue;
800 return -EIO;
801 }
802 switch(state.regs[i].where) {
803 default:
804 break;
805 case Register:
806 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
807 || REG_INVALID(state.regs[i].value)
808 || reg_info[i].width > reg_info[state.regs[i].value].width)
809 return -EIO;
810 switch(reg_info[state.regs[i].value].width) {
811 #define CASE(n) \
812 case sizeof(u##n): \
813 state.regs[i].value = FRAME_REG(state.regs[i].value, \
814 const u##n); \
815 break
816 CASES;
817 #undef CASE
818 default:
819 return -EIO;
820 }
821 break;
822 }
823 }
824 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
825 if (REG_INVALID(i))
826 continue;
827 switch(state.regs[i].where) {
828 case Nowhere:
829 if (reg_info[i].width != sizeof(UNW_SP(frame))
830 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
831 != &UNW_SP(frame))
832 continue;
833 UNW_SP(frame) = cfa;
834 break;
835 case Register:
836 switch(reg_info[i].width) {
837 #define CASE(n) case sizeof(u##n): \
838 FRAME_REG(i, u##n) = state.regs[i].value; \
839 break
840 CASES;
841 #undef CASE
842 default:
843 return -EIO;
844 }
845 break;
846 case Value:
847 if (reg_info[i].width != sizeof(unsigned long))
848 return -EIO;
849 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
850 * state.dataAlign;
851 break;
852 case Memory: {
853 unsigned long addr = cfa + state.regs[i].value
854 * state.dataAlign;
855
856 if ((state.regs[i].value * state.dataAlign)
857 % sizeof(unsigned long)
858 || addr < startLoc
859 || addr + sizeof(unsigned long) < addr
860 || addr + sizeof(unsigned long) > endLoc)
861 return -EIO;
862 switch(reg_info[i].width) {
863 #define CASE(n) case sizeof(u##n): \
864 __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
865 break
866 CASES;
867 #undef CASE
868 default:
869 return -EIO;
870 }
871 }
872 break;
873 }
874 }
875
876 return 0;
877 #undef CASES
878 #undef FRAME_REG
879 }
880 EXPORT_SYMBOL(unwind);
881
882 int unwind_init_frame_info(struct unwind_frame_info *info,
883 struct task_struct *tsk,
884 /*const*/ struct pt_regs *regs)
885 {
886 info->task = tsk;
887 info->call_frame = 0;
888 arch_unw_init_frame_info(info, regs);
889
890 return 0;
891 }
892 EXPORT_SYMBOL(unwind_init_frame_info);
893
894 /*
895 * Prepare to unwind a blocked task.
896 */
897 int unwind_init_blocked(struct unwind_frame_info *info,
898 struct task_struct *tsk)
899 {
900 info->task = tsk;
901 info->call_frame = 0;
902 arch_unw_init_blocked(info);
903
904 return 0;
905 }
906 EXPORT_SYMBOL(unwind_init_blocked);
907
908 /*
909 * Prepare to unwind the currently running thread.
910 */
911 int unwind_init_running(struct unwind_frame_info *info,
912 asmlinkage int (*callback)(struct unwind_frame_info *,
913 void *arg),
914 void *arg)
915 {
916 info->task = current;
917 info->call_frame = 0;
918
919 return arch_unwind_init_running(info, callback, arg);
920 }
921 EXPORT_SYMBOL(unwind_init_running);
922
923 /*
924 * Unwind until the return pointer is in user-land (or until an error
925 * occurs). Returns 0 if successful, negative number in case of
926 * error.
927 */
928 int unwind_to_user(struct unwind_frame_info *info)
929 {
930 while (!arch_unw_user_mode(info)) {
931 int err = unwind(info);
932
933 if (err < 0)
934 return err;
935 }
936
937 return 0;
938 }
939 EXPORT_SYMBOL(unwind_to_user);
This page took 0.058892 seconds and 6 git commands to generate.