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

Configure Feed

Select the types of activity you want to include in your feed.

libbpf: Add layout encoding support

Support encoding of BTF layout data via btf__new_empty_opts().

Current supported opts are base_btf and add_layout.

Layout information is maintained in btf.c in the layouts[] array;
when BTF is created with the add_layout option it represents the
current view of supported BTF kinds.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260326145444.2076244-5-alan.maguire@oracle.com

authored by

Alan Maguire and committed by
Andrii Nakryiko
d686d92c 2ecbe53e

+83 -2
+61 -2
tools/lib/bpf/btf.c
··· 29 29 30 30 static struct btf_type btf_void; 31 31 32 + /* 33 + * Describe how kinds are laid out; some have a singular element following the "struct btf_type", 34 + * some have BTF_INFO_VLEN(t->info) elements. Specify sizes for both. Flags are currently unused. 35 + * Kind layout can be optionally added to the BTF representation in a dedicated section to 36 + * facilitate parsing. New kinds must be added here. 37 + */ 38 + static struct btf_layout layouts[NR_BTF_KINDS] = { 39 + /* singular element size vlen element(s) size flags */ 40 + [BTF_KIND_UNKN] = { 0, 0, 0 }, 41 + [BTF_KIND_INT] = { sizeof(__u32), 0, 0 }, 42 + [BTF_KIND_PTR] = { 0, 0, 0 }, 43 + [BTF_KIND_ARRAY] = { sizeof(struct btf_array), 0, 0 }, 44 + [BTF_KIND_STRUCT] = { 0, sizeof(struct btf_member), 0 }, 45 + [BTF_KIND_UNION] = { 0, sizeof(struct btf_member), 0 }, 46 + [BTF_KIND_ENUM] = { 0, sizeof(struct btf_enum), 0 }, 47 + [BTF_KIND_FWD] = { 0, 0, 0 }, 48 + [BTF_KIND_TYPEDEF] = { 0, 0, 0 }, 49 + [BTF_KIND_VOLATILE] = { 0, 0, 0 }, 50 + [BTF_KIND_CONST] = { 0, 0, 0 }, 51 + [BTF_KIND_RESTRICT] = { 0, 0, 0 }, 52 + [BTF_KIND_FUNC] = { 0, 0, 0 }, 53 + [BTF_KIND_FUNC_PROTO] = { 0, sizeof(struct btf_param), 0 }, 54 + [BTF_KIND_VAR] = { sizeof(struct btf_var), 0, 0 }, 55 + [BTF_KIND_DATASEC] = { 0, sizeof(struct btf_var_secinfo), 0 }, 56 + [BTF_KIND_FLOAT] = { 0, 0, 0 }, 57 + [BTF_KIND_DECL_TAG] = { sizeof(struct btf_decl_tag), 0, 0 }, 58 + [BTF_KIND_TYPE_TAG] = { 0, 0, 0 }, 59 + [BTF_KIND_ENUM64] = { 0, sizeof(struct btf_enum64), 0 }, 60 + }; 61 + 32 62 struct btf { 33 63 /* raw BTF data in native endianness */ 34 64 void *raw_data; ··· 1209 1179 free(btf); 1210 1180 } 1211 1181 1212 - static struct btf *btf_new_empty(struct btf *base_btf) 1182 + static struct btf *btf_new_empty(struct btf_new_opts *opts) 1213 1183 { 1184 + bool add_layout = OPTS_GET(opts, add_layout, false); 1185 + struct btf *base_btf = OPTS_GET(opts, base_btf, NULL); 1214 1186 struct btf_header *hdr; 1215 1187 struct btf *btf; 1216 1188 ··· 1237 1205 1238 1206 /* +1 for empty string at offset 0 */ 1239 1207 btf->raw_size = sizeof(struct btf_header) + (base_btf ? 0 : 1); 1208 + if (add_layout) 1209 + btf->raw_size += sizeof(layouts); 1240 1210 btf->raw_data = calloc(1, btf->raw_size); 1241 1211 if (!btf->raw_data) { 1242 1212 free(btf); ··· 1253 1219 btf->types_data = btf->raw_data + hdr->hdr_len; 1254 1220 btf->strs_data = btf->raw_data + hdr->hdr_len; 1255 1221 hdr->str_len = base_btf ? 0 : 1; /* empty string at offset 0 */ 1222 + 1223 + if (add_layout) { 1224 + hdr->layout_len = sizeof(layouts); 1225 + btf->layout = layouts; 1226 + /* 1227 + * No need to swap endianness here as btf_get_raw_data() 1228 + * will do this for us if btf->swapped_endian is true. 1229 + */ 1230 + memcpy(btf->raw_data + hdr->hdr_len, layouts, sizeof(layouts)); 1231 + btf->strs_data += sizeof(layouts); 1232 + hdr->str_off += sizeof(layouts); 1233 + } 1234 + 1256 1235 memcpy(&btf->hdr, hdr, sizeof(*hdr)); 1257 1236 1258 1237 return btf; ··· 1278 1231 1279 1232 struct btf *btf__new_empty_split(struct btf *base_btf) 1280 1233 { 1281 - return libbpf_ptr(btf_new_empty(base_btf)); 1234 + LIBBPF_OPTS(btf_new_opts, opts); 1235 + 1236 + opts.base_btf = base_btf; 1237 + 1238 + return libbpf_ptr(btf_new_empty(&opts)); 1239 + } 1240 + 1241 + struct btf *btf__new_empty_opts(struct btf_new_opts *opts) 1242 + { 1243 + if (!OPTS_VALID(opts, btf_new_opts)) 1244 + return libbpf_err_ptr(-EINVAL); 1245 + 1246 + return libbpf_ptr(btf_new_empty(opts)); 1282 1247 } 1283 1248 1284 1249 static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf, bool is_mmap)
+20
tools/lib/bpf/btf.h
··· 109 109 */ 110 110 LIBBPF_API struct btf *btf__new_empty_split(struct btf *base_btf); 111 111 112 + struct btf_new_opts { 113 + size_t sz; 114 + struct btf *base_btf; /* optional base BTF */ 115 + bool add_layout; /* add BTF layout information */ 116 + size_t:0; 117 + }; 118 + #define btf_new_opts__last_field add_layout 119 + 120 + /** 121 + * @brief **btf__new_empty_opts()** creates an unpopulated BTF object with 122 + * optional *base_btf* and BTF kind layout description if *add_layout* 123 + * is set 124 + * @return new BTF object instance which has to be eventually freed with 125 + * **btf__free()** 126 + * 127 + * On error, NULL is returned and the thread-local `errno` variable is 128 + * set to the error code. 129 + */ 130 + LIBBPF_API struct btf *btf__new_empty_opts(struct btf_new_opts *opts); 131 + 112 132 /** 113 133 * @brief **btf__distill_base()** creates new versions of the split BTF 114 134 * *src_btf* and its base BTF. The new base BTF will only contain the types
+2
tools/lib/bpf/libbpf.map
··· 458 458 } LIBBPF_1.6.0; 459 459 460 460 LIBBPF_1.8.0 { 461 + global: 462 + btf__new_empty_opts; 461 463 } LIBBPF_1.7.0;