diff options
author | Steven Rostedt <srostedt@redhat.com> | 2012-04-25 14:39:54 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2012-05-16 19:58:49 -0400 |
commit | f0cf973a224a3e3c1dec3395af3ba01cf14b1ff4 (patch) | |
tree | c8efdfadbf904ce9eaff942156bc3d0608375d7d /kernel | |
parent | a650e02a528ab9d6d6f0b8b57745c32f2a138459 (diff) |
ftrace: Return record ip addr for ftrace_location()
ftrace_location() is passed an addr, and returns 1 if the addr is
on a ftrace nop (or caller to ftrace_caller), and 0 otherwise.
To let kprobes know if it should move a breakpoint or not, it
must return the actual addr that is the start of the ftrace nop.
This way a kprobe placed on the location of a ftrace nop, can
instead be placed on the instruction after the nop. Even if the
probe addr is on the second or later byte of the nop, it can
simply be moved forward.
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/ftrace.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index dd091c84b57f..ef0826204840 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -1393,7 +1393,7 @@ static int ftrace_cmp_recs(const void *a, const void *b) | |||
1393 | return 0; | 1393 | return 0; |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | static int ftrace_location_range(unsigned long start, unsigned long end) | 1396 | static unsigned long ftrace_location_range(unsigned long start, unsigned long end) |
1397 | { | 1397 | { |
1398 | struct ftrace_page *pg; | 1398 | struct ftrace_page *pg; |
1399 | struct dyn_ftrace *rec; | 1399 | struct dyn_ftrace *rec; |
@@ -1410,7 +1410,7 @@ static int ftrace_location_range(unsigned long start, unsigned long end) | |||
1410 | sizeof(struct dyn_ftrace), | 1410 | sizeof(struct dyn_ftrace), |
1411 | ftrace_cmp_recs); | 1411 | ftrace_cmp_recs); |
1412 | if (rec) | 1412 | if (rec) |
1413 | return 1; | 1413 | return rec->ip; |
1414 | } | 1414 | } |
1415 | 1415 | ||
1416 | return 0; | 1416 | return 0; |
@@ -1420,12 +1420,12 @@ static int ftrace_location_range(unsigned long start, unsigned long end) | |||
1420 | * ftrace_location - return true if the ip giving is a traced location | 1420 | * ftrace_location - return true if the ip giving is a traced location |
1421 | * @ip: the instruction pointer to check | 1421 | * @ip: the instruction pointer to check |
1422 | * | 1422 | * |
1423 | * Returns 1 if @ip given is a pointer to a ftrace location. | 1423 | * Returns rec->ip if @ip given is a pointer to a ftrace location. |
1424 | * That is, the instruction that is either a NOP or call to | 1424 | * That is, the instruction that is either a NOP or call to |
1425 | * the function tracer. It checks the ftrace internal tables to | 1425 | * the function tracer. It checks the ftrace internal tables to |
1426 | * determine if the address belongs or not. | 1426 | * determine if the address belongs or not. |
1427 | */ | 1427 | */ |
1428 | int ftrace_location(unsigned long ip) | 1428 | unsigned long ftrace_location(unsigned long ip) |
1429 | { | 1429 | { |
1430 | return ftrace_location_range(ip, ip); | 1430 | return ftrace_location_range(ip, ip); |
1431 | } | 1431 | } |
@@ -1442,8 +1442,12 @@ int ftrace_location(unsigned long ip) | |||
1442 | */ | 1442 | */ |
1443 | int ftrace_text_reserved(void *start, void *end) | 1443 | int ftrace_text_reserved(void *start, void *end) |
1444 | { | 1444 | { |
1445 | return ftrace_location_range((unsigned long)start, | 1445 | unsigned long ret; |
1446 | (unsigned long)end); | 1446 | |
1447 | ret = ftrace_location_range((unsigned long)start, | ||
1448 | (unsigned long)end); | ||
1449 | |||
1450 | return (int)!!ret; | ||
1447 | } | 1451 | } |
1448 | 1452 | ||
1449 | static void __ftrace_hash_rec_update(struct ftrace_ops *ops, | 1453 | static void __ftrace_hash_rec_update(struct ftrace_ops *ops, |