1970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#ifndef _ASM_UML_STACKTRACE_H
2970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#define _ASM_UML_STACKTRACE_H
3970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
4970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#include <linux/uaccess.h>
5970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#include <linux/ptrace.h>
6970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
7970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterstruct stack_frame {
8970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	struct stack_frame *next_frame;
9970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	unsigned long return_address;
10970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter};
11970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
12970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterstruct stacktrace_ops {
13970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	void (*address)(void *data, unsigned long address, int reliable);
14970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter};
15970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
16970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#ifdef CONFIG_FRAME_POINTER
17970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterstatic inline unsigned long
18970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterget_frame_pointer(struct task_struct *task, struct pt_regs *segv_regs)
19970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter{
20970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	if (!task || task == current)
21970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter		return segv_regs ? PT_REGS_BP(segv_regs) : current_bp();
22970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	return KSTK_EBP(task);
23970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter}
24970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#else
25970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterstatic inline unsigned long
26970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterget_frame_pointer(struct task_struct *task, struct pt_regs *segv_regs)
27970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter{
28970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	return 0;
29970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter}
30970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#endif
31970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
32970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walterstatic inline unsigned long
33970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter*get_stack_pointer(struct task_struct *task, struct pt_regs *segv_regs)
34970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter{
35970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	if (!task || task == current)
36970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter		return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp();
37970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter	return (unsigned long *)KSTK_ESP(task);
38970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter}
39970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
40970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Waltervoid dump_trace(struct task_struct *tsk, const struct stacktrace_ops *ops, void *data);
41970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter
42970e51feaddbc33ed0e7d187af7f69d1a12c7b6aDaniel Walter#endif /* _ASM_UML_STACKTRACE_H */
43