All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@kernel.org>, "H . Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org, linux-kernel@vger.kernel.org,
	Andy Lutomirski <luto@amacapital.net>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Brian Gerst <brgerst@gmail.com>,
	Kees Cook <keescook@chromium.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Byungchul Park <byungchul.park@lge.com>
Subject: [PATCH v2 21/44] ftrace: add ftrace_graph_ret_addr() stack unwinding helpers
Date: Thu,  4 Aug 2016 17:22:17 -0500	[thread overview]
Message-ID: <6e3d1d06e144ba7f9f61361f0bc6847c1296d5ee.1470345772.git.jpoimboe@redhat.com> (raw)
In-Reply-To: <cover.1470345772.git.jpoimboe@redhat.com>

When function graph tracing is enabled for a function, ftrace modifies
the stack by replacing the original return address with the address of a
hook function (return_to_handler).

Stack unwinders need a way to get the original return address.  Add an
arch-independent helper function for that named ftrace_graph_ret_addr().

This adds two variations of the function: one depends on
HAVE_FUNCTION_GRAPH_RET_ADDR_PTR, and the other relies on an index state
variable.

The former is recommended because, in some cases, the latter can cause
problems when the unwinder skips stack frames.  It can get out of sync
with the ret_stack index and wrong addresses can be reported for the
stack trace.

Once all arches have been ported to use
HAVE_FUNCTION_GRAPH_RET_ADDR_PTR, we can get rid of the distinction.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
 include/linux/ftrace.h               | 10 +++++++
 kernel/trace/trace_functions_graph.c | 58 ++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 483e02a..6f93ac4 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -814,6 +814,9 @@ extern int
 ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
 			 unsigned long frame_pointer, unsigned long *retp);
 
+unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
+				    unsigned long ret, unsigned long *retp);
+
 /*
  * Sometimes we don't want to trace a function with the function
  * graph tracer but we want them to keep traced by the usual function
@@ -875,6 +878,13 @@ static inline int task_curr_ret_stack(struct task_struct *tsk)
 	return -1;
 }
 
+static inline unsigned long
+ftrace_graph_ret_addr(struct task_struct *task, int *idx, unsigned long ret,
+		      unsigned long *retp)
+{
+	return ret;
+}
+
 static inline void pause_graph_tracing(void) { }
 static inline void unpause_graph_tracing(void) { }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index f7212ec..0cbe38a 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -284,6 +284,64 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 	return ret;
 }
 
+/**
+ * ftrace_graph_ret_addr - convert a potentially modified stack return address
+ *			   to its original value
+ *
+ * This function can be called by stack unwinding code to convert a found stack
+ * return address ('ret') to its original value, in case the function graph
+ * tracer has modified it to be 'return_to_handler'.  If the address hasn't
+ * been modified, the unchanged value of 'ret' is returned.
+ *
+ * 'idx' is a state variable which should be initialized by the caller to zero
+ * before the first call.
+ *
+ * 'retp' is a pointer to the return address on the stack.  It's ignored if
+ * the arch doesn't have HAVE_FUNCTION_GRAPH_RET_ADDR_PTR defined.
+ */
+#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
+unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
+				    unsigned long ret, unsigned long *retp)
+{
+	int index = task->curr_ret_stack;
+	int i;
+
+	if (ret != (unsigned long)return_to_handler)
+		return ret;
+
+	if (index < -1)
+		index += FTRACE_NOTRACE_DEPTH;
+
+	if (index < 0)
+		return ret;
+
+	for (i = 0; i <= index; i++)
+		if (task->ret_stack[i].retp == retp)
+			return task->ret_stack[i].ret;
+
+	return ret;
+}
+#else /* !HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
+unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
+				    unsigned long ret, unsigned long *retp)
+{
+	int task_idx;
+
+	if (ret != (unsigned long)return_to_handler)
+		return ret;
+
+	task_idx = task->curr_ret_stack;
+
+	if (!task->ret_stack || task_idx < *idx)
+		return ret;
+
+	task_idx -= *idx;
+	(*idx)++;
+
+	return task->ret_stack[task_idx].ret;
+}
+#endif /* HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
+
 int __trace_graph_entry(struct trace_array *tr,
 				struct ftrace_graph_ent *trace,
 				unsigned long flags,
-- 
2.7.4

  parent reply	other threads:[~2016-08-04 22:29 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-04 22:21 [PATCH v2 00/44] x86/dumpstack: rewrite x86 stack dump code Josh Poimboeuf
2016-08-04 22:21 ` [PATCH v2 01/44] x86/dumpstack: remove show_trace() Josh Poimboeuf
2016-08-04 22:21 ` [PATCH v2 02/44] x86/asm/head: remove unused init_rsp variable Josh Poimboeuf
2016-08-04 22:21 ` [PATCH v2 03/44] x86/asm/head: rename 'stack_start' -> 'initial_stack' Josh Poimboeuf
2016-08-05 15:28   ` Nilay Vaish
2016-08-05 16:01     ` Josh Poimboeuf
2016-08-06  5:25       ` Borislav Petkov
2016-08-06 13:13         ` Josh Poimboeuf
2016-08-06 13:15         ` Brian Gerst
2016-08-06 13:38           ` Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 04/44] x86/asm/head: use a common function for starting CPUs Josh Poimboeuf
2016-08-05 15:41   ` Nilay Vaish
2016-08-05 16:17     ` Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 05/44] x86/dumpstack: make printk_stack_address() more generally useful Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 06/44] x86/dumpstack: add IRQ_USABLE_STACK_SIZE define Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 07/44] x86/dumpstack: remove extra brackets around "<EOE>" Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 08/44] x86/dumpstack: fix irq stack bounds calculation in show_stack_log_lvl() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 09/44] x86/dumpstack: fix x86_32 kernel_stack_pointer() previous stack access Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 10/44] x86/dumpstack: add get_stack_pointer() and get_frame_pointer() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 11/44] x86/dumpstack: remove unnecessary stack pointer arguments Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 12/44] x86: move _stext marker to before head code Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 13/44] x86/asm/head: remove useless zeroed word Josh Poimboeuf
2016-08-05 16:13   ` Brian Gerst
2016-08-05 16:23     ` Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 14/44] x86/asm/head: put real return address on idle task stack Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 15/44] perf/x86: check perf_callchain_store() error Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 16/44] oprofile/x86: add regs->ip to oprofile trace Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 17/44] proc: fix return address printk conversion specifer in /proc/<pid>/stack Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 18/44] ftrace: remove CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST from config Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 19/44] ftrace: only allocate the ret_stack 'fp' field when needed Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 20/44] ftrace: add return address pointer to ftrace_ret_stack Josh Poimboeuf
2016-08-04 22:22 ` Josh Poimboeuf [this message]
2016-08-04 22:22 ` [PATCH v2 22/44] x86/dumpstack/ftrace: convert dump_trace() callbacks to use ftrace_graph_ret_addr() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 23/44] ftrace/x86: implement HAVE_FUNCTION_GRAPH_RET_ADDR_PTR Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 24/44] x86/dumpstack/ftrace: mark function graph handler function as unreliable Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 25/44] x86/dumpstack/ftrace: don't print unreliable addresses in print_context_stack_bp() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 26/44] x86/dumpstack: allow preemption in show_stack_log_lvl() and dump_trace() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 27/44] x86/dumpstack: simplify in_exception_stack() Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 28/44] x86/dumpstack: add get_stack_info() interface Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 29/44] x86/dumpstack: add recursion checking for all stacks Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 30/44] x86/unwind: add new unwind interface and implementations Josh Poimboeuf
2016-08-09 23:17   ` Nilay Vaish
2016-08-09 23:27     ` Josh Poimboeuf
2016-08-10  7:25       ` Andy Lutomirski
2016-08-10 14:16         ` Josh Poimboeuf
2016-08-11  7:18           ` Andy Lutomirski
2016-08-11 14:28             ` Josh Poimboeuf
2016-08-11 14:58               ` Andy Lutomirski
2016-08-11 16:09                 ` Josh Poimboeuf
2016-08-11 18:58                   ` Andy Lutomirski
2016-08-11 19:15                     ` Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 31/44] perf/x86: convert perf_callchain_kernel() to use the new unwinder Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 32/44] x86/stacktrace: convert save_stack_trace_*() " Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 33/44] oprofile/x86: convert x86_backtrace() " Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 34/44] x86/dumpstack: convert show_trace_log_lvl() " Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 35/44] x86/dumpstack: remove dump_trace() and related callbacks Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 36/44] x86/entry/unwind: encode pt_regs pointer in frame pointer Josh Poimboeuf
2016-08-08 23:06   ` Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 37/44] x86/unwind: detect syscall entry regs Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 38/44] x86/dumpstack: print stack identifier on its own line Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 39/44] x86/dumpstack: print any pt_regs found on the stack Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 40/44] x86: remove 64-byte gap at end of irq stack Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 41/44] x86/asm/head: standardize the end of the stack for idle tasks Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 42/44] x86/unwind: warn on kernel stack corruption Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 43/44] x86/unwind: warn on bad stack return address Josh Poimboeuf
2016-08-04 22:22 ` [PATCH v2 44/44] x86/unwind: warn if stack grows up Josh Poimboeuf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6e3d1d06e144ba7f9f61361f0bc6847c1296d5ee.1470345772.git.jpoimboe@redhat.com \
    --to=jpoimboe@redhat.com \
    --cc=brgerst@gmail.com \
    --cc=byungchul.park@lge.com \
    --cc=fweisbec@gmail.com \
    --cc=hpa@zytor.com \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.