aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-02-21 11:23:57 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-02-21 20:21:27 -0500
commitfbee632d0ca9f4073a3fefb9a843eac8af036b0f (patch)
tree8fcc1304b6503f3ad00e94b256f08002cb008e90
parenta3d1ee10d1bf4520af3d44c1aa6cd46956ec4fd7 (diff)
perf probe: Fix error propagation leading to segfault
There are two hunks in this patch that stops probe processing as soon as one error is found, breaking out of loops, the other fix an error propagation that should return a negative error number but instead was returning the result of "ret < 0", which is 1 and thus made several error checks fail because they test agains < 0. The problem could be triggered by asking for a variable that was optimized out, fact that should stop the whole probe processing but instead was segfaulting while installing broken probes: [root@emilia ~]# probe perf_mmap:55 user_lock_limit Failed to find the location of user_lock_limit at this address. Perhaps, it has been optimized out. Failed to find 'user_lock_limit' in this function. Add new events: probe:perf_mmap (on perf_mmap:55 with user_lock_limit) probe:perf_mmap_1 (on perf_mmap:55 with user_lock_limit) Segmentation fault (core dumped) [root@emilia ~]# perf probe -l probe:perf_mmap (on perf_mmap:55@git/linux/kernel/perf_event.c with user_lock_limit) probe:perf_mmap_1 (on perf_mmap:55@git/linux/kernel/perf_event.c with user_lock_limit) [root@emilia ~]# After the fix: [root@emilia ~]# probe perf_mmap:55 user_lock_limit Failed to find the location of user_lock_limit at this address. Perhaps, it has been optimized out. Failed to find 'user_lock_limit' in this function. Error: Failed to add events. (-2) [root@emilia ~]# Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/probe-finder.c4
2 files changed, 7 insertions, 2 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 0e3ea1321103..369ddc64bbb6 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1832,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1832 } 1832 }
1833 1833
1834 /* Loop 2: add all events */ 1834 /* Loop 2: add all events */
1835 for (i = 0; i < npevs && ret >= 0; i++) 1835 for (i = 0; i < npevs && ret >= 0; i++) {
1836 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1836 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1837 pkgs[i].ntevs, force_add); 1837 pkgs[i].ntevs, force_add);
1838 if (ret < 0)
1839 break;
1840 }
1838end: 1841end:
1839 /* Loop 3: cleanup and free trace events */ 1842 /* Loop 3: cleanup and free trace events */
1840 for (i = 0; i < npevs; i++) { 1843 for (i = 0; i < npevs; i++) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index fe461f6559f1..eecbdca5c0d5 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1262,7 +1262,7 @@ static int probe_point_line_walker(const char *fname, int lineno,
1262 ret = call_probe_finder(NULL, pf); 1262 ret = call_probe_finder(NULL, pf);
1263 1263
1264 /* Continue if no error, because the line will be in inline function */ 1264 /* Continue if no error, because the line will be in inline function */
1265 return ret < 0 ?: 0; 1265 return ret < 0 ? ret : 0;
1266} 1266}
1267 1267
1268/* Find probe point from its line number */ 1268/* Find probe point from its line number */
@@ -1484,6 +1484,8 @@ static int find_probes(int fd, struct probe_finder *pf)
1484 pf->lno = pp->line; 1484 pf->lno = pp->line;
1485 ret = find_probe_point_by_line(pf); 1485 ret = find_probe_point_by_line(pf);
1486 } 1486 }
1487 if (ret != DWARF_CB_OK)
1488 break;
1487 } 1489 }
1488 off = noff; 1490 off = noff;
1489 } 1491 }