summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorKevin Hao <haokexin@gmail.com>2013-10-23 20:58:16 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 11:11:50 -0800
commitfe78c20faafde229631b0402ef9fdfbc75277903 (patch)
tree1a4528b5eedcb014ec6d282662a959b724bfdd05 /arch
parentb5f92a134b69faeffa0e1a811f01a48d686a4e97 (diff)
downloadlinux-3.10-fe78c20faafde229631b0402ef9fdfbc75277903.tar.gz
linux-3.10-fe78c20faafde229631b0402ef9fdfbc75277903.tar.bz2
linux-3.10-fe78c20faafde229631b0402ef9fdfbc75277903.zip
ftrace/x86: skip over the breakpoint for ftrace caller
commit ab4ead02ec235d706d0611d8741964628291237e upstream. 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. Signed-off-by: Kevin Hao <haokexin@gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/ftrace.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 42a392a9fd0..d4bdd253fea 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)
return ret;
}
+static int is_ftrace_caller(unsigned long ip)
+{
+ if (ip == (unsigned long)(&ftrace_call) ||
+ ip == (unsigned long)(&ftrace_regs_call))
+ return 1;
+
+ return 0;
+}
+
/*
* A breakpoint was added to the code address we are about to
* 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)
*/
int ftrace_int3_handler(struct pt_regs *regs)
{
+ unsigned long ip;
+
if (WARN_ON_ONCE(!regs))
return 0;
- if (!ftrace_location(regs->ip - 1))
+ ip = regs->ip - 1;
+ if (!ftrace_location(ip) && !is_ftrace_caller(ip))
return 0;
regs->ip += MCOUNT_INSN_SIZE - 1;