Skip to content

Commit b4ee6d4

Browse files
WangNan0acmel
authored andcommitted
perf bpf: Support BPF program attach to tracepoints
To support 98b5c2c ("perf, bpf: allow bpf programs attach to tracepoints"), this patch allows BPF scripts to select tracepoints in their section name. Example: # cat test_tracepoint.c /*********************************************/ #include <uapi/linux/bpf.h> #define SEC(NAME) __attribute__((section(NAME), used)) SEC("raw_syscalls:sys_enter") int func(void *ctx) { /* * /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format: * ... * field:long id; offset:8; size:8; signed:1; * ... * ctx + 8 select 'id' */ u64 id = *((u64 *)(ctx + 8)); if (id == 1) return 1; return 0; } SEC("_write=sys_write") int _write(void *ctx) { return 1; } char _license[] SEC("license") = "GPL"; int _version SEC("version") = LINUX_VERSION_CODE; /*********************************************/ # perf record -e ./test_tracepoint.c dd if=/dev/zero of=/dev/null count=5 5+0 records in 5+0 records out 2560 bytes (2.6 kB) copied, 6.2281e-05 s, 41.1 MB/s [ perf record: Woken up 1 times to write data ] # perf script dd 13436 [005] 1596.490869: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, 7ffe82470d60, ffffffffffffe020, fffff dd 13436 [005] 1596.490871: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490873: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490874: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490876: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490876: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490878: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490879: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490881: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490882: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490900: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1f, 40acb8, 7f44bac74700, 7f44baa4fba dd 13436 [005] 1596.490901: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490917: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffffa, 7f44bac74700, 7f44baa4f dd 13436 [005] 1596.490918: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490932: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffff9, 7f44bac74700, 7f44baa4f dd 13436 [005] 1596.490933: perf_bpf_probe:_write: (ffffffff812351e0) Committer note: Further testing: # trace --no-sys --event /home/acme/bpf/tracepoint.c cat /etc/passwd > /dev/null 0.000 raw_syscalls:sys_enter:NR 1 (1, 7f0490504000, c48, 7f0490503010, ffffffffffffffff, 0)) 0.006 perf_bpf_probe:_write:(ffffffff81241bc0)) # Signed-off-by: Wang Nan <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Jiri Olsa <[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 cd102d7 commit b4ee6d4

File tree

1 file changed

+60
-5
lines changed

1 file changed

+60
-5
lines changed

tools/perf/util/bpf-loader.c

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1)
3737
DEFINE_PRINT_FN(debug, 1)
3838

3939
struct bpf_prog_priv {
40+
bool is_tp;
41+
char *sys_name;
42+
char *evt_name;
4043
struct perf_probe_event pev;
4144
bool need_prologue;
4245
struct bpf_insn *insns_buf;
@@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused,
118121
cleanup_perf_probe_events(&priv->pev, 1);
119122
zfree(&priv->insns_buf);
120123
zfree(&priv->type_mapping);
124+
zfree(&priv->sys_name);
125+
zfree(&priv->evt_name);
121126
free(priv);
122127
}
123128

@@ -269,14 +274,31 @@ parse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev)
269274
}
270275

271276
static int
272-
parse_prog_config(const char *config_str, struct perf_probe_event *pev)
277+
parse_prog_config(const char *config_str, const char **p_main_str,
278+
bool *is_tp, struct perf_probe_event *pev)
273279
{
274280
int err;
275281
const char *main_str = parse_prog_config_kvpair(config_str, pev);
276282

277283
if (IS_ERR(main_str))
278284
return PTR_ERR(main_str);
279285

286+
*p_main_str = main_str;
287+
if (!strchr(main_str, '=')) {
288+
/* Is a tracepoint event? */
289+
const char *s = strchr(main_str, ':');
290+
291+
if (!s) {
292+
pr_debug("bpf: '%s' is not a valid tracepoint\n",
293+
config_str);
294+
return -BPF_LOADER_ERRNO__CONFIG;
295+
}
296+
297+
*is_tp = true;
298+
return 0;
299+
}
300+
301+
*is_tp = false;
280302
err = parse_perf_probe_command(main_str, pev);
281303
if (err < 0) {
282304
pr_debug("bpf: '%s' is not a valid config string\n",
@@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog)
292314
{
293315
struct perf_probe_event *pev = NULL;
294316
struct bpf_prog_priv *priv = NULL;
295-
const char *config_str;
317+
const char *config_str, *main_str;
318+
bool is_tp = false;
296319
int err;
297320

298321
/* Initialize per-program probing setting */
@@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog)
313336
pev = &priv->pev;
314337

315338
pr_debug("bpf: config program '%s'\n", config_str);
316-
err = parse_prog_config(config_str, pev);
339+
err = parse_prog_config(config_str, &main_str, &is_tp, pev);
317340
if (err)
318341
goto errout;
319342

343+
if (is_tp) {
344+
char *s = strchr(main_str, ':');
345+
346+
priv->is_tp = true;
347+
priv->sys_name = strndup(main_str, s - main_str);
348+
priv->evt_name = strdup(s + 1);
349+
goto set_priv;
350+
}
351+
320352
if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
321353
pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
322354
config_str, PERF_BPF_PROBE_GROUP);
@@ -339,6 +371,7 @@ config_bpf_program(struct bpf_program *prog)
339371
}
340372
pr_debug("bpf: config '%s' is ok\n", config_str);
341373

374+
set_priv:
342375
err = bpf_program__set_priv(prog, priv, clear_prog_priv);
343376
if (err) {
344377
pr_debug("Failed to set priv for program '%s'\n", config_str);
@@ -387,7 +420,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
387420
size_t prologue_cnt = 0;
388421
int i, err;
389422

390-
if (IS_ERR(priv) || !priv)
423+
if (IS_ERR(priv) || !priv || priv->is_tp)
391424
goto errout;
392425

393426
pev = &priv->pev;
@@ -544,6 +577,11 @@ static int hook_load_preprocessor(struct bpf_program *prog)
544577
return -BPF_LOADER_ERRNO__INTERNAL;
545578
}
546579

580+
if (priv->is_tp) {
581+
priv->need_prologue = false;
582+
return 0;
583+
}
584+
547585
pev = &priv->pev;
548586
for (i = 0; i < pev->ntevs; i++) {
549587
struct probe_trace_event *tev = &pev->tevs[i];
@@ -610,6 +648,13 @@ int bpf__probe(struct bpf_object *obj)
610648
err = PTR_ERR(priv);
611649
goto out;
612650
}
651+
652+
if (priv->is_tp) {
653+
bpf_program__set_tracepoint(prog);
654+
continue;
655+
}
656+
657+
bpf_program__set_kprobe(prog);
613658
pev = &priv->pev;
614659

615660
err = convert_perf_probe_events(pev, 1);
@@ -650,7 +695,7 @@ int bpf__unprobe(struct bpf_object *obj)
650695
struct bpf_prog_priv *priv = bpf_program__priv(prog);
651696
int i;
652697

653-
if (IS_ERR(priv) || !priv)
698+
if (IS_ERR(priv) || !priv || priv->is_tp)
654699
continue;
655700

656701
for (i = 0; i < priv->pev.ntevs; i++) {
@@ -711,6 +756,16 @@ int bpf__foreach_event(struct bpf_object *obj,
711756
return -BPF_LOADER_ERRNO__INTERNAL;
712757
}
713758

759+
if (priv->is_tp) {
760+
fd = bpf_program__fd(prog);
761+
err = (*func)(priv->sys_name, priv->evt_name, fd, arg);
762+
if (err) {
763+
pr_debug("bpf: tracepoint call back failed, stop iterate\n");
764+
return err;
765+
}
766+
continue;
767+
}
768+
714769
pev = &priv->pev;
715770
for (i = 0; i < pev->ntevs; i++) {
716771
tev = &pev->tevs[i];

0 commit comments

Comments
 (0)