]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bpftool: Use bpf_obj_get_info_by_fd directly
authorDave Marchevsky <davemarchevsky@fb.com>
Mon, 1 Nov 2021 22:43:55 +0000 (15:43 -0700)
committerAndrii Nakryiko <andrii@kernel.org>
Wed, 3 Nov 2021 18:25:32 +0000 (11:25 -0700)
To prepare for impending deprecation of libbpf's
bpf_program__get_prog_info_linear, migrate uses of this function to use
bpf_obj_get_info_by_fd.

Since the profile_target_name and dump_prog_id_as_func_ptr helpers were
only looking at the first func_info, avoid grabbing the rest to save a
malloc. For do_dump, add a more full-featured helper, but avoid
free/realloc of buffer when possible for multi-prog dumps.

Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20211101224357.2651181-3-davemarchevsky@fb.com
tools/bpf/bpftool/btf_dumper.c
tools/bpf/bpftool/prog.c

index 6934e8634b94bf154c00a0f9cfa321cb0536c93b..f5dddf8ef404b1eec57218e8eeba847d068d9061 100644 (file)
@@ -32,14 +32,16 @@ static int dump_prog_id_as_func_ptr(const struct btf_dumper *d,
                                    const struct btf_type *func_proto,
                                    __u32 prog_id)
 {
-       struct bpf_prog_info_linear *prog_info = NULL;
        const struct btf_type *func_type;
+       int prog_fd = -1, func_sig_len;
+       struct bpf_prog_info info = {};
+       __u32 info_len = sizeof(info);
        const char *prog_name = NULL;
-       struct bpf_func_info *finfo;
        struct btf *prog_btf = NULL;
-       struct bpf_prog_info *info;
-       int prog_fd, func_sig_len;
+       struct bpf_func_info finfo;
+       __u32 finfo_rec_size;
        char prog_str[1024];
+       int err;
 
        /* Get the ptr's func_proto */
        func_sig_len = btf_dump_func(d->btf, prog_str, func_proto, NULL, 0,
@@ -55,22 +57,27 @@ static int dump_prog_id_as_func_ptr(const struct btf_dumper *d,
        if (prog_fd < 0)
                goto print;
 
-       prog_info = bpf_program__get_prog_info_linear(prog_fd,
-                                               1UL << BPF_PROG_INFO_FUNC_INFO);
-       close(prog_fd);
-       if (IS_ERR(prog_info)) {
-               prog_info = NULL;
+       err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+       if (err)
                goto print;
-       }
-       info = &prog_info->info;
 
-       if (!info->btf_id || !info->nr_func_info)
+       if (!info.btf_id || !info.nr_func_info)
+               goto print;
+
+       finfo_rec_size = info.func_info_rec_size;
+       memset(&info, 0, sizeof(info));
+       info.nr_func_info = 1;
+       info.func_info_rec_size = finfo_rec_size;
+       info.func_info = ptr_to_u64(&finfo);
+
+       err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+       if (err)
                goto print;
-       prog_btf = btf__load_from_kernel_by_id(info->btf_id);
+
+       prog_btf = btf__load_from_kernel_by_id(info.btf_id);
        if (libbpf_get_error(prog_btf))
                goto print;
-       finfo = u64_to_ptr(info->func_info);
-       func_type = btf__type_by_id(prog_btf, finfo->type_id);
+       func_type = btf__type_by_id(prog_btf, finfo.type_id);
        if (!func_type || !btf_is_func(func_type))
                goto print;
 
@@ -92,7 +99,8 @@ print:
        prog_str[sizeof(prog_str) - 1] = '\0';
        jsonw_string(d->jw, prog_str);
        btf__free(prog_btf);
-       free(prog_info);
+       if (prog_fd >= 0)
+               close(prog_fd);
        return 0;
 }
 
index 515d229526026414ae310234be9832ba300bbb3a..dea7a49ec26e8485deb485ff4efd7a951a1888f6 100644 (file)
@@ -100,6 +100,76 @@ static enum bpf_attach_type parse_attach_type(const char *str)
        return __MAX_BPF_ATTACH_TYPE;
 }
 
+static int prep_prog_info(struct bpf_prog_info *const info, enum dump_mode mode,
+                         void **info_data, size_t *const info_data_sz)
+{
+       struct bpf_prog_info holder = {};
+       size_t needed = 0;
+       void *ptr;
+
+       if (mode == DUMP_JITED) {
+               holder.jited_prog_len = info->jited_prog_len;
+               needed += info->jited_prog_len;
+       } else {
+               holder.xlated_prog_len = info->xlated_prog_len;
+               needed += info->xlated_prog_len;
+       }
+
+       holder.nr_jited_ksyms = info->nr_jited_ksyms;
+       needed += info->nr_jited_ksyms * sizeof(__u64);
+
+       holder.nr_jited_func_lens = info->nr_jited_func_lens;
+       needed += info->nr_jited_func_lens * sizeof(__u32);
+
+       holder.nr_func_info = info->nr_func_info;
+       holder.func_info_rec_size = info->func_info_rec_size;
+       needed += info->nr_func_info * info->func_info_rec_size;
+
+       holder.nr_line_info = info->nr_line_info;
+       holder.line_info_rec_size = info->line_info_rec_size;
+       needed += info->nr_line_info * info->line_info_rec_size;
+
+       holder.nr_jited_line_info = info->nr_jited_line_info;
+       holder.jited_line_info_rec_size = info->jited_line_info_rec_size;
+       needed += info->nr_jited_line_info * info->jited_line_info_rec_size;
+
+       if (needed > *info_data_sz) {
+               ptr = realloc(*info_data, needed);
+               if (!ptr)
+                       return -1;
+
+               *info_data = ptr;
+               *info_data_sz = needed;
+       }
+       ptr = *info_data;
+
+       if (mode == DUMP_JITED) {
+               holder.jited_prog_insns = ptr_to_u64(ptr);
+               ptr += holder.jited_prog_len;
+       } else {
+               holder.xlated_prog_insns = ptr_to_u64(ptr);
+               ptr += holder.xlated_prog_len;
+       }
+
+       holder.jited_ksyms = ptr_to_u64(ptr);
+       ptr += holder.nr_jited_ksyms * sizeof(__u64);
+
+       holder.jited_func_lens = ptr_to_u64(ptr);
+       ptr += holder.nr_jited_func_lens * sizeof(__u32);
+
+       holder.func_info = ptr_to_u64(ptr);
+       ptr += holder.nr_func_info * holder.func_info_rec_size;
+
+       holder.line_info = ptr_to_u64(ptr);
+       ptr += holder.nr_line_info * holder.line_info_rec_size;
+
+       holder.jited_line_info = ptr_to_u64(ptr);
+       ptr += holder.nr_jited_line_info * holder.jited_line_info_rec_size;
+
+       *info = holder;
+       return 0;
+}
+
 static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
 {
        struct timespec real_time_ts, boot_time_ts;
@@ -803,16 +873,18 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
 
 static int do_dump(int argc, char **argv)
 {
-       struct bpf_prog_info_linear *info_linear;
+       struct bpf_prog_info info;
+       __u32 info_len = sizeof(info);
+       size_t info_data_sz = 0;
+       void *info_data = NULL;
        char *filepath = NULL;
        bool opcodes = false;
        bool visual = false;
        enum dump_mode mode;
        bool linum = false;
-       int *fds = NULL;
        int nb_fds, i = 0;
+       int *fds = NULL;
        int err = -1;
-       __u64 arrays;
 
        if (is_prefix(*argv, "jited")) {
                if (disasm_init())
@@ -872,43 +944,44 @@ static int do_dump(int argc, char **argv)
                goto exit_close;
        }
 
-       if (mode == DUMP_JITED)
-               arrays = 1UL << BPF_PROG_INFO_JITED_INSNS;
-       else
-               arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS;
-
-       arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS;
-       arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
-       arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
-       arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
-       arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
-
        if (json_output && nb_fds > 1)
                jsonw_start_array(json_wtr);    /* root array */
        for (i = 0; i < nb_fds; i++) {
-               info_linear = bpf_program__get_prog_info_linear(fds[i], arrays);
-               if (IS_ERR_OR_NULL(info_linear)) {
+               memset(&info, 0, sizeof(info));
+
+               err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len);
+               if (err) {
+                       p_err("can't get prog info: %s", strerror(errno));
+                       break;
+               }
+
+               err = prep_prog_info(&info, mode, &info_data, &info_data_sz);
+               if (err) {
+                       p_err("can't grow prog info_data");
+                       break;
+               }
+
+               err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len);
+               if (err) {
                        p_err("can't get prog info: %s", strerror(errno));
                        break;
                }
 
                if (json_output && nb_fds > 1) {
                        jsonw_start_object(json_wtr);   /* prog object */
-                       print_prog_header_json(&info_linear->info);
+                       print_prog_header_json(&info);
                        jsonw_name(json_wtr, "insns");
                } else if (nb_fds > 1) {
-                       print_prog_header_plain(&info_linear->info);
+                       print_prog_header_plain(&info);
                }
 
-               err = prog_dump(&info_linear->info, mode, filepath, opcodes,
-                               visual, linum);
+               err = prog_dump(&info, mode, filepath, opcodes, visual, linum);
 
                if (json_output && nb_fds > 1)
                        jsonw_end_object(json_wtr);     /* prog object */
                else if (i != nb_fds - 1 && nb_fds > 1)
                        printf("\n");
 
-               free(info_linear);
                if (err)
                        break;
                close(fds[i]);
@@ -920,6 +993,7 @@ exit_close:
        for (; i < nb_fds; i++)
                close(fds[i]);
 exit_free:
+       free(info_data);
        free(fds);
        return err;
 }
@@ -2016,41 +2090,58 @@ static void profile_print_readings(void)
 
 static char *profile_target_name(int tgt_fd)
 {
-       struct bpf_prog_info_linear *info_linear;
-       struct bpf_func_info *func_info;
+       struct bpf_func_info func_info;
+       struct bpf_prog_info info = {};
+       __u32 info_len = sizeof(info);
        const struct btf_type *t;
+       __u32 func_info_rec_size;
        struct btf *btf = NULL;
        char *name = NULL;
+       int err;
 
-       info_linear = bpf_program__get_prog_info_linear(
-               tgt_fd, 1UL << BPF_PROG_INFO_FUNC_INFO);
-       if (IS_ERR_OR_NULL(info_linear)) {
-               p_err("failed to get info_linear for prog FD %d", tgt_fd);
-               return NULL;
+       err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len);
+       if (err) {
+               p_err("failed to bpf_obj_get_info_by_fd for prog FD %d", tgt_fd);
+               goto out;
        }
 
-       if (info_linear->info.btf_id == 0) {
+       if (info.btf_id == 0) {
                p_err("prog FD %d doesn't have valid btf", tgt_fd);
                goto out;
        }
 
-       btf = btf__load_from_kernel_by_id(info_linear->info.btf_id);
+       func_info_rec_size = info.func_info_rec_size;
+       if (info.nr_func_info == 0) {
+               p_err("bpf_obj_get_info_by_fd for prog FD %d found 0 func_info", tgt_fd);
+               goto out;
+       }
+
+       memset(&info, 0, sizeof(info));
+       info.nr_func_info = 1;
+       info.func_info_rec_size = func_info_rec_size;
+       info.func_info = ptr_to_u64(&func_info);
+
+       err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len);
+       if (err) {
+               p_err("failed to get func_info for prog FD %d", tgt_fd);
+               goto out;
+       }
+
+       btf = btf__load_from_kernel_by_id(info.btf_id);
        if (libbpf_get_error(btf)) {
                p_err("failed to load btf for prog FD %d", tgt_fd);
                goto out;
        }
 
-       func_info = u64_to_ptr(info_linear->info.func_info);
-       t = btf__type_by_id(btf, func_info[0].type_id);
+       t = btf__type_by_id(btf, func_info.type_id);
        if (!t) {
                p_err("btf %d doesn't have type %d",
-                     info_linear->info.btf_id, func_info[0].type_id);
+                     info.btf_id, func_info.type_id);
                goto out;
        }
        name = strdup(btf__name_by_offset(btf, t->name_off));
 out:
        btf__free(btf);
-       free(info_linear);
        return name;
 }