This patch parses section name of each program, and creates corresponding 'struct perf_probe_event' structure.
parse_perf_probe_command() is used to do the main parsing works. Parsing result is stored into a global array. This is because add_perf_probe_events() is non-reentrantable. In following patch, add_perf_probe_events will be introduced to insert kprobes. It accepts an array of 'struct perf_probe_event' and do works in one call. Define PERF_BPF_PROBE_GROUP as "perf_bpf_probe", which will be used as group name of all eBPF probing points. Signed-off-by: Wang Nan <wangn...@huawei.com> --- tools/perf/util/bpf-loader.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 67bfb62..3dc9b61 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -29,6 +29,7 @@ DEFINE_PRINT_FN(debug, 1) static bool libbpf_inited = false; #define MAX_OBJECTS 128 +#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" struct { struct bpf_object *objects[MAX_OBJECTS]; @@ -36,10 +37,78 @@ struct { struct { struct bpf_prog_handler *prog; + struct perf_probe_event *pevent; } progs[MAX_PROBES]; size_t nr_progs; + + struct perf_probe_event event_array[MAX_PROBES]; + size_t nr_events; } params; +static struct perf_probe_event * +alloc_perf_probe_event(void) +{ + struct perf_probe_event *pev; + int n = params.nr_events; + + if (n >= MAX_PROBES) { + pr_err("bpf: too many events, increase MAX_PROBES\n"); + return NULL; + } + + params.nr_events = n + 1; + pev = ¶ms.event_array[n]; + bzero(pev, sizeof(*pev)); + return pev; +} + +static int +bpf_do_config(size_t prog_idx, const char *config_str) +{ + struct perf_probe_event *pev = alloc_perf_probe_event(); + int err = 0; + + if (!pev) + return -ENOMEM; + + if ((err = parse_perf_probe_command(config_str, pev)) < 0) { + pr_err("bpf config: %s is not a valid config string\n", + config_str); + /* parse failed, don't need clear pev. */ + return -EINVAL; + } + + if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { + pr_err("bpf config: '%s': group for event is set " + "and not '%s'.\n", config_str, + PERF_BPF_PROBE_GROUP); + err = -EINVAL; + goto errout; + } else if (!pev->group) + pev->group = strdup(PERF_BPF_PROBE_GROUP); + + if (!pev->group) { + pr_err("bpf config: strdup failed\n"); + err = -ENOMEM; + goto errout; + } + + if (!pev->event) { + pr_err("bpf config: '%s': event name is missing\n", + config_str); + err = -EINVAL; + goto errout; + } + + pr_debug("bpf config: config '%s' ok\n", config_str); + params.progs[prog_idx].pevent = pev; + return 0; +errout: + if (pev) + clear_perf_probe_event(pev); + return err; +} + int bpf_prepare_load(const char *filename) { struct bpf_object *obj; @@ -81,6 +150,8 @@ int bpf_prepare_load(const char *filename) return -EINVAL; } pr_debug("bpf: add program '%s'\n", title); + + bpf_do_config(params.nr_progs - 1, title); } return 0; } @@ -89,6 +160,9 @@ void bpf_clear(void) { size_t i; + for (i = 0; i < params.nr_events; i++) + clear_perf_probe_event(¶ms.event_array[i]); + for (i = 0; i < params.nr_objects; i++) bpf_close_object(params.objects[i]); } -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/