aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-11-18 19:13:25 -0500
committerSteven Rostedt <rostedt@goodmis.org>2014-11-19 15:24:31 -0500
commit9960efeb80f73bd073483dab0855ee0ddc27085c (patch)
tree2eb8c3ea46a6fe5636507c2411e59b0ed8716ae2
parenta9ce7c36aa4256019180c590d60e2fad7431c749 (diff)
ftrace/x86: Add frames pointers to trampoline as necessary
When CONFIG_FRAME_POINTERS are enabled, it is required that the ftrace_caller and ftrace_regs_caller trampolines set up frame pointers otherwise a stack trace from a function call wont print the functions that called the trampoline. This is due to a check in __save_stack_address(): #ifdef CONFIG_FRAME_POINTER if (!reliable) return; #endif The "reliable" variable is only set if the function address is equal to contents of the address before the address the frame pointer register points to. If the frame pointer is not set up for the ftrace caller then this will fail the reliable test. It will miss the function that called the trampoline. Worse yet, if fentry is used (gcc 4.6 and beyond), it will also miss the parent, as the fentry is called before the stack frame is set up. That means the bp frame pointer points to the stack of just before the parent function was called. Link: http://lkml.kernel.org/r/20141119034829.355440340@goodmis.org Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: x86@kernel.org Cc: stable@vger.kernel.org # 3.7+ Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--arch/x86/kernel/mcount_64.S41
1 files changed, 41 insertions, 0 deletions
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index 42f0cdd20baf..35a793fa4bba 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -47,14 +47,51 @@ GLOBAL(\trace_label)
47#endif 47#endif
48.endm 48.endm
49 49
50#ifdef CONFIG_FRAME_POINTER
51/*
52 * Stack traces will stop at the ftrace trampoline if the frame pointer
53 * is not set up properly. If fentry is used, we need to save a frame
54 * pointer for the parent as well as the function traced, because the
55 * fentry is called before the stack frame is set up, where as mcount
56 * is called afterward.
57 */
58.macro create_frame parent rip
59#ifdef CC_USING_FENTRY
60 pushq \parent
61 pushq %rbp
62 movq %rsp, %rbp
63#endif
64 pushq \rip
65 pushq %rbp
66 movq %rsp, %rbp
67.endm
68
69.macro restore_frame
70#ifdef CC_USING_FENTRY
71 addq $16, %rsp
72#endif
73 popq %rbp
74 addq $8, %rsp
75.endm
76#else
77.macro create_frame parent rip
78.endm
79.macro restore_frame
80.endm
81#endif /* CONFIG_FRAME_POINTER */
82
50ENTRY(ftrace_caller) 83ENTRY(ftrace_caller)
51 ftrace_caller_setup ftrace_caller_op_ptr 84 ftrace_caller_setup ftrace_caller_op_ptr
52 /* regs go into 4th parameter (but make it NULL) */ 85 /* regs go into 4th parameter (but make it NULL) */
53 movq $0, %rcx 86 movq $0, %rcx
54 87
88 create_frame %rsi, %rdi
89
55GLOBAL(ftrace_call) 90GLOBAL(ftrace_call)
56 call ftrace_stub 91 call ftrace_stub
57 92
93 restore_frame
94
58 MCOUNT_RESTORE_FRAME 95 MCOUNT_RESTORE_FRAME
59 96
60 /* 97 /*
@@ -105,9 +142,13 @@ ENTRY(ftrace_regs_caller)
105 /* regs go into 4th parameter */ 142 /* regs go into 4th parameter */
106 leaq (%rsp), %rcx 143 leaq (%rsp), %rcx
107 144
145 create_frame %rsi, %rdi
146
108GLOBAL(ftrace_regs_call) 147GLOBAL(ftrace_regs_call)
109 call ftrace_stub 148 call ftrace_stub
110 149
150 restore_frame
151
111 /* Copy flags back to SS, to restore them */ 152 /* Copy flags back to SS, to restore them */
112 movq EFLAGS(%rsp), %rax 153 movq EFLAGS(%rsp), %rax
113 movq %rax, SS(%rsp) 154 movq %rax, SS(%rsp)