From d6bb6d333cc9bb030d27f459c2e6ce1e4a2d0043 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Thu, 7 Sep 2017 10:25:35 +1000 Subject: arm64: stacktrace: avoid listing stacktrace functions in stacktrace The stacktraces always begin as follows: [] save_stack_trace_tsk+0x0/0x98 [] save_stack_trace+0x24/0x28 ... This is because the stack trace code includes the stack frames for itself. This is incorrect behaviour, and also leads to "skip" doing the wrong thing (which is the number of stack frames to avoid recording.) Perversely, it does the right thing when passed a non-current thread. Fix this by ensuring that we have a known constant number of frames above the main stack trace function, and always skip these. This was fixed for arch arm by 3683f44c42e9 ("ARM: stacktrace: avoid listing stacktrace functions in stacktrace") Change-Id: I1a65ee011f022227204b406bb0288828a7beb0b8 Link: http://lkml.kernel.org/r/1504078343-28754-1-git-send-email-guptap@codeaurora.org Cc: Russell King Cc: Michal Hocko Cc: Vlastimil Babka Cc: Will Deacon Cc: Catalin Marinas Cc: Joonsoo Kim Signed-off-by: Andrew Morton Signed-off-by: Stephen Rothwell Git-commit: 457b9ab50babff7100fe7902d195069561bc1db7 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git [guptap@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Prakash Gupta --- arch/arm64/kernel/stacktrace.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index 1fd1a9a6596f..770d64547a6a 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -157,24 +157,26 @@ static int save_trace(struct stackframe *frame, void *d) return trace->nr_entries >= trace->max_entries; } -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +static noinline void __save_stack_trace(struct task_struct *tsk, + struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; + data.no_sched_functions = nosched; if (tsk != current) { - data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.pc = thread_saved_pc(tsk); } else { - data.no_sched_functions = 0; + /* We don't want this function nor the caller */ + data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_stack_pointer; - frame.pc = (unsigned long)save_stack_trace_tsk; + frame.pc = (unsigned long)__save_stack_trace; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = tsk->curr_ret_stack; @@ -186,9 +188,15 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) } EXPORT_SYMBOL(save_stack_trace_tsk); +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + __save_stack_trace(tsk, trace, 1); +} + void save_stack_trace(struct stack_trace *trace) { - save_stack_trace_tsk(current, trace); + __save_stack_trace(current, trace, 0); } + EXPORT_SYMBOL_GPL(save_stack_trace); #endif -- cgit v1.2.3