Skip to content

Commit 092b1f0

Browse files
WangNan0acmel
authored andcommitted
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 <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Zefan Li <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 0196e78 commit 092b1f0

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

tools/perf/util/probe-finder.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
11831183
container_of(pf, struct trace_event_finder, pf);
11841184
struct perf_probe_point *pp = &pf->pev->point;
11851185
struct probe_trace_event *tev;
1186-
struct perf_probe_arg *args;
1186+
struct perf_probe_arg *args = NULL;
11871187
int ret, i;
11881188

11891189
/* Check number of tevs */
@@ -1198,19 +1198,23 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
11981198
ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
11991199
pp->retprobe, pp->function, &tev->point);
12001200
if (ret < 0)
1201-
return ret;
1201+
goto end;
12021202

12031203
tev->point.realname = strdup(dwarf_diename(sc_die));
1204-
if (!tev->point.realname)
1205-
return -ENOMEM;
1204+
if (!tev->point.realname) {
1205+
ret = -ENOMEM;
1206+
goto end;
1207+
}
12061208

12071209
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
12081210
tev->point.offset);
12091211

12101212
/* Expand special probe argument if exist */
12111213
args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1212-
if (args == NULL)
1213-
return -ENOMEM;
1214+
if (args == NULL) {
1215+
ret = -ENOMEM;
1216+
goto end;
1217+
}
12141218

12151219
ret = expand_probe_args(sc_die, pf, args);
12161220
if (ret < 0)
@@ -1234,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
12341238
}
12351239

12361240
end:
1241+
if (ret) {
1242+
clear_probe_trace_event(tev);
1243+
tf->ntevs--;
1244+
}
12371245
free(args);
12381246
return ret;
12391247
}

0 commit comments

Comments
 (0)