Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932745AbbFIFwr (ORCPT ); Tue, 9 Jun 2015 01:52:47 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:40935 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932304AbbFIFvj (ORCPT ); Tue, 9 Jun 2015 01:51:39 -0400 From: Wang Nan To: , , , , , , , , , , CC: , , , , Subject: [RFC PATCH v6 26/32] perf tools: Parse probe points of eBPF programs during preparation Date: Tue, 9 Jun 2015 05:50:30 +0000 Message-ID: <1433829036-23687-27-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1433829036-23687-1-git-send-email-wangnan0@huawei.com> References: <1433829036-23687-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.200] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.55767ED9.005D,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: d939f4d672cce729195c3e69ac8b68a1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5480 Lines: 213 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 all 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. This patch utilizes bpf_program__set_private(), bind perf_probe_event with bpf program by private field. Signed-off-by: Wang Nan --- tools/perf/util/bpf-loader.c | 124 ++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/bpf-loader.h | 2 + 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index f33fd47..d786efc 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -10,6 +10,8 @@ #include "debug.h" #include "util.h" #include "bpf-loader.h" +#include "probe-event.h" +#include "probe-finder.h" #define DEFINE_PRINT_FN(name, level) \ static int libbpf_##name(const char *fmt, ...) \ @@ -29,6 +31,9 @@ DEFINE_PRINT_FN(debug, 1) static bool libbpf_initialized = false; +static struct perf_probe_event probe_event_array[MAX_PROBES]; +static size_t nr_probe_events; + /* * Group all bpf related programs together. Futher we can config them * using perf_default_config(). @@ -211,9 +216,117 @@ out: return err; } +static struct perf_probe_event * +alloc_perf_probe_event(void) +{ + struct perf_probe_event *pev; + int n = nr_probe_events; + if (n >= MAX_PROBES) { + pr_err("bpf: too many events, increase MAX_PROBES\n"); + return NULL; + } + + nr_probe_events = n + 1; + pev = &probe_event_array[n]; + bzero(pev, sizeof(*pev)); + return pev; +} + +struct bpf_prog_priv { + struct perf_probe_event *pev; +}; + +static void +bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused, + void *_priv) +{ + struct bpf_prog_priv *priv = _priv; + if (priv->pev) + clear_perf_probe_event(priv->pev); + free(priv); +} + +static int +config_bpf_program(struct bpf_program *prog) +{ + struct perf_probe_event *pev = alloc_perf_probe_event(); + struct bpf_prog_priv *priv = NULL; + const char *config_str; + int err; + + /* pr_err has been done by alloc_perf_probe_event */ + if (!pev) + return -ENOMEM; + + err = bpf_program__get_title(prog, &config_str, false); + if (err || !config_str) { + pr_err("bpf: unable to get title for program\n"); + return -EINVAL; + } + + pr_debug("bpf: config program '%s'\n", config_str); + err = parse_perf_probe_command(config_str, pev); + if (err < 0) { + pr_err("bpf: '%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: '%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: strdup failed\n"); + err = -ENOMEM; + goto errout; + } + + if (!pev->event) { + pr_err("bpf: '%s': event name is missing\n", + config_str); + err = -EINVAL; + goto errout; + } + + pr_debug("bpf: config '%s' is ok\n", config_str); + + priv = calloc(1, sizeof(*priv)); + if (!priv) { + pr_err("bpf: failed to alloc memory\n"); + err = -ENOMEM; + goto errout; + } + + priv->pev = pev; + + err = bpf_program__set_private(prog, priv, + bpf_prog_priv__clear); + if (err) { + pr_err("bpf: set program private failed\n"); + err = -ENOMEM; + goto errout; + } + return 0; + +errout: + if (pev) + clear_perf_probe_event(pev); + if (priv) + free(priv); + return err; +} + int bpf__prepare_load(const char *filename, bool source) { struct bpf_object *obj; + struct bpf_program *prog; + int err = 0; if (!libbpf_initialized) libbpf_set_print(libbpf_warning, @@ -223,7 +336,6 @@ int bpf__prepare_load(const char *filename, bool source) if (source) { void *obj_buf; size_t obj_buf_sz; - int err; err = bpf__compile(filename, &obj_buf, &obj_buf_sz); if (err) @@ -238,12 +350,20 @@ int bpf__prepare_load(const char *filename, bool source) return -EINVAL; } + bpf_object__for_each_program(prog, obj) { + err = config_bpf_program(prog); + if (err) + goto errout; + } + /* * Throw object pointer away: it will be retrived using * bpf_objects iterater. */ - return 0; +errout: + bpf_object__close(obj); + return err; } void bpf__clear(void) diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index edc211e..2ed7a16 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -17,6 +17,8 @@ struct bpf_param { extern struct bpf_param bpf_param; extern int perf_bpf_config(const char *var, const char *value); +#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" + #ifdef HAVE_LIBBPF_SUPPORT int bpf__prepare_load(const char *filename, bool source); -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/