1c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker/*
2c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker *  Copyright (C) 1991, 1992  Linus Torvalds
3c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker */
5c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
61965aae3c98397aad957412413c07e97b1bd4e64H. Peter Anvin#ifndef _ASM_X86_STACKTRACE_H
71965aae3c98397aad957412413c07e97b1bd4e64H. Peter Anvin#define _ASM_X86_STACKTRACE_H
8c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen
9c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#include <linux/uaccess.h>
109c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen#include <linux/ptrace.h>
11c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
120741f4d207a644482d7a040f05cd264c98cf7ee8Chuck Ebbertextern int kstack_depth_to_print;
130741f4d207a644482d7a040f05cd264c98cf7ee8Chuck Ebbert
1461c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbeckerstruct thread_info;
1561c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbeckerstruct stacktrace_ops;
1661c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker
1761c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbeckertypedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
1861c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      unsigned long *stack,
1961c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      unsigned long bp,
2061c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      const struct stacktrace_ops *ops,
2161c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      void *data,
2261c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      unsigned long *end,
2361c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker				      int *graph);
2461c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker
2561c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbeckerextern unsigned long
2661c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbeckerprint_context_stack(struct thread_info *tinfo,
2761c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker		    unsigned long *stack, unsigned long bp,
2861c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker		    const struct stacktrace_ops *ops, void *data,
2961c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker		    unsigned long *end, int *graph);
3061c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker
3106d65bda75341485d32f33da474b0664819ad497Frederic Weisbeckerextern unsigned long
3206d65bda75341485d32f33da474b0664819ad497Frederic Weisbeckerprint_context_stack_bp(struct thread_info *tinfo,
3306d65bda75341485d32f33da474b0664819ad497Frederic Weisbecker		       unsigned long *stack, unsigned long bp,
3406d65bda75341485d32f33da474b0664819ad497Frederic Weisbecker		       const struct stacktrace_ops *ops, void *data,
3506d65bda75341485d32f33da474b0664819ad497Frederic Weisbecker		       unsigned long *end, int *graph);
3606d65bda75341485d32f33da474b0664819ad497Frederic Weisbecker
37c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen/* Generic stack tracer with callbacks */
38c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen
39c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleenstruct stacktrace_ops {
40bc850d6b374fffd08336996f4b4d3bbd6bf427f6Arjan van de Ven	void (*address)(void *data, unsigned long address, int reliable);
41c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen	/* On negative return stop dumping */
42c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen	int (*stack)(void *data, char *name);
4361c1917f47f73c968e92d04d15370b1dc3ec4592Frederic Weisbecker	walk_stack_t	walk_stack;
44c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen};
45c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen
46bc850d6b374fffd08336996f4b4d3bbd6bf427f6Arjan van de Venvoid dump_trace(struct task_struct *tsk, struct pt_regs *regs,
47e8e999cf3cc733482e390b02ff25a64cecdc0b64Namhyung Kim		unsigned long *stack, unsigned long bp,
489689ba8ad0dc27c0a2ce40eb4c0f8fb66551119cJan Beulich		const struct stacktrace_ops *ops, void *data);
49c0b766f13d8e1189ce4d00e54700c9d96b543b9aAndi Kleen
50c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#ifdef CONFIG_X86_32
51c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#define STACKSLOTS_PER_LINE 8
52c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
53c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#else
54c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#define STACKSLOTS_PER_LINE 4
55c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
56c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#endif
57c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
589c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen#ifdef CONFIG_FRAME_POINTER
599c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersenstatic inline unsigned long
609c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersenstack_frame(struct task_struct *task, struct pt_regs *regs)
619c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen{
629c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	unsigned long bp;
639c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen
649c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	if (regs)
659c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen		return regs->bp;
669c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen
679c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	if (task == current) {
689c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen		/* Grab bp right from our regs */
699c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen		get_bp(bp);
709c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen		return bp;
719c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	}
729c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen
739c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	/* bp is the last reg pushed by switch_to */
749c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	return *(unsigned long *)task->thread.sp;
759c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen}
769c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen#else
779c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersenstatic inline unsigned long
789c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersenstack_frame(struct task_struct *task, struct pt_regs *regs)
799c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen{
809c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen	return 0;
819c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen}
829c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen#endif
839c0729dc8062bed96189bd14ac6d4920f3958743Soeren Sandmann Pedersen
84c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckerextern void
85c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckershow_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
86e8e999cf3cc733482e390b02ff25a64cecdc0b64Namhyung Kim		   unsigned long *stack, unsigned long bp, char *log_lvl);
87c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
88c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckerextern void
89c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckershow_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
90e8e999cf3cc733482e390b02ff25a64cecdc0b64Namhyung Kim		   unsigned long *sp, unsigned long bp, char *log_lvl);
91c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
92c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckerextern unsigned int code_bytes;
93c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
94c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker/* The form of the top of the frame on the stack */
95c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckerstruct stack_frame {
96c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker	struct stack_frame *next_frame;
97c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker	unsigned long return_address;
98c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker};
99c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
100c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbeckerstruct stack_frame_ia32 {
101c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker    u32 next_frame;
102c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker    u32 return_address;
103c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker};
104c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
105b0f82b81fe6bbcf78d478071f33e44554726bc81Frederic Weisbeckerstatic inline unsigned long caller_frame_pointer(void)
106c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker{
107c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker	struct stack_frame *frame;
108c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
109c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker	get_bp(frame);
110c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
111c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#ifdef CONFIG_FRAME_POINTER
112b0f82b81fe6bbcf78d478071f33e44554726bc81Frederic Weisbecker	frame = frame->next_frame;
113c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker#endif
114c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
115c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker	return (unsigned long)frame;
116c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker}
117c9cf4dbb4d9ca715d8fedf13301a53296429abc6Frederic Weisbecker
1181965aae3c98397aad957412413c07e97b1bd4e64H. Peter Anvin#endif /* _ASM_X86_STACKTRACE_H */
119