Skip to content

Commit f7edb45

Browse files
committed
tracing/arm64: Have max stack tracer handle the case of return address after data
Most archs (well at least x86) store the function call return address on the stack before storing the local variables for the function. The max stack tracer depends on this in its algorithm to display the stack size of each function it finds in the back trace. Some archs (arm64), may store the return address (from its link register) just before calling a nested function. There's no reason to save the link register on leaf functions, as it wont be updated. This breaks the algorithm of the max stack tracer. Add a new define ARCH_FTRACE_SHIFT_STACK_TRACER that an architecture may set if it stores the return address (link register) after it stores the function's local variables, and have the stack trace shift the values of the mapped stack size to the appropriate functions. Link: [email protected] Reported-by: Jiping Ma <[email protected]> Acked-by: Will Deacon <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 4fbcf07 commit f7edb45

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

arch/arm64/include/asm/ftrace.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
#define MCOUNT_ADDR ((unsigned long)_mcount)
1515
#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE
1616

17+
/*
18+
* Currently, gcc tends to save the link register after the local variables
19+
* on the stack. This causes the max stack tracer to report the function
20+
* frame sizes for the wrong functions. By defining
21+
* ARCH_FTRACE_SHIFT_STACK_TRACER, it will tell the stack tracer to expect
22+
* to find the return address on the stack after the local variables have
23+
* been set up.
24+
*
25+
* Note, this may change in the future, and we will need to deal with that
26+
* if it were to happen.
27+
*/
28+
#define ARCH_FTRACE_SHIFT_STACK_TRACER 1
29+
1730
#ifndef __ASSEMBLY__
1831
#include <linux/compat.h>
1932

kernel/trace/trace_stack.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,20 @@ static void check_stack(unsigned long ip, unsigned long *stack)
158158
i++;
159159
}
160160

161+
#ifdef ARCH_FTRACE_SHIFT_STACK_TRACER
162+
/*
163+
* Some archs will store the link register before calling
164+
* nested functions. This means the saved return address
165+
* comes after the local storage, and we need to shift
166+
* for that.
167+
*/
168+
if (x > 1) {
169+
memmove(&stack_trace_index[0], &stack_trace_index[1],
170+
sizeof(stack_trace_index[0]) * (x - 1));
171+
x--;
172+
}
173+
#endif
174+
161175
stack_trace_nr_entries = x;
162176

163177
if (task_stack_end_corrupted(current)) {

0 commit comments

Comments
 (0)