perf probe: Clear probe_trace_event when add_probe_trace_event() fails
When probing with a glob, errors in add_probe_trace_event() won't be passed to debuginfo__find_trace_events() because it would be modified by probe_point_search_cb(). It causes a segfault if perf fails to find an argument for a probe point matched by the glob. For example: # ./perf probe -v -n 'SyS_dup? oldfd' probe-definition(0): SyS_dup? oldfd symbol:SyS_dup? file:(null) line:0 offset:0 return:0 lazy:(null) parsing arg: oldfd into oldfd 1 arguments Looking at the vmlinux_path (7 entries long) Using /lib/modules/4.3.0-rc4+/build/vmlinux for symbols Open Debuginfo file: /lib/modules/4.3.0-rc4+/build/vmlinux Try to find probe point from debuginfo. Matched function: SyS_dup3 found inline addr: 0xffffffff812095c0 Probe point found: SyS_dup3+0 Searching 'oldfd' variable in context. Converting variable oldfd into trace event. oldfd type is long int. found inline addr: 0xffffffff812096d4 Probe point found: SyS_dup2+36 Searching 'oldfd' variable in context. Failed to find 'oldfd' in this function. Matched function: SyS_dup3 Probe point found: SyS_dup3+0 Searching 'oldfd' variable in context. Converting variable oldfd into trace event. oldfd type is long int. Matched function: SyS_dup2 Probe point found: SyS_dup2+0 Searching 'oldfd' variable in context. Converting variable oldfd into trace event. oldfd type is long int. Found 4 probe_trace_events. Opening /sys/kernel/debug/tracing//kprobe_events write=1 Writing event: p:probe/SyS_dup3 _text+2135488 oldfd=%di:s64 Segmentation fault (core dumped) # This patch ensures that add_probe_trace_event() doesn't touches tf->ntevs and tf->tevs if those functions fail. After the patch: # perf probe 'SyS_dup? oldfd' Failed to find 'oldfd' in this function. Added new events: probe:SyS_dup3 (on SyS_dup? with oldfd) probe:SyS_dup3_1 (on SyS_dup? with oldfd) probe:SyS_dup2 (on SyS_dup? with oldfd) You can now use it in all perf tools, such as: perf record -e probe:SyS_dup2 -aR sleep 1 Signed-off-by: Wang Nan <wangnan0@huawei.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1447417761-156094-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
0196e787ce
Коммит
092b1f0b5f
|
@ -1183,7 +1183,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||||
container_of(pf, struct trace_event_finder, pf);
|
container_of(pf, struct trace_event_finder, pf);
|
||||||
struct perf_probe_point *pp = &pf->pev->point;
|
struct perf_probe_point *pp = &pf->pev->point;
|
||||||
struct probe_trace_event *tev;
|
struct probe_trace_event *tev;
|
||||||
struct perf_probe_arg *args;
|
struct perf_probe_arg *args = NULL;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
/* Check number of tevs */
|
/* Check number of tevs */
|
||||||
|
@ -1198,19 +1198,23 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||||
ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
|
ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
|
||||||
pp->retprobe, pp->function, &tev->point);
|
pp->retprobe, pp->function, &tev->point);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto end;
|
||||||
|
|
||||||
tev->point.realname = strdup(dwarf_diename(sc_die));
|
tev->point.realname = strdup(dwarf_diename(sc_die));
|
||||||
if (!tev->point.realname)
|
if (!tev->point.realname) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
|
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
|
||||||
tev->point.offset);
|
tev->point.offset);
|
||||||
|
|
||||||
/* Expand special probe argument if exist */
|
/* Expand special probe argument if exist */
|
||||||
args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
|
args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
|
||||||
if (args == NULL)
|
if (args == NULL) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
ret = expand_probe_args(sc_die, pf, args);
|
ret = expand_probe_args(sc_die, pf, args);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -1234,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
if (ret) {
|
||||||
|
clear_probe_trace_event(tev);
|
||||||
|
tf->ntevs--;
|
||||||
|
}
|
||||||
free(args);
|
free(args);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче