Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1730793 > unrolled thread
| Started by | James Morse <james.morse@arm.com> |
|---|---|
| First post | 2017-09-12 12:00 +0200 |
| Last post | 2017-09-13 07:00 +0200 |
| Articles | 3 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH v2] arm64: fix unwind_frame() for filtered out fn for function graph tracing James Morse <james.morse@arm.com> - 2017-09-12 12:00 +0200
Re: [PATCH v2] arm64: fix unwind_frame() for filtered out fn for function graph tracing Will Deacon <will.deacon@arm.com> - 2017-09-13 04:50 +0200
Re: [PATCH v2] arm64: fix unwind_frame() for filtered out fn for function graph tracing Pratyush Anand <panand@redhat.com> - 2017-09-13 07:00 +0200
| From | James Morse <james.morse@arm.com> |
|---|---|
| Date | 2017-09-12 12:00 +0200 |
| Subject | Re: [PATCH v2] arm64: fix unwind_frame() for filtered out fn for function graph tracing |
| Message-ID | <uoQ93-82V-1@gated-at.bofh.it> |
Hi Pratyush,
On 01/09/17 06:48, Pratyush Anand wrote:
> do_task_stat() calls get_wchan(), which further does unbind_frame().
> unbind_frame() restores frame->pc to original value in case function
> graph tracer has modified a return address (LR) in a stack frame to hook
> a function return. However, if function graph tracer has hit a filtered
> function, then we can't unwind it as ftrace_push_return_trace() has
> biased the index(frame->graph) with a 'huge negative'
> offset(-FTRACE_NOTRACE_DEPTH).
>
> Moreover, arm64 stack walker defines index(frame->graph) as unsigned
> int, which can not compare a -ve number.
>
> Similar problem we can have with calling of walk_stackframe() from
> save_stack_trace_tsk() or dump_backtrace().
>
> This patch fixes unwind_frame() to test the index for -ve value and
> restore index accordingly before we can restore frame->pc.
I've just spotted arm64's profile_pc, which does this:
From arch/arm64/kernel/time.c:profile_pc():
> #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> frame.graph = -1; /* no task info */
> #endif
Is this another elaborate way of hitting this problem?
I guess the options are skip any return-address restore in the unwinder if
frame.graph is -1. (and profile_pc may have a bug here). Or, put
current->curr_ret_stack in there.
profile_pc() always passes tsk=NULL, so the unwinder assumes its current...
kernel/profile.c pulls the pt_regs from a per-cpu irq_regs variable, that is
updated by handle_IPI ... so it looks like this should always be current...
Thanks,
James
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 09d37d66b630..4c47147d0554 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -75,6 +75,9 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
> #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> if (tsk->ret_stack &&
> (frame->pc == (unsigned long)return_to_handler)) {
> + if (frame->graph < 0)
> + frame->graph += FTRACE_NOTRACE_DEPTH;
> +
> /*
> * This is a case where function graph tracer has
> * modified a return address (LR) in a stack frame
>
[toc] | [next] | [standalone]
| From | Will Deacon <will.deacon@arm.com> |
|---|---|
| Date | 2017-09-13 04:50 +0200 |
| Message-ID | <up5Ut-1pM-7@gated-at.bofh.it> |
| In reply to | #1730793 |
On Tue, Sep 12, 2017 at 10:54:28AM +0100, James Morse wrote: > Hi Pratyush, > > On 01/09/17 06:48, Pratyush Anand wrote: > > do_task_stat() calls get_wchan(), which further does unbind_frame(). > > unbind_frame() restores frame->pc to original value in case function > > graph tracer has modified a return address (LR) in a stack frame to hook > > a function return. However, if function graph tracer has hit a filtered > > function, then we can't unwind it as ftrace_push_return_trace() has > > biased the index(frame->graph) with a 'huge negative' > > offset(-FTRACE_NOTRACE_DEPTH). > > > > Moreover, arm64 stack walker defines index(frame->graph) as unsigned > > int, which can not compare a -ve number. > > > > Similar problem we can have with calling of walk_stackframe() from > > save_stack_trace_tsk() or dump_backtrace(). > > > > This patch fixes unwind_frame() to test the index for -ve value and > > restore index accordingly before we can restore frame->pc. > > I've just spotted arm64's profile_pc, which does this: > From arch/arm64/kernel/time.c:profile_pc(): > > #ifdef CONFIG_FUNCTION_GRAPH_TRACER > > frame.graph = -1; /* no task info */ > > #endif > > Is this another elaborate way of hitting this problem? > > I guess the options are skip any return-address restore in the unwinder if > frame.graph is -1. (and profile_pc may have a bug here). Or, put > current->curr_ret_stack in there. > > profile_pc() always passes tsk=NULL, so the unwinder assumes its current... > kernel/profile.c pulls the pt_regs from a per-cpu irq_regs variable, that is > updated by handle_IPI ... so it looks like this should always be current... Hmmm... is profile_pc the *only* case where frame->graph isn't equal to tsk->curr_ret_stack in unwind_frame? If so, maybe unwind_frame should just use that, and we could kill the graph member of struct stackframe completely? Will
[toc] | [prev] | [next] | [standalone]
| From | Pratyush Anand <panand@redhat.com> |
|---|---|
| Date | 2017-09-13 07:00 +0200 |
| Message-ID | <up7Wh-2FC-1@gated-at.bofh.it> |
| In reply to | #1731345 |
On Wednesday 13 September 2017 08:12 AM, Will Deacon wrote: > On Tue, Sep 12, 2017 at 10:54:28AM +0100, James Morse wrote: >> Hi Pratyush, >> >> On 01/09/17 06:48, Pratyush Anand wrote: >>> do_task_stat() calls get_wchan(), which further does unbind_frame(). >>> unbind_frame() restores frame->pc to original value in case function >>> graph tracer has modified a return address (LR) in a stack frame to hook >>> a function return. However, if function graph tracer has hit a filtered >>> function, then we can't unwind it as ftrace_push_return_trace() has >>> biased the index(frame->graph) with a 'huge negative' >>> offset(-FTRACE_NOTRACE_DEPTH). >>> >>> Moreover, arm64 stack walker defines index(frame->graph) as unsigned >>> int, which can not compare a -ve number. >>> >>> Similar problem we can have with calling of walk_stackframe() from >>> save_stack_trace_tsk() or dump_backtrace(). >>> >>> This patch fixes unwind_frame() to test the index for -ve value and >>> restore index accordingly before we can restore frame->pc. >> >> I've just spotted arm64's profile_pc, which does this: >> From arch/arm64/kernel/time.c:profile_pc(): >>> #ifdef CONFIG_FUNCTION_GRAPH_TRACER >>> frame.graph = -1; /* no task info */ >>> #endif >> >> Is this another elaborate way of hitting this problem? >> >> I guess the options are skip any return-address restore in the unwinder if >> frame.graph is -1. (and profile_pc may have a bug here). Or, put >> current->curr_ret_stack in there. I think we should go with latter, ie assign frame.graph = current->curr_ret_stack in profile_pc(). >> >> profile_pc() always passes tsk=NULL, so the unwinder assumes its current... >> kernel/profile.c pulls the pt_regs from a per-cpu irq_regs variable, that is >> updated by handle_IPI ... so it looks like this should always be current... > > Hmmm... is profile_pc the *only* case where frame->graph isn't equal to > tsk->curr_ret_stack in unwind_frame? If so, maybe unwind_frame should just Yes, it is the only place. > use that, and we could kill the graph member of struct stackframe completely? > Humm, not sure, we initialize frame->graph out of the while loop in unwind_frame()'s caller and then keep in decrementing it in looped function. -- Regards Pratyush
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web