Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1466322

[PATCH 4/8] ftrace: add ftrace_graph_ret_addr() stack unwinding helpers

From Josh Poimboeuf <jpoimboe@redhat.com>
Newsgroups linux.kernel
Subject [PATCH 4/8] ftrace: add ftrace_graph_ret_addr() stack unwinding helpers
Date 2016-08-19 14:00 +0200
Message-ID <s7QCT-594-53@gated-at.bofh.it> (permalink)
References <s7QCS-594-13@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


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

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 0/8] ftrace/x86: function_graph stack dump fixes Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
  [PATCH 5/8] x86/dumpstack/ftrace: convert dump_trace() callbacks to use ftrace_graph_ret_addr() Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] x86/dumpstack/ftrace: Convert dump_trace() callbacks  to use ftrace_graph_ret_addr() tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:50 +0200
  [PATCH 1/8] ftrace: remove CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST from config Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] ftrace: Remove CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST  from config tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:10 +0200
  [PATCH 7/8] x86/dumpstack/ftrace: mark function graph handler function as unreliable Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] x86/dumpstack/ftrace: Mark function graph handler  function as unreliable tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:50 +0200
  [PATCH 8/8] x86/dumpstack/ftrace: don't print unreliable addresses in print_context_stack_bp() Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] x86/dumpstack/ftrace: Don't print unreliable  addresses in print_context_stack_bp() tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:50 +0200
  [PATCH 2/8] ftrace: only allocate the ret_stack 'fp' field when needed Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] ftrace: Only allocate the ret_stack 'fp' field when  needed tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:10 +0200
  [PATCH 6/8] ftrace/x86: implement HAVE_FUNCTION_GRAPH_RET_ADDR_PTR Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] ftrace/x86: Implement  HAVE_FUNCTION_GRAPH_RET_ADDR_PTR tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:10 +0200
  [PATCH 4/8] ftrace: add ftrace_graph_ret_addr() stack unwinding helpers Josh Poimboeuf <jpoimboe@redhat.com> - 2016-08-19 14:00 +0200
    [tip:x86/asm] ftrace: Add ftrace_graph_ret_addr() stack unwinding  helpers tip-bot for Josh Poimboeuf <tipbot@zytor.com> - 2016-08-24 15:10 +0200
  Re: [PATCH 0/8] ftrace/x86: function_graph stack dump fixes Steven Rostedt <rostedt@goodmis.org> - 2016-08-23 16:30 +0200
    Re: [PATCH 0/8] ftrace/x86: function_graph stack dump fixes Ingo Molnar <mingo@kernel.org> - 2016-08-24 12:20 +0200

csiph-web