diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2011-06-27 03:27:45 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-15 16:19:08 -0400 |
commit | 190b57fcb9c5fed5414935a174094f534fc510bc (patch) | |
tree | 952c19ed78abe454715d357fd5d0f8c6af9efd55 /tools/perf/util/probe-event.c | |
parent | ff741783506c340035659a71be68ddb4068760d1 (diff) |
perf probe: Add probed module in front of function
Add probed module name and ":" in front of function name
if -m module option is given. In the result, the symbol
name passed to kprobe-tracer becomes MODULE:FUNCTION,
so that kallsyms can solve it as a symbol in the module
correctly.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Link: http://lkml.kernel.org/r/20110627072745.6528.26416.stgit@fedora15
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 920c1957d6d3..ee3f41eec5c1 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -226,14 +226,26 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | ||
230 | int ntevs, const char *module) | ||
231 | { | ||
232 | int i; | ||
233 | for (i = 0; i < ntevs; i++) { | ||
234 | tevs[i].point.module = strdup(module); | ||
235 | if (!tevs[i].point.module) | ||
236 | return -ENOMEM; | ||
237 | } | ||
238 | return 0; | ||
239 | } | ||
240 | |||
229 | /* Try to find perf_probe_event with debuginfo */ | 241 | /* Try to find perf_probe_event with debuginfo */ |
230 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 242 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, |
231 | struct probe_trace_event **tevs, | 243 | struct probe_trace_event **tevs, |
232 | int max_tevs, const char *module) | 244 | int max_tevs, const char *module) |
233 | { | 245 | { |
234 | bool need_dwarf = perf_probe_event_need_dwarf(pev); | 246 | bool need_dwarf = perf_probe_event_need_dwarf(pev); |
235 | struct debuginfo *dinfo = open_debuginfo(module); | 247 | struct debuginfo *dinfo = open_debuginfo(module); |
236 | int ntevs; | 248 | int ntevs, ret = 0; |
237 | 249 | ||
238 | if (!dinfo) { | 250 | if (!dinfo) { |
239 | if (need_dwarf) { | 251 | if (need_dwarf) { |
@@ -251,7 +263,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
251 | 263 | ||
252 | if (ntevs > 0) { /* Succeeded to find trace events */ | 264 | if (ntevs > 0) { /* Succeeded to find trace events */ |
253 | pr_debug("find %d probe_trace_events.\n", ntevs); | 265 | pr_debug("find %d probe_trace_events.\n", ntevs); |
254 | return ntevs; | 266 | if (module) |
267 | ret = add_module_to_probe_trace_events(*tevs, ntevs, | ||
268 | module); | ||
269 | return ret < 0 ? ret : ntevs; | ||
255 | } | 270 | } |
256 | 271 | ||
257 | if (ntevs == 0) { /* No error but failed to find probe point. */ | 272 | if (ntevs == 0) { /* No error but failed to find probe point. */ |
@@ -1010,7 +1025,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) | |||
1010 | 1025 | ||
1011 | /* Parse probe_events event into struct probe_point */ | 1026 | /* Parse probe_events event into struct probe_point */ |
1012 | static int parse_probe_trace_command(const char *cmd, | 1027 | static int parse_probe_trace_command(const char *cmd, |
1013 | struct probe_trace_event *tev) | 1028 | struct probe_trace_event *tev) |
1014 | { | 1029 | { |
1015 | struct probe_trace_point *tp = &tev->point; | 1030 | struct probe_trace_point *tp = &tev->point; |
1016 | char pr; | 1031 | char pr; |
@@ -1043,8 +1058,14 @@ static int parse_probe_trace_command(const char *cmd, | |||
1043 | 1058 | ||
1044 | tp->retprobe = (pr == 'r'); | 1059 | tp->retprobe = (pr == 'r'); |
1045 | 1060 | ||
1046 | /* Scan function name and offset */ | 1061 | /* Scan module name(if there), function name and offset */ |
1047 | ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, | 1062 | p = strchr(argv[1], ':'); |
1063 | if (p) { | ||
1064 | tp->module = strndup(argv[1], p - argv[1]); | ||
1065 | p++; | ||
1066 | } else | ||
1067 | p = argv[1]; | ||
1068 | ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, | ||
1048 | &tp->offset); | 1069 | &tp->offset); |
1049 | if (ret == 1) | 1070 | if (ret == 1) |
1050 | tp->offset = 0; | 1071 | tp->offset = 0; |
@@ -1289,9 +1310,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) | |||
1289 | if (buf == NULL) | 1310 | if (buf == NULL) |
1290 | return NULL; | 1311 | return NULL; |
1291 | 1312 | ||
1292 | len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", | 1313 | len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", |
1293 | tp->retprobe ? 'r' : 'p', | 1314 | tp->retprobe ? 'r' : 'p', |
1294 | tev->group, tev->event, | 1315 | tev->group, tev->event, |
1316 | tp->module ?: "", tp->module ? ":" : "", | ||
1295 | tp->symbol, tp->offset); | 1317 | tp->symbol, tp->offset); |
1296 | if (len <= 0) | 1318 | if (len <= 0) |
1297 | goto error; | 1319 | goto error; |
@@ -1398,6 +1420,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
1398 | free(tev->group); | 1420 | free(tev->group); |
1399 | if (tev->point.symbol) | 1421 | if (tev->point.symbol) |
1400 | free(tev->point.symbol); | 1422 | free(tev->point.symbol); |
1423 | if (tev->point.module) | ||
1424 | free(tev->point.module); | ||
1401 | for (i = 0; i < tev->nargs; i++) { | 1425 | for (i = 0; i < tev->nargs; i++) { |
1402 | if (tev->args[i].name) | 1426 | if (tev->args[i].name) |
1403 | free(tev->args[i].name); | 1427 | free(tev->args[i].name); |
@@ -1749,7 +1773,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
1749 | /* Convert perf_probe_event with debuginfo */ | 1773 | /* Convert perf_probe_event with debuginfo */ |
1750 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); | 1774 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); |
1751 | if (ret != 0) | 1775 | if (ret != 0) |
1752 | return ret; | 1776 | return ret; /* Found in debuginfo or got an error */ |
1753 | 1777 | ||
1754 | /* Allocate trace event buffer */ | 1778 | /* Allocate trace event buffer */ |
1755 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); | 1779 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); |
@@ -1762,6 +1786,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
1762 | ret = -ENOMEM; | 1786 | ret = -ENOMEM; |
1763 | goto error; | 1787 | goto error; |
1764 | } | 1788 | } |
1789 | tev->point.module = strdup(module); | ||
1790 | if (tev->point.module == NULL) { | ||
1791 | ret = -ENOMEM; | ||
1792 | goto error; | ||
1793 | } | ||
1765 | tev->point.offset = pev->point.offset; | 1794 | tev->point.offset = pev->point.offset; |
1766 | tev->point.retprobe = pev->point.retprobe; | 1795 | tev->point.retprobe = pev->point.retprobe; |
1767 | tev->nargs = pev->nargs; | 1796 | tev->nargs = pev->nargs; |