2 * arch/i386/kernel/stacktrace.c
4 * Stack trace management functions
6 * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
8 #include <linux/sched.h>
9 #include <linux/stacktrace.h>
11 static inline int valid_stack_ptr(struct thread_info
*tinfo
, void *p
)
13 return p
> (void *)tinfo
&&
14 p
< (void *)tinfo
+ THREAD_SIZE
- 3;
18 * Save stack-backtrace addresses into a stack_trace buffer:
20 static inline unsigned long
21 save_context_stack(struct stack_trace
*trace
, unsigned int skip
,
22 struct thread_info
*tinfo
, unsigned long *stack
,
27 #ifdef CONFIG_FRAME_POINTER
28 while (valid_stack_ptr(tinfo
, (void *)ebp
)) {
29 addr
= *(unsigned long *)(ebp
+ 4);
31 trace
->entries
[trace
->nr_entries
++] = addr
;
34 if (trace
->nr_entries
>= trace
->max_entries
)
37 * break out of recursive entries (such as
38 * end_of_stack_stop_unwind_function):
40 if (ebp
== *(unsigned long *)ebp
)
43 ebp
= *(unsigned long *)ebp
;
46 while (valid_stack_ptr(tinfo
, stack
)) {
48 if (__kernel_text_address(addr
)) {
50 trace
->entries
[trace
->nr_entries
++] = addr
;
53 if (trace
->nr_entries
>= trace
->max_entries
)
63 * Save stack-backtrace addresses into a stack_trace buffer.
64 * If all_contexts is set, all contexts (hardirq, softirq and process)
65 * are saved. If not set then only the current context is saved.
67 void save_stack_trace(struct stack_trace
*trace
,
68 struct task_struct
*task
, int all_contexts
,
72 unsigned long *stack
= &ebp
;
74 WARN_ON(trace
->nr_entries
|| !trace
->max_entries
);
76 if (!task
|| task
== current
) {
77 /* Grab ebp right from our regs: */
78 asm ("movl %%ebp, %0" : "=r" (ebp
));
80 /* ebp is the last reg pushed by switch_to(): */
81 ebp
= *(unsigned long *) task
->thread
.esp
;
85 struct thread_info
*context
= (struct thread_info
*)
86 ((unsigned long)stack
& (~(THREAD_SIZE
- 1)));
88 ebp
= save_context_stack(trace
, skip
, context
, stack
, ebp
);
89 stack
= (unsigned long *)context
->previous_esp
;
90 if (!all_contexts
|| !stack
||
91 trace
->nr_entries
>= trace
->max_entries
)
93 trace
->entries
[trace
->nr_entries
++] = ULONG_MAX
;
94 if (trace
->nr_entries
>= trace
->max_entries
)