xref: /openbmc/linux/include/linux/stacktrace.h (revision 1614b2b1)
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