Messages in this thread Patch in this message | | | From | 平松雅巳 / HIRAMATU,MASAMI <> | Subject | RE: [PATCH] perf probe: Clear probe_trace_event when add_probe_trace_event() fails | Date | Sat, 14 Nov 2015 03:32:24 +0000 |
| |
>From: Wang Nan [mailto:wangnan0@huawei.com] > >When probe with glob, error in add_probe_trace_event() won't be passed >to debuginfo__find_trace_events() because it whould be modified by >probe_point_search_cb(). It causes segfault if perf failed to find >argument for one probing 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 add_probe_trace_event() not touch tf->ntevs and >tf->tevs if it returns failure. > >Here is testing result: > > # 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
Good catch!
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Thanks!
> >Signed-off-by: Wang Nan <wangnan0@huawei.com> >Cc: Arnaldo Carvalho de Melo <acme@redhat.com> >Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> >Cc: Zefan Li <lizefan@huawei.com> >Cc: pi3orama@163.com >--- > tools/perf/util/probe-finder.c | 20 ++++++++++++++------ > 1 file changed, 14 insertions(+), 6 deletions(-) > >diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c >index 63993d7..05012bb 100644 >--- a/tools/perf/util/probe-finder.c >+++ b/tools/perf/util/probe-finder.c >@@ -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); > struct perf_probe_point *pp = &pf->pev->point; > struct probe_trace_event *tev; >- struct perf_probe_arg *args; >+ struct perf_probe_arg *args = NULL; > int ret, i; > > /* 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, > pp->retprobe, pp->function, &tev->point); > if (ret < 0) >- return ret; >+ goto end; > > tev->point.realname = strdup(dwarf_diename(sc_die)); >- if (!tev->point.realname) >- return -ENOMEM; >+ if (!tev->point.realname) { >+ ret = -ENOMEM; >+ goto end; >+ } > > pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, > tev->point.offset); > > /* Expand special probe argument if exist */ > args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); >- if (args == NULL) >- return -ENOMEM; >+ if (args == NULL) { >+ ret = -ENOMEM; >+ goto end; >+ } > > ret = expand_probe_args(sc_die, pf, args); > if (ret < 0) >@@ -1234,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) > } > > end: >+ if (ret) { >+ clear_probe_trace_event(tev); >+ tf->ntevs--; >+ } > free(args); > return ret; > } >-- >1.8.3.4
| |