diff options
author | Kevin Hao <haokexin@gmail.com> | 2013-10-23 08:58:16 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-11-05 16:01:47 -0500 |
commit | ab4ead02ec235d706d0611d8741964628291237e (patch) | |
tree | 3a0d764b40cc2219d8ded433dcf4fe48b1b3e7fc /arch/x86 | |
parent | 9cd804ac1f39e10510bf93700f1f7ea66b2e1b38 (diff) |
ftrace/x86: skip over the breakpoint for ftrace caller
In commit 8a4d0a687a59 "ftrace: Use breakpoint method to update ftrace
caller", we choose to use breakpoint method to update the ftrace
caller. But we also need to skip over the breakpoint in function
ftrace_int3_handler() for them. Otherwise weird things would happen.
Cc: stable@vger.kernel.org # 3.5+
Signed-off-by: Kevin Hao <haokexin@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/ftrace.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 42a392a9fd02..d4bdd253fea7 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -248,6 +248,15 @@ int ftrace_update_ftrace_func(ftrace_func_t func) | |||
248 | return ret; | 248 | return ret; |
249 | } | 249 | } |
250 | 250 | ||
251 | static int is_ftrace_caller(unsigned long ip) | ||
252 | { | ||
253 | if (ip == (unsigned long)(&ftrace_call) || | ||
254 | ip == (unsigned long)(&ftrace_regs_call)) | ||
255 | return 1; | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
251 | /* | 260 | /* |
252 | * A breakpoint was added to the code address we are about to | 261 | * A breakpoint was added to the code address we are about to |
253 | * modify, and this is the handle that will just skip over it. | 262 | * modify, and this is the handle that will just skip over it. |
@@ -257,10 +266,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func) | |||
257 | */ | 266 | */ |
258 | int ftrace_int3_handler(struct pt_regs *regs) | 267 | int ftrace_int3_handler(struct pt_regs *regs) |
259 | { | 268 | { |
269 | unsigned long ip; | ||
270 | |||
260 | if (WARN_ON_ONCE(!regs)) | 271 | if (WARN_ON_ONCE(!regs)) |
261 | return 0; | 272 | return 0; |
262 | 273 | ||
263 | if (!ftrace_location(regs->ip - 1)) | 274 | ip = regs->ip - 1; |
275 | if (!ftrace_location(ip) && !is_ftrace_caller(ip)) | ||
264 | return 0; | 276 | return 0; |
265 | 277 | ||
266 | regs->ip += MCOUNT_INSN_SIZE - 1; | 278 | regs->ip += MCOUNT_INSN_SIZE - 1; |