Skip to content

Commit 3683f44

Browse files
author
Russell King
committed
ARM: stacktrace: avoid listing stacktrace functions in stacktrace
While debugging the FEC ethernet driver using stacktrace, it was noticed that the stacktraces always begin as follows: [<c00117b4>] save_stack_trace_tsk+0x0/0x98 [<c0011870>] 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. Cc: <stable@vger.kernel.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
1 parent deace4a commit 3683f44

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

arch/arm/kernel/stacktrace.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ static int save_trace(struct stackframe *frame, void *d)
8383
return trace->nr_entries >= trace->max_entries;
8484
}
8585

86-
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
86+
/* This must be noinline to so that our skip calculation works correctly */
87+
static noinline void __save_stack_trace(struct task_struct *tsk,
88+
struct stack_trace *trace, unsigned int nosched)
8789
{
8890
struct stack_trace_data data;
8991
struct stackframe frame;
9092

9193
data.trace = trace;
9294
data.skip = trace->skip;
95+
data.no_sched_functions = nosched;
9396

9497
if (tsk != current) {
9598
#ifdef CONFIG_SMP
@@ -102,7 +105,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
102105
trace->entries[trace->nr_entries++] = ULONG_MAX;
103106
return;
104107
#else
105-
data.no_sched_functions = 1;
106108
frame.fp = thread_saved_fp(tsk);
107109
frame.sp = thread_saved_sp(tsk);
108110
frame.lr = 0; /* recovered from the stack */
@@ -111,21 +113,27 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
111113
} else {
112114
register unsigned long current_sp asm ("sp");
113115

114-
data.no_sched_functions = 0;
116+
/* We don't want this function nor the caller */
117+
data.skip += 2;
115118
frame.fp = (unsigned long)__builtin_frame_address(0);
116119
frame.sp = current_sp;
117120
frame.lr = (unsigned long)__builtin_return_address(0);
118-
frame.pc = (unsigned long)save_stack_trace_tsk;
121+
frame.pc = (unsigned long)__save_stack_trace;
119122
}
120123

121124
walk_stackframe(&frame, save_trace, &data);
122125
if (trace->nr_entries < trace->max_entries)
123126
trace->entries[trace->nr_entries++] = ULONG_MAX;
124127
}
125128

129+
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
130+
{
131+
__save_stack_trace(tsk, trace, 1);
132+
}
133+
126134
void save_stack_trace(struct stack_trace *trace)
127135
{
128-
save_stack_trace_tsk(current, trace);
136+
__save_stack_trace(current, trace, 0);
129137
}
130138
EXPORT_SYMBOL_GPL(save_stack_trace);
131139
#endif

0 commit comments

Comments
 (0)