'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", &param.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/

Reply via email to