Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61c1917f authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Ingo Molnar
Browse files

perf events, x86/stacktrace: Make stack walking optional



The current print_context_stack helper that does the stack
walking job is good for usual stacktraces as it walks through
all the stack and reports even addresses that look unreliable,
which is nice when we don't have frame pointers for example.

But we have users like perf that only require reliable
stacktraces, and those may want a more adapted stack walker, so
lets make this function a callback in stacktrace_ops that users
can tune for their needs.

Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1261024834-5336-1-git-send-regression-fweisbec@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 5b74ed47
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -5,6 +5,23 @@ extern int kstack_depth_to_print;

int x86_is_stack_id(int id, char *name);

struct thread_info;
struct stacktrace_ops;

typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
				      unsigned long *stack,
				      unsigned long bp,
				      const struct stacktrace_ops *ops,
				      void *data,
				      unsigned long *end,
				      int *graph);

extern unsigned long
print_context_stack(struct thread_info *tinfo,
		    unsigned long *stack, unsigned long bp,
		    const struct stacktrace_ops *ops, void *data,
		    unsigned long *end, int *graph);

/* Generic stack tracer with callbacks */

struct stacktrace_ops {
@@ -14,6 +31,7 @@ struct stacktrace_ops {
	void (*address)(void *data, unsigned long address, int reliable);
	/* On negative return stop dumping */
	int (*stack)(void *data, char *name);
	walk_stack_t	walk_stack;
};

void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+1 −0
Original line number Diff line number Diff line
@@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = {
	.warning_symbol		= backtrace_warning_symbol,
	.stack			= backtrace_stack,
	.address		= backtrace_address,
	.walk_stack		= print_context_stack,
};

#include "../dumpstack.h"
+5 −4
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ static const struct stacktrace_ops print_trace_ops = {
	.warning_symbol		= print_trace_warning_symbol,
	.stack 			= print_trace_stack,
	.address 		= print_trace_address,
	.walk_stack		= print_context_stack,
};

void
+0 −6
Original line number Diff line number Diff line
@@ -14,12 +14,6 @@
#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
#endif

extern unsigned long
print_context_stack(struct thread_info *tinfo,
		unsigned long *stack, unsigned long bp,
		const struct stacktrace_ops *ops, void *data,
		unsigned long *end, int *graph);

extern void
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
		unsigned long *stack, unsigned long bp, char *log_lvl);
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,

		context = (struct thread_info *)
			((unsigned long)stack & (~(THREAD_SIZE - 1)));
		bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph);
		bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);

		stack = (unsigned long *)context->previous_esp;
		if (!stack)
Loading