'perf bpf record' will be implemented to load eBPF object file then start recording on events defined in it. This patch only adds a '--object' option for selecting object file. Other arguments are directly passed to cmd_record.
Example: # perf bpf --object obj1.o --object obj2.o -- -a command-to-record Signed-off-by: Wang Nan <wangn...@huawei.com> --- tools/perf/builtin-bpf.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c index a8858e2..b5c613f 100644 --- a/tools/perf/builtin-bpf.c +++ b/tools/perf/builtin-bpf.c @@ -48,14 +48,121 @@ static void print_usage(void) exit(129); } -static const char * const bpf_subcommands[] = { NULL }; +static const char * const bpf_record_usage[] = { + "perf bpf record [<options>] -- [options passed to record]", + NULL +}; + +struct param { + struct strlist *object_file_names; +} param; + +static int add_bpf_object_file(const struct option *opt, + const char *str, + int unset __maybe_unused) +{ + struct strlist **filenames = (struct strlist **)opt->value; + + if (!*filenames) + *filenames = strlist__new(true, NULL); + + if (!*filenames) { + pr_err("alloc strlist failed\n"); + return -ENOMEM; + } + + strlist__add(*filenames, str); + return 0; +} + +static int start_bpf_record(int argc, const char **argv) +{ + int i, new_argc, err, pos = 0; + const char **new_argv; + + new_argc = argc + 1; + new_argv = malloc((new_argc + 1) * sizeof(const char *)); + if (!new_argv) { + pr_err("malloc failed\n"); + return -ENOMEM; + } + bzero(new_argv, sizeof(const char *) * (new_argc + 1)); + + new_argv[pos++] = strdup("bpf record --"); + + for (i = 0; i < argc; i++) { + new_argv[pos++] = strdup(argv[i]); + if (!new_argv[pos - 1]) { + pr_err("strdup failed\n"); + err = -ENOMEM; + goto errout; + } + } + + return cmd_record(new_argc, new_argv, NULL); + +errout: + if (new_argv) { + for (i = 0; i < pos; i++) + free((void *)new_argv[i]); + free(new_argv); + } + return err; +} + +static int cmd_bpf_record(int argc, const char **argv, + const char *prefix __maybe_unused) +{ + /* + * Options in perf-record may be mirrored here. This command + * should add '-e' options to cmd_record. + */ + static const struct option options[] = { + OPT_CALLBACK(0, "object", ¶m.object_file_names, + "file", "eBPF object file name", + add_bpf_object_file), + OPT_END() + }; + struct str_node *str_node; + + argc = parse_options(argc, argv, options, + bpf_record_usage, PARSE_OPT_KEEP_DASHDASH); + + if (!param.object_file_names) { + pr_err("At least one '--object' option is needed to " + "select an eBPF object file\n"); + goto usage; + } + + if (!argv || strcmp(argv[0], "--")) { + pr_err("Should use '--' to pass options to perf " + "record\n"); + goto usage; + } + + /* skip "--" */ + argc--; + argv++; + + strlist__for_each(str_node, param.object_file_names) + pr_debug("loading %s\n", str_node->s); + + return start_bpf_record(argc, argv); +usage: + usage_with_options(bpf_record_usage, options); + return -1; +} + + +static const char * const bpf_subcommands[] = { "record", NULL }; static struct bpf_cmd bpf_cmds[] = { + { "record", "load eBPF program into kernel then start record on events in it", cmd_bpf_record }, { .name = NULL, }, }; int cmd_bpf(int argc, const char **argv, - const char *prefix __maybe_unused) + const char *prefix) { struct bpf_cmd *cmd; const char *cmdstr; -- 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/