perf probe: Fix error propagation leading to segfault
authorArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 21 Feb 2011 16:23:57 +0000 (13:23 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 22 Feb 2011 01:21:27 +0000 (22:21 -0300)
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>
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c

index 0e3ea1321103b0ac5aa86605cc44be86623668ef..369ddc64bbb6a6d81aea0b9f92075fe5315af178 100644 (file)
@@ -1832,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
        }
 
        /* Loop 2: add all events */
-       for (i = 0; i < npevs && ret >= 0; i++)
+       for (i = 0; i < npevs && ret >= 0; i++) {
                ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
                                                pkgs[i].ntevs, force_add);
+               if (ret < 0)
+                       break;
+       }
 end:
        /* Loop 3: cleanup and free trace events  */
        for (i = 0; i < npevs; i++) {
index fe461f6559f1bc10d9ac4f2f956e46daefffc51f..eecbdca5c0d5ec8b7659c8036d69bb83366a6c4b 100644 (file)
@@ -1262,7 +1262,7 @@ static int probe_point_line_walker(const char *fname, int lineno,
        ret = call_probe_finder(NULL, pf);
 
        /* Continue if no error, because the line will be in inline function */
-       return ret < 0 ?: 0;
+       return ret < 0 ? ret : 0;
 }
 
 /* Find probe point from its line number */
@@ -1484,6 +1484,8 @@ static int find_probes(int fd, struct probe_finder *pf)
                                pf->lno = pp->line;
                                ret = find_probe_point_by_line(pf);
                        }
+                       if (ret != DWARF_CB_OK)
+                               break;
                }
                off = noff;
        }