Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpftool: Use bpf_obj_get_info_by_fd directly

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

authored by

Dave Marchevsky and committed by
Andrii Nakryiko
c59765cf 60f27075

+149 -50
+24 -16
tools/bpf/bpftool/btf_dumper.c
··· 32 32 const struct btf_type *func_proto, 33 33 __u32 prog_id) 34 34 { 35 - struct bpf_prog_info_linear *prog_info = NULL; 36 35 const struct btf_type *func_type; 36 + int prog_fd = -1, func_sig_len; 37 + struct bpf_prog_info info = {}; 38 + __u32 info_len = sizeof(info); 37 39 const char *prog_name = NULL; 38 - struct bpf_func_info *finfo; 39 40 struct btf *prog_btf = NULL; 40 - struct bpf_prog_info *info; 41 - int prog_fd, func_sig_len; 41 + struct bpf_func_info finfo; 42 + __u32 finfo_rec_size; 42 43 char prog_str[1024]; 44 + int err; 43 45 44 46 /* Get the ptr's func_proto */ 45 47 func_sig_len = btf_dump_func(d->btf, prog_str, func_proto, NULL, 0, ··· 57 55 if (prog_fd < 0) 58 56 goto print; 59 57 60 - prog_info = bpf_program__get_prog_info_linear(prog_fd, 61 - 1UL << BPF_PROG_INFO_FUNC_INFO); 62 - close(prog_fd); 63 - if (IS_ERR(prog_info)) { 64 - prog_info = NULL; 58 + err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 59 + if (err) 65 60 goto print; 66 - } 67 - info = &prog_info->info; 68 61 69 - if (!info->btf_id || !info->nr_func_info) 62 + if (!info.btf_id || !info.nr_func_info) 70 63 goto print; 71 - prog_btf = btf__load_from_kernel_by_id(info->btf_id); 64 + 65 + finfo_rec_size = info.func_info_rec_size; 66 + memset(&info, 0, sizeof(info)); 67 + info.nr_func_info = 1; 68 + info.func_info_rec_size = finfo_rec_size; 69 + info.func_info = ptr_to_u64(&finfo); 70 + 71 + err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 72 + if (err) 73 + goto print; 74 + 75 + prog_btf = btf__load_from_kernel_by_id(info.btf_id); 72 76 if (libbpf_get_error(prog_btf)) 73 77 goto print; 74 - finfo = u64_to_ptr(info->func_info); 75 - func_type = btf__type_by_id(prog_btf, finfo->type_id); 78 + func_type = btf__type_by_id(prog_btf, finfo.type_id); 76 79 if (!func_type || !btf_is_func(func_type)) 77 80 goto print; 78 81 ··· 99 92 prog_str[sizeof(prog_str) - 1] = '\0'; 100 93 jsonw_string(d->jw, prog_str); 101 94 btf__free(prog_btf); 102 - free(prog_info); 95 + if (prog_fd >= 0) 96 + close(prog_fd); 103 97 return 0; 104 98 } 105 99
+125 -34
tools/bpf/bpftool/prog.c
··· 100 100 return __MAX_BPF_ATTACH_TYPE; 101 101 } 102 102 103 + static int prep_prog_info(struct bpf_prog_info *const info, enum dump_mode mode, 104 + void **info_data, size_t *const info_data_sz) 105 + { 106 + struct bpf_prog_info holder = {}; 107 + size_t needed = 0; 108 + void *ptr; 109 + 110 + if (mode == DUMP_JITED) { 111 + holder.jited_prog_len = info->jited_prog_len; 112 + needed += info->jited_prog_len; 113 + } else { 114 + holder.xlated_prog_len = info->xlated_prog_len; 115 + needed += info->xlated_prog_len; 116 + } 117 + 118 + holder.nr_jited_ksyms = info->nr_jited_ksyms; 119 + needed += info->nr_jited_ksyms * sizeof(__u64); 120 + 121 + holder.nr_jited_func_lens = info->nr_jited_func_lens; 122 + needed += info->nr_jited_func_lens * sizeof(__u32); 123 + 124 + holder.nr_func_info = info->nr_func_info; 125 + holder.func_info_rec_size = info->func_info_rec_size; 126 + needed += info->nr_func_info * info->func_info_rec_size; 127 + 128 + holder.nr_line_info = info->nr_line_info; 129 + holder.line_info_rec_size = info->line_info_rec_size; 130 + needed += info->nr_line_info * info->line_info_rec_size; 131 + 132 + holder.nr_jited_line_info = info->nr_jited_line_info; 133 + holder.jited_line_info_rec_size = info->jited_line_info_rec_size; 134 + needed += info->nr_jited_line_info * info->jited_line_info_rec_size; 135 + 136 + if (needed > *info_data_sz) { 137 + ptr = realloc(*info_data, needed); 138 + if (!ptr) 139 + return -1; 140 + 141 + *info_data = ptr; 142 + *info_data_sz = needed; 143 + } 144 + ptr = *info_data; 145 + 146 + if (mode == DUMP_JITED) { 147 + holder.jited_prog_insns = ptr_to_u64(ptr); 148 + ptr += holder.jited_prog_len; 149 + } else { 150 + holder.xlated_prog_insns = ptr_to_u64(ptr); 151 + ptr += holder.xlated_prog_len; 152 + } 153 + 154 + holder.jited_ksyms = ptr_to_u64(ptr); 155 + ptr += holder.nr_jited_ksyms * sizeof(__u64); 156 + 157 + holder.jited_func_lens = ptr_to_u64(ptr); 158 + ptr += holder.nr_jited_func_lens * sizeof(__u32); 159 + 160 + holder.func_info = ptr_to_u64(ptr); 161 + ptr += holder.nr_func_info * holder.func_info_rec_size; 162 + 163 + holder.line_info = ptr_to_u64(ptr); 164 + ptr += holder.nr_line_info * holder.line_info_rec_size; 165 + 166 + holder.jited_line_info = ptr_to_u64(ptr); 167 + ptr += holder.nr_jited_line_info * holder.jited_line_info_rec_size; 168 + 169 + *info = holder; 170 + return 0; 171 + } 172 + 103 173 static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) 104 174 { 105 175 struct timespec real_time_ts, boot_time_ts; ··· 873 803 874 804 static int do_dump(int argc, char **argv) 875 805 { 876 - struct bpf_prog_info_linear *info_linear; 806 + struct bpf_prog_info info; 807 + __u32 info_len = sizeof(info); 808 + size_t info_data_sz = 0; 809 + void *info_data = NULL; 877 810 char *filepath = NULL; 878 811 bool opcodes = false; 879 812 bool visual = false; 880 813 enum dump_mode mode; 881 814 bool linum = false; 882 - int *fds = NULL; 883 815 int nb_fds, i = 0; 816 + int *fds = NULL; 884 817 int err = -1; 885 - __u64 arrays; 886 818 887 819 if (is_prefix(*argv, "jited")) { 888 820 if (disasm_init()) ··· 944 872 goto exit_close; 945 873 } 946 874 947 - if (mode == DUMP_JITED) 948 - arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; 949 - else 950 - arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS; 951 - 952 - arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; 953 - arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 954 - arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 955 - arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; 956 - arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; 957 - 958 875 if (json_output && nb_fds > 1) 959 876 jsonw_start_array(json_wtr); /* root array */ 960 877 for (i = 0; i < nb_fds; i++) { 961 - info_linear = bpf_program__get_prog_info_linear(fds[i], arrays); 962 - if (IS_ERR_OR_NULL(info_linear)) { 878 + memset(&info, 0, sizeof(info)); 879 + 880 + err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len); 881 + if (err) { 882 + p_err("can't get prog info: %s", strerror(errno)); 883 + break; 884 + } 885 + 886 + err = prep_prog_info(&info, mode, &info_data, &info_data_sz); 887 + if (err) { 888 + p_err("can't grow prog info_data"); 889 + break; 890 + } 891 + 892 + err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len); 893 + if (err) { 963 894 p_err("can't get prog info: %s", strerror(errno)); 964 895 break; 965 896 } 966 897 967 898 if (json_output && nb_fds > 1) { 968 899 jsonw_start_object(json_wtr); /* prog object */ 969 - print_prog_header_json(&info_linear->info); 900 + print_prog_header_json(&info); 970 901 jsonw_name(json_wtr, "insns"); 971 902 } else if (nb_fds > 1) { 972 - print_prog_header_plain(&info_linear->info); 903 + print_prog_header_plain(&info); 973 904 } 974 905 975 - err = prog_dump(&info_linear->info, mode, filepath, opcodes, 976 - visual, linum); 906 + err = prog_dump(&info, mode, filepath, opcodes, visual, linum); 977 907 978 908 if (json_output && nb_fds > 1) 979 909 jsonw_end_object(json_wtr); /* prog object */ 980 910 else if (i != nb_fds - 1 && nb_fds > 1) 981 911 printf("\n"); 982 912 983 - free(info_linear); 984 913 if (err) 985 914 break; 986 915 close(fds[i]); ··· 993 920 for (; i < nb_fds; i++) 994 921 close(fds[i]); 995 922 exit_free: 923 + free(info_data); 996 924 free(fds); 997 925 return err; 998 926 } ··· 2090 2016 2091 2017 static char *profile_target_name(int tgt_fd) 2092 2018 { 2093 - struct bpf_prog_info_linear *info_linear; 2094 - struct bpf_func_info *func_info; 2019 + struct bpf_func_info func_info; 2020 + struct bpf_prog_info info = {}; 2021 + __u32 info_len = sizeof(info); 2095 2022 const struct btf_type *t; 2023 + __u32 func_info_rec_size; 2096 2024 struct btf *btf = NULL; 2097 2025 char *name = NULL; 2026 + int err; 2098 2027 2099 - info_linear = bpf_program__get_prog_info_linear( 2100 - tgt_fd, 1UL << BPF_PROG_INFO_FUNC_INFO); 2101 - if (IS_ERR_OR_NULL(info_linear)) { 2102 - p_err("failed to get info_linear for prog FD %d", tgt_fd); 2103 - return NULL; 2028 + err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len); 2029 + if (err) { 2030 + p_err("failed to bpf_obj_get_info_by_fd for prog FD %d", tgt_fd); 2031 + goto out; 2104 2032 } 2105 2033 2106 - if (info_linear->info.btf_id == 0) { 2034 + if (info.btf_id == 0) { 2107 2035 p_err("prog FD %d doesn't have valid btf", tgt_fd); 2108 2036 goto out; 2109 2037 } 2110 2038 2111 - btf = btf__load_from_kernel_by_id(info_linear->info.btf_id); 2039 + func_info_rec_size = info.func_info_rec_size; 2040 + if (info.nr_func_info == 0) { 2041 + p_err("bpf_obj_get_info_by_fd for prog FD %d found 0 func_info", tgt_fd); 2042 + goto out; 2043 + } 2044 + 2045 + memset(&info, 0, sizeof(info)); 2046 + info.nr_func_info = 1; 2047 + info.func_info_rec_size = func_info_rec_size; 2048 + info.func_info = ptr_to_u64(&func_info); 2049 + 2050 + err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len); 2051 + if (err) { 2052 + p_err("failed to get func_info for prog FD %d", tgt_fd); 2053 + goto out; 2054 + } 2055 + 2056 + btf = btf__load_from_kernel_by_id(info.btf_id); 2112 2057 if (libbpf_get_error(btf)) { 2113 2058 p_err("failed to load btf for prog FD %d", tgt_fd); 2114 2059 goto out; 2115 2060 } 2116 2061 2117 - func_info = u64_to_ptr(info_linear->info.func_info); 2118 - t = btf__type_by_id(btf, func_info[0].type_id); 2062 + t = btf__type_by_id(btf, func_info.type_id); 2119 2063 if (!t) { 2120 2064 p_err("btf %d doesn't have type %d", 2121 - info_linear->info.btf_id, func_info[0].type_id); 2065 + info.btf_id, func_info.type_id); 2122 2066 goto out; 2123 2067 } 2124 2068 name = strdup(btf__name_by_offset(btf, t->name_off)); 2125 2069 out: 2126 2070 btf__free(btf); 2127 - free(info_linear); 2128 2071 return name; 2129 2072 } 2130 2073