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)
34 unsigned offs
:BITS_PER_LONG
/ 2;
35 unsigned width
:BITS_PER_LONG
/ 2;
44 #define REG_INVALID(r) (reg_info[r].width == 0)
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
{
103 struct unwind_table
*link
;
105 } root_table
, *last_table
;
117 struct unwind_state
{
119 const u8
*cieStart
, *cieEnd
;
125 struct unwind_item regs
[ARRAY_SIZE(reg_info
)];
126 unsigned stackDepth
:8;
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
))
148 static void init_unwind_table(struct unwind_table
*table
,
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
;
167 void __init
unwind_init(void)
169 init_unwind_table(&root_table
, "kernel",
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
;
185 table
= kmalloc(sizeof(*table
), GFP_KERNEL
);
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
);
195 last_table
->link
= table
;
197 root_table
.link
= table
;
203 struct unlink_table_info
205 struct unwind_table
*table
;
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
)
218 if (info
->init_only
) {
220 table
->init
.range
= 0;
223 prev
->link
= table
->link
;
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
)
242 if (init_only
&& table
== last_table
) {
244 table
->init
.range
= 0;
249 info
.init_only
= init_only
;
250 stop_machine_run(unlink_table
, &info
, NR_CPUS
);
256 static uleb128_t
get_uleb128(const u8
**pcur
, const u8
*end
)
258 const u8
*cur
= *pcur
;
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
))) {
268 value
|= (uleb128_t
)(*cur
& 0x7f) << shift
;
269 if (!(*cur
++ & 0x80))
277 static sleb128_t
get_sleb128(const u8
**pcur
, const u8
*end
)
279 const u8
*cur
= *pcur
;
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
))) {
289 value
|= (sleb128_t
)(*cur
& 0x7f) << shift
;
290 if (!(*cur
& 0x80)) {
291 value
|= -(*cur
++ & 0x40) << shift
;
300 static unsigned long read_pointer(const u8
**pLoc
,
304 unsigned long value
= 0;
311 const unsigned long *pul
;
314 if (ptrType
< 0 || ptrType
== DW_EH_PE_omit
)
317 switch(ptrType
& DW_EH_PE_FORM
) {
319 if (end
< (const void *)(ptr
.p16u
+ 1))
321 if(ptrType
& DW_EH_PE_signed
)
322 value
= get_unaligned(ptr
.p16s
++);
324 value
= get_unaligned(ptr
.p16u
++);
328 if (end
< (const void *)(ptr
.p32u
+ 1))
330 if(ptrType
& DW_EH_PE_signed
)
331 value
= get_unaligned(ptr
.p32s
++);
333 value
= get_unaligned(ptr
.p32u
++);
336 BUILD_BUG_ON(sizeof(u64
) != sizeof(value
));
338 BUILD_BUG_ON(sizeof(u32
) != sizeof(value
));
340 case DW_EH_PE_native
:
341 if (end
< (const void *)(ptr
.pul
+ 1))
343 value
= get_unaligned(ptr
.pul
++);
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
)
356 switch(ptrType
& DW_EH_PE_ADJUST
) {
360 value
+= (unsigned long)*pLoc
;
365 if ((ptrType
& DW_EH_PE_indirect
)
366 && __get_user(value
, (unsigned long *)value
))
373 static signed fde_pointer_type(const u32
*cie
)
375 const u8
*ptr
= (const u8
*)(cie
+ 2);
376 unsigned version
= *ptr
;
379 return -1; /* unsupported */
382 const u8
*end
= (const u8
*)(cie
+ 1) + *cie
;
385 /* check if augmentation size is first (and thus present) */
388 /* check if augmentation string is nul-terminated */
389 if ((ptr
= memchr(aug
= (const void *)ptr
, 0, end
- ptr
)) == NULL
)
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
)
408 signed ptrType
= *ptr
++;
410 if (!read_pointer(&ptr
, end
, ptrType
) || ptr
> end
)
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
;
431 static void set_rule(uleb128_t reg
,
432 enum item_location where
,
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
,
444 unsigned long targetLoc
,
446 struct unwind_state
*state
)
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
)
461 for (ptr
.p8
= start
; result
&& ptr
.p8
< end
; ) {
462 switch(*ptr
.p8
>> 6) {
470 if ((state
->loc
= read_pointer(&ptr
.p8
, end
, ptrType
)) == 0)
473 case DW_CFA_advance_loc1
:
474 result
= ptr
.p8
< end
&& advance_loc(*ptr
.p8
++, state
);
476 case DW_CFA_advance_loc2
:
477 result
= ptr
.p8
<= end
+ 2
478 && advance_loc(*ptr
.p16
++, state
);
480 case DW_CFA_advance_loc4
:
481 result
= ptr
.p8
<= end
+ 4
482 && advance_loc(*ptr
.p32
++, state
);
484 case DW_CFA_offset_extended
:
485 value
= get_uleb128(&ptr
.p8
, end
);
486 set_rule(value
, Memory
, get_uleb128(&ptr
.p8
, end
), state
);
488 case DW_CFA_val_offset
:
489 value
= get_uleb128(&ptr
.p8
, end
);
490 set_rule(value
, Value
, get_uleb128(&ptr
.p8
, end
), state
);
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
);
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
);
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
);
505 case DW_CFA_register
:
506 value
= get_uleb128(&ptr
.p8
, end
);
509 get_uleb128(&ptr
.p8
, end
), state
);
511 case DW_CFA_remember_state
:
512 if (ptr
.p8
== state
->label
) {
516 if (state
->stackDepth
>= MAX_STACK_DEPTH
)
518 state
->stack
[state
->stackDepth
++] = ptr
.p8
;
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
);
531 state
->label
= label
;
536 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
538 case DW_CFA_def_cfa_offset
:
539 state
->cfa
.offs
= get_uleb128(&ptr
.p8
, end
);
541 case DW_CFA_def_cfa_sf
:
542 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
544 case DW_CFA_def_cfa_offset_sf
:
545 state
->cfa
.offs
= get_sleb128(&ptr
.p8
, end
)
548 case DW_CFA_def_cfa_register
:
549 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
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
);
557 case DW_CFA_GNU_negative_offset_extended
:
558 value
= get_uleb128(&ptr
.p8
, end
);
561 (uleb128_t
)0 - get_uleb128(&ptr
.p8
, end
), state
);
563 case DW_CFA_GNU_window_save
:
570 result
= advance_loc(*ptr
.p8
++ & 0x3f, state
);
573 value
= *ptr
.p8
++ & 0x3f;
574 set_rule(value
, Memory
, get_uleb128(&ptr
.p8
, end
), state
);
577 set_rule(*ptr
.p8
++ & 0x3f, Nowhere
, 0, state
);
582 if (result
&& targetLoc
!= 0 && targetLoc
< state
->loc
)
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
;
605 uleb128_t retAddrReg
= 0;
606 struct unwind_table
*table
;
607 struct unwind_state state
;
609 if (UNW_PC(frame
) == 0)
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)))
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))
632 || (ptrType
= fde_pointer_type(cie
)) < 0) {
633 cie
= NULL
; /* this is not a (valid) CIE */
636 ptr
= (const u8
*)(fde
+ 2);
637 startLoc
= read_pointer(&ptr
,
638 (const u8
*)(fde
+ 1) + *fde
,
642 (const u8
*)(fde
+ 1) + *fde
,
643 ptrType
& DW_EH_PE_indirect
645 : ptrType
& (DW_EH_PE_FORM
|DW_EH_PE_signed
));
646 if (UNW_PC(frame
) >= startLoc
&& UNW_PC(frame
) < endLoc
)
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 */
659 /* check if augmentation size is first (and thus present) */
661 /* check for ignorable (or already handled)
662 * nul-terminated augmentation string */
663 while (++ptr
< end
&& *ptr
)
664 if (strchr("LPR", *ptr
) == NULL
)
667 if (ptr
>= end
|| *ptr
)
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
)
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
);
685 || retAddrReg
>= ARRAY_SIZE(reg_info
)
686 || REG_INVALID(retAddrReg
)
687 || reg_info
[retAddrReg
].width
!= sizeof(unsigned long))
692 state
.cieStart
= ptr
;
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
)
704 if (cie
== NULL
|| fde
== NULL
) {
705 #ifdef CONFIG_FRAME_POINTER
706 unsigned long top
, bottom
;
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
)
717 if (UNW_SP(frame
) > top
718 && UNW_FP(frame
) >= UNW_SP(frame
)
719 && bottom
> UNW_FP(frame
)
721 && !((UNW_SP(frame
) | UNW_FP(frame
))
722 & (sizeof(unsigned long) - 1))) {
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
)
731 && link
> UNW_FP(frame
) && link
< bottom
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
743 sizeof(UNW_PC(frame
));
744 UNW_FP(frame
) = link
;
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))
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
);
770 # define CASES CASE(8); CASE(16); CASE(32)
772 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
774 for (i
= 0; i
< ARRAY_SIZE(state
.regs
); ++i
) {
775 if (REG_INVALID(i
)) {
776 if (state
.regs
[i
].where
== Nowhere
)
780 switch(state
.regs
[i
].where
) {
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
)
788 switch(reg_info
[state
.regs
[i
].value
].width
) {
791 state.regs[i].value = FRAME_REG(state.regs[i].value, \
802 for (i
= 0; i
< ARRAY_SIZE(state
.regs
); ++i
) {
805 switch(state
.regs
[i
].where
) {
807 if (reg_info
[i
].width
!= sizeof(UNW_SP(frame
))
808 || &FRAME_REG(i
, __typeof__(UNW_SP(frame
)))
814 switch(reg_info
[i
].width
) {
815 #define CASE(n) case sizeof(u##n): \
816 FRAME_REG(i, u##n) = state.regs[i].value; \
825 if (reg_info
[i
].width
!= sizeof(unsigned long))
827 FRAME_REG(i
, unsigned long) = cfa
+ state
.regs
[i
].value
831 unsigned long addr
= cfa
+ state
.regs
[i
].value
834 if ((state
.regs
[i
].value
* state
.dataAlign
)
835 % sizeof(unsigned long)
837 || addr
+ sizeof(unsigned long) < addr
838 || addr
+ sizeof(unsigned long) > endLoc
)
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); \
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
)
865 arch_unw_init_frame_info(info
, regs
);
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
)
878 arch_unw_init_blocked(info
);
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
*,
892 info
->task
= current
;
893 arch_unwind_init_running(info
, callback
, arg
);
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
904 int unwind_to_user(struct unwind_frame_info
*info
)
906 while (!arch_unw_user_mode(info
)) {
907 int err
= unwind(info
);
915 EXPORT_SYMBOL(unwind_to_user
);