From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Wang Nan <wangnan0@huawei.com>
Cc: masami.hiramatsu.pt@hitachi.com, ast@kernel.org,
lizefan@huawei.com, pi3orama@163.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 03/12] perf tools: Allow BPF program attach to uprobe events
Date: Fri, 13 Nov 2015 12:39:41 -0300 [thread overview]
Message-ID: <20151113153941.GJ7160@kernel.org> (raw)
In-Reply-To: <1447417761-156094-4-git-send-email-wangnan0@huawei.com>
Em Fri, Nov 13, 2015 at 12:29:12PM +0000, Wang Nan escreveu:
> This patch appends new syntax to BPF object section name to support
> probing at uprobe event. Now we can use BPF program like this:
>
> SEC(
> "exec=/lib64/libc.so.6\n"
> "libcwrite=__write"
> )
> int libcwrite(void *ctx)
> {
> return 1;
> }
>
> Where, in section name of a program, before the main config string,
> we can use 'key=value' style options. Now the only option key "exec"
> is for uprobe probing.
>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> 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/bpf-loader.c | 122 ++++++++++++++++++++++++++++++++++++++++---
> tools/perf/util/bpf-loader.h | 1 +
> 2 files changed, 117 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
> index 4c50411..5f5505d 100644
> --- a/tools/perf/util/bpf-loader.c
> +++ b/tools/perf/util/bpf-loader.c
> @@ -110,6 +110,115 @@ bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
> }
>
> static int
> +config__exec(const char *value, struct perf_probe_event *pev)
> +{
> + pev->uprobes = true;
> + pev->target = strdup(value);
Shouldn't we check if this fails and return some failure error
accordingly?
> + return 0;
> +}
> +
> +static struct {
> + const char *key;
> + const char *usage;
> + const char *desc;
> + int (*func)(const char *, struct perf_probe_event *);
> +} bpf_config_terms[] = {
> + {
> + "exec",
> + "exec=<full path of file>",
> + "Set uprobe target",
> + config__exec,
> + },
Even with the definition of the struct right above it, please use named
initializers, i.e. turn the avove into:
+ {
+ .key = "exec",
+ .usage = "exec=<full path of file>",
+ .desc = "Set uprobe target",
+ .func = config__exec,
+ },
> +};
> +
> +static int
> +do_config(const char *key, const char *value,
> + struct perf_probe_event *pev)
> +{
> + unsigned int i;
> +
> + pr_debug("config bpf program: %s=%s\n", key, value);
> + for (i = 0; i < ARRAY_SIZE(bpf_config_terms); i++)
> + if (strcmp(key, bpf_config_terms[i].key) == 0)
> + return bpf_config_terms[i].func(value, pev);
> +
> + pr_debug("BPF: ERROR: invalid config option in object: %s=%s\n",
> + key, value);
> +
> + pr_debug("\nHint: Currently valid options are:\n");
> + for (i = 0; i < ARRAY_SIZE(bpf_config_terms); i++)
> + pr_debug("\t%s:\t%s\n", bpf_config_terms[i].usage,
> + bpf_config_terms[i].desc);
> + pr_debug("\n");
> +
> + return -BPF_LOADER_ERRNO__CONFIG_TERM;
> +}
> +
> +static const char *
> +parse_config_kvpair(const char *config_str, struct perf_probe_event *pev)
> +{
> + char *text = strdup(config_str);
> + char *sep, *line;
> + const char *main_str = NULL;
> + int err = 0;
> +
> + if (!text) {
See, here you do it correctly, checking the strdup() return, providing
some debugging for -v usage _and_ the right ERR_PTR() return, well done!
> + pr_debug("No enough memory: dup config_str failed\n");
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + line = text;
> + while ((sep = strchr(line, '\n'))) {
> + char *equ;
> +
> + *sep = '\0';
> + equ = strchr(line, '=');
> + if (!equ) {
> + pr_warning("WARNING: invalid config in BPF object: %s\n",
> + line);
> + pr_warning("\tShould be 'key=value'.\n");
> + goto nextline;
> + }
> + *equ = '\0';
> +
> + err = do_config(line, equ + 1, pev);
> + if (err)
> + break;
> +nextline:
> + line = sep + 1;
> + }
> +
> + if (!err)
> + main_str = config_str + (line - text);
> + free(text);
> +
> + if (err)
> + return ERR_PTR(err);
> +
> + return main_str;
No biggie, but doing:
return err ? ERR_PTR(err) : main_str;
Is more compact and clear :-)
> +}
> +
> +static int
> +parse_config(const char *config_str, struct perf_probe_event *pev)
> +{
> + const char *main_str;
> + int err;
> +
> + main_str = parse_config_kvpair(config_str, pev);
Also just for compactness, just a suggestion, doing:
const char *main_str = parse_config_kvpair(config_str, pev);
Saves screen real state :-)
> + if (IS_ERR(main_str))
> + return PTR_ERR(main_str);
> +
> + err = parse_perf_probe_command(main_str, pev);
> + if (err < 0) {
> + pr_debug("bpf: '%s' is not a valid config string\n",
> + config_str);
> + /* parse failed, don't need clear pev. */
> + return -BPF_LOADER_ERRNO__CONFIG;
> + }
> + return 0;
> +}
> +
> +static int
> config_bpf_program(struct bpf_program *prog)
> {
> struct perf_probe_event *pev = NULL;
> @@ -131,13 +240,9 @@ config_bpf_program(struct bpf_program *prog)
> pev = &priv->pev;
>
> pr_debug("bpf: config program '%s'\n", config_str);
> - err = parse_perf_probe_command(config_str, pev);
> - if (err < 0) {
> - pr_debug("bpf: '%s' is not a valid config string\n",
> - config_str);
> - err = -BPF_LOADER_ERRNO__CONFIG;
> + err = parse_config(config_str, pev);
> + if (err)
> goto errout;
> - }
>
> if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
> pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
> @@ -340,6 +445,7 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
> [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string",
> [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error",
> [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet",
> + [ERRCODE_OFFSET(CONFIG_TERM)] = "Invalid config term in config string",
> };
>
> static int
> @@ -420,6 +526,10 @@ int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
> int err, char *buf, size_t size)
> {
> bpf__strerror_head(err, buf, size);
> + case BPF_LOADER_ERRNO__CONFIG_TERM: {
> + scnprintf(buf, size, "%s (add -v to see detail)", emsg);
> + break;
> + }
> bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
> bpf__strerror_entry(EACCES, "You need to be root");
> bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
> diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
> index 9caf3ae..d19f5c5 100644
> --- a/tools/perf/util/bpf-loader.h
> +++ b/tools/perf/util/bpf-loader.h
> @@ -20,6 +20,7 @@ enum bpf_loader_errno {
> BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */
> BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */
> BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */
> + BPF_LOADER_ERRNO__CONFIG_TERM, /* Invalid config term in config term */
> __BPF_LOADER_ERRNO__END,
> };
>
> --
> 1.8.3.4
next prev parent reply other threads:[~2015-11-13 15:39 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-13 12:29 [PATCH 00/12] perf tools: bpf: Improve BPF program ability Wang Nan
2015-11-13 12:29 ` [PATCH 01/12] perf probe: Fix memory leaking on faiulre by clearing all probe_trace_events Wang Nan
2015-11-18 6:19 ` [tip:perf/urgent] perf probe: Fix memory leaking on failure " tip-bot for Masami Hiramatsu
2015-11-13 12:29 ` [PATCH 02/12] perf probe: Clear probe_trace_event when add_probe_trace_event() fails Wang Nan
2015-11-13 15:50 ` Arnaldo Carvalho de Melo
2015-11-18 6:19 ` [tip:perf/urgent] " tip-bot for Wang Nan
2015-11-13 12:29 ` [PATCH 03/12] perf tools: Allow BPF program attach to uprobe events Wang Nan
2015-11-13 15:39 ` Arnaldo Carvalho de Melo [this message]
2015-11-13 12:29 ` [PATCH 04/12] perf tools: Allow BPF program attach to modules Wang Nan
2015-11-13 15:40 ` Arnaldo Carvalho de Melo
2015-11-13 12:29 ` [PATCH 05/12] perf tools: Allow BPF program config probing options Wang Nan
2015-11-13 15:46 ` Arnaldo Carvalho de Melo
2015-11-16 9:11 ` Wangnan (F)
2015-11-13 12:29 ` [PATCH 06/12] bpf tools: Load a program with different instances using preprocessor Wang Nan
2015-11-13 12:29 ` [PATCH 07/12] perf tools: Add BPF_PROLOGUE config options for further patches Wang Nan
2015-11-13 12:29 ` [PATCH 08/12] perf tools: Compile dwarf-regs.c if CONFIG_BPF_PROLOGUE is on Wang Nan
2015-11-13 12:29 ` [PATCH 09/12] perf tools: Add prologue for BPF programs for fetching arguments Wang Nan
2015-11-13 12:29 ` [PATCH 10/12] perf tools: Generate prologue for BPF programs Wang Nan
2015-11-13 12:29 ` [PATCH 11/12] perf test: Test BPF prologue Wang Nan
2015-11-13 12:29 ` [PATCH 12/12] perf tools: Use same BPF program if arguments are identical Wang Nan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151113153941.GJ7160@kernel.org \
--to=acme@kernel.org \
--cc=ast@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan@huawei.com \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=pi3orama@163.com \
--cc=wangnan0@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.