1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
28637c099SIngo Molnar #ifndef __LINUX_STACKTRACE_H
38637c099SIngo Molnar #define __LINUX_STACKTRACE_H
48637c099SIngo Molnar
59a92a6ceSJoonsoo Kim #include <linux/types.h>
6e9b98e16SThomas Gleixner #include <asm/errno.h>
79a92a6ceSJoonsoo Kim
8897312bdSAndrew Morton struct task_struct;
99c0729dcSSoeren Sandmann Pedersen struct pt_regs;
10897312bdSAndrew Morton
11214d8ca6SThomas Gleixner #ifdef CONFIG_ARCH_STACKWALK
12214d8ca6SThomas Gleixner
13214d8ca6SThomas Gleixner /**
14214d8ca6SThomas Gleixner * stack_trace_consume_fn - Callback for arch_stack_walk()
15214d8ca6SThomas Gleixner * @cookie: Caller supplied pointer handed back by arch_stack_walk()
16214d8ca6SThomas Gleixner * @addr: The stack entry address to consume
17214d8ca6SThomas Gleixner *
18214d8ca6SThomas Gleixner * Return: True, if the entry was consumed or skipped
19214d8ca6SThomas Gleixner * False, if there is no space left to store
20214d8ca6SThomas Gleixner */
21264c03a2SMark Brown typedef bool (*stack_trace_consume_fn)(void *cookie, unsigned long addr);
22214d8ca6SThomas Gleixner /**
23214d8ca6SThomas Gleixner * arch_stack_walk - Architecture specific function to walk the stack
24214d8ca6SThomas Gleixner * @consume_entry: Callback which is invoked by the architecture code for
25214d8ca6SThomas Gleixner * each entry.
26214d8ca6SThomas Gleixner * @cookie: Caller supplied pointer which is handed back to
27214d8ca6SThomas Gleixner * @consume_entry
28214d8ca6SThomas Gleixner * @task: Pointer to a task struct, can be NULL
29214d8ca6SThomas Gleixner * @regs: Pointer to registers, can be NULL
30214d8ca6SThomas Gleixner *
31214d8ca6SThomas Gleixner * ============ ======= ============================================
32214d8ca6SThomas Gleixner * task regs
33214d8ca6SThomas Gleixner * ============ ======= ============================================
34214d8ca6SThomas Gleixner * task NULL Stack trace from task (can be current)
35214d8ca6SThomas Gleixner * current regs Stack trace starting on regs->stackpointer
36214d8ca6SThomas Gleixner * ============ ======= ============================================
37214d8ca6SThomas Gleixner */
38214d8ca6SThomas Gleixner void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
39214d8ca6SThomas Gleixner struct task_struct *task, struct pt_regs *regs);
40b18adee4SMark Brown
41b18adee4SMark Brown /**
42b18adee4SMark Brown * arch_stack_walk_reliable - Architecture specific function to walk the
43b18adee4SMark Brown * stack reliably
44b18adee4SMark Brown *
45b18adee4SMark Brown * @consume_entry: Callback which is invoked by the architecture code for
46b18adee4SMark Brown * each entry.
47b18adee4SMark Brown * @cookie: Caller supplied pointer which is handed back to
48b18adee4SMark Brown * @consume_entry
49b18adee4SMark Brown * @task: Pointer to a task struct, can be NULL
50b18adee4SMark Brown *
51b18adee4SMark Brown * This function returns an error if it detects any unreliable
52b18adee4SMark Brown * features of the stack. Otherwise it guarantees that the stack
53b18adee4SMark Brown * trace is reliable.
54b18adee4SMark Brown *
55b18adee4SMark Brown * If the task is not 'current', the caller *must* ensure the task is
56b18adee4SMark Brown * inactive and its stack is pinned.
57b18adee4SMark Brown */
58214d8ca6SThomas Gleixner int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry, void *cookie,
59214d8ca6SThomas Gleixner struct task_struct *task);
60b18adee4SMark Brown
61214d8ca6SThomas Gleixner void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
62214d8ca6SThomas Gleixner const struct pt_regs *regs);
63*1614b2b1SPeter Zijlstra #endif /* CONFIG_ARCH_STACKWALK */
64214d8ca6SThomas Gleixner
65*1614b2b1SPeter Zijlstra #ifdef CONFIG_STACKTRACE
66*1614b2b1SPeter Zijlstra void stack_trace_print(const unsigned long *trace, unsigned int nr_entries,
67*1614b2b1SPeter Zijlstra int spaces);
68*1614b2b1SPeter Zijlstra int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
69*1614b2b1SPeter Zijlstra unsigned int nr_entries, int spaces);
70*1614b2b1SPeter Zijlstra unsigned int stack_trace_save(unsigned long *store, unsigned int size,
71*1614b2b1SPeter Zijlstra unsigned int skipnr);
72*1614b2b1SPeter Zijlstra unsigned int stack_trace_save_tsk(struct task_struct *task,
73*1614b2b1SPeter Zijlstra unsigned long *store, unsigned int size,
74*1614b2b1SPeter Zijlstra unsigned int skipnr);
75*1614b2b1SPeter Zijlstra unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
76*1614b2b1SPeter Zijlstra unsigned int size, unsigned int skipnr);
77*1614b2b1SPeter Zijlstra unsigned int stack_trace_save_user(unsigned long *store, unsigned int size);
78*1614b2b1SPeter Zijlstra unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries);
79*1614b2b1SPeter Zijlstra
80*1614b2b1SPeter Zijlstra #ifndef CONFIG_ARCH_STACKWALK
81*1614b2b1SPeter Zijlstra /* Internal interfaces. Do not use in generic code */
828637c099SIngo Molnar struct stack_trace {
838637c099SIngo Molnar unsigned int nr_entries, max_entries;
848637c099SIngo Molnar unsigned long *entries;
852c34f6f7SWalter Wu unsigned int skip; /* input argument: How many entries to skip */
868637c099SIngo Molnar };
878637c099SIngo Molnar
88ab1b6f03SChristoph Hellwig extern void save_stack_trace(struct stack_trace *trace);
8939581062SMasami Hiramatsu extern void save_stack_trace_regs(struct pt_regs *regs,
9039581062SMasami Hiramatsu struct stack_trace *trace);
919745512cSArjan van de Ven extern void save_stack_trace_tsk(struct task_struct *tsk,
929745512cSArjan van de Ven struct stack_trace *trace);
93af085d90SJosh Poimboeuf extern int save_stack_trace_tsk_reliable(struct task_struct *tsk,
94af085d90SJosh Poimboeuf struct stack_trace *trace);
9502b67518STörök Edwin extern void save_stack_trace_user(struct stack_trace *trace);
96214d8ca6SThomas Gleixner #endif /* !CONFIG_ARCH_STACKWALK */
97af085d90SJosh Poimboeuf #endif /* CONFIG_STACKTRACE */
988637c099SIngo Molnar
99e9b98e16SThomas Gleixner #if defined(CONFIG_STACKTRACE) && defined(CONFIG_HAVE_RELIABLE_STACKTRACE)
100e9b98e16SThomas Gleixner int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
101e9b98e16SThomas Gleixner unsigned int size);
102e9b98e16SThomas Gleixner #else
stack_trace_save_tsk_reliable(struct task_struct * tsk,unsigned long * store,unsigned int size)103e9b98e16SThomas Gleixner static inline int stack_trace_save_tsk_reliable(struct task_struct *tsk,
104e9b98e16SThomas Gleixner unsigned long *store,
105e9b98e16SThomas Gleixner unsigned int size)
106e9b98e16SThomas Gleixner {
107e9b98e16SThomas Gleixner return -ENOSYS;
108e9b98e16SThomas Gleixner }
109e9b98e16SThomas Gleixner #endif
110e9b98e16SThomas Gleixner
111af085d90SJosh Poimboeuf #endif /* __LINUX_STACKTRACE_H */
112