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 | |
| 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>
| -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; |
