Support encoding of BTF kind layout data and crcs via btf__new_empty_opts(). Current supported opts are base_btf, add_kind_layout and add_crc. Kind layout information is maintained in btf.c in the kind_layouts[] array; when BTF is created with the add_kind_layout option it represents the current view of supported BTF kinds. Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> --- tools/lib/bpf/btf.c | 74 ++++++++++++++++++++++++++++++++++++++-- tools/lib/bpf/btf.h | 11 ++++++ tools/lib/bpf/libbpf.map | 1 + 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 007ce6bcad70..ed728d0511a4 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -16,6 +16,7 @@ #include <linux/err.h> #include <linux/btf.h> #include <gelf.h> +#include <zlib.h> #include "btf.h" #include "bpf.h" #include "libbpf.h" @@ -28,6 +29,35 @@ static struct btf_type btf_void; +/* Describe how kinds are laid out; some have a singular element following the "struct btf_type", + * some have BTF_INFO_VLEN(t->info) elements. Specify sizes for both. Flags are currently unused. + * Kind layout can be optionally added to the BTF representation in a dedicated section to + * facilitate parsing. New kinds must be added here. + */ +struct btf_kind_layout kind_layouts[NR_BTF_KINDS] = { +/* flags singular element size vlen element(s) size */ +{ 0, 0, 0 }, /* _UNKN */ +{ 0, sizeof(__u32), 0 }, /* _INT */ +{ 0, 0, 0 }, /* _PTR */ +{ 0, sizeof(struct btf_array), 0 }, /* _ARRAY */ +{ 0, 0, sizeof(struct btf_member) }, /* _STRUCT */ +{ 0, 0, sizeof(struct btf_member) }, /* _UNION */ +{ 0, 0, sizeof(struct btf_enum) }, /* _ENUM */ +{ 0, 0, 0 }, /* _FWD */ +{ 0, 0, 0 }, /* _TYPEDEF */ +{ 0, 0, 0 }, /* _VOLATILE */ +{ 0, 0, 0 }, /* _CONST */ +{ 0, 0, 0 }, /* _RESTRICT */ +{ 0, 0, 0 }, /* _FUNC */ +{ 0, 0, sizeof(struct btf_param) }, /* _FUNC_PROTO */ +{ 0, sizeof(struct btf_var), 0 }, /* _VAR */ +{ 0, 0, sizeof(struct btf_var_secinfo) }, /* _DATASEC */ +{ 0, 0, 0 }, /* _FLOAT */ +{ 0, sizeof(struct btf_decl_tag), 0 }, /* _DECL_TAG */ +{ 0, 0, 0 }, /* _TYPE_TAG */ +{ 0, 0, sizeof(struct btf_enum64) }, /* _ENUM64 */ +}; + struct btf { /* raw BTF data in native endianness */ void *raw_data; @@ -1061,8 +1091,9 @@ void btf__free(struct btf *btf) free(btf); } -static struct btf *btf_new_empty(struct btf *base_btf) +static struct btf *btf_new_empty(struct btf_new_opts *opts) { + struct btf *base_btf = OPTS_GET(opts, base_btf, NULL); struct btf_header *hdr; struct btf *btf; @@ -1104,6 +1135,23 @@ static struct btf *btf_new_empty(struct btf *base_btf) free(btf); return ERR_PTR(-ENOMEM); } + + if (opts->add_kind_layout) { + btf->kind_layout = kind_layouts; + hdr->kind_layout_len = sizeof(kind_layouts); + } + if (opts->add_crc) { + if (btf->base_btf) { + struct btf_header *base_hdr = btf->base_btf->hdr; + + if (base_hdr->hdr_len >= sizeof(struct btf_header) && + base_hdr->flags & BTF_FLAG_CRC_SET) { + hdr->base_crc = base_hdr->crc; + hdr->flags |= BTF_FLAG_BASE_CRC_SET; + } + } + hdr->flags |= BTF_FLAG_CRC_SET; + } memcpy(btf->hdr, hdr, sizeof(*hdr)); return btf; @@ -1111,12 +1159,26 @@ static struct btf *btf_new_empty(struct btf *base_btf) struct btf *btf__new_empty(void) { - return libbpf_ptr(btf_new_empty(NULL)); + LIBBPF_OPTS(btf_new_opts, opts); + + return libbpf_ptr(btf_new_empty(&opts)); } struct btf *btf__new_empty_split(struct btf *base_btf) { - return libbpf_ptr(btf_new_empty(base_btf)); + LIBBPF_OPTS(btf_new_opts, opts); + + opts.base_btf = base_btf; + + return libbpf_ptr(btf_new_empty(&opts)); +} + +struct btf *btf__new_empty_opts(struct btf_new_opts *opts) +{ + if (!OPTS_VALID(opts, btf_new_opts)) + return libbpf_err_ptr(-EINVAL); + + return libbpf_ptr(btf_new_empty(opts)); } static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf) @@ -1562,6 +1624,12 @@ static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endi btf_bswap_kind_layout_sec(p, hdr->kind_layout_len); } + if (hdr->flags & BTF_FLAG_CRC_SET) { + struct btf_header *h = data; + + h->crc = crc32(0L, (const Bytef *)data, data_sz); + } + *size = data_sz; return data; err_out: diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 8e6880d91c84..d25bd5c19eec 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -107,6 +107,17 @@ LIBBPF_API struct btf *btf__new_empty(void); */ LIBBPF_API struct btf *btf__new_empty_split(struct btf *base_btf); +struct btf_new_opts { + size_t sz; + struct btf *base_btf; /* optional base BTF */ + bool add_kind_layout; /* add BTF kind layout information */ + bool add_crc; /* add CRC information */ + size_t:0; +}; +#define btf_new_opts__last_field add_crc + +LIBBPF_API struct btf *btf__new_empty_opts(struct btf_new_opts *opts); + LIBBPF_API struct btf *btf__parse(const char *path, struct btf_ext **btf_ext); LIBBPF_API struct btf *btf__parse_split(const char *path, struct btf *base_btf); LIBBPF_API struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index b52dc28dc8af..b8c0716133d1 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -401,6 +401,7 @@ LIBBPF_1.3.0 { bpf_program__attach_netkit; bpf_program__attach_tcx; bpf_program__attach_uprobe_multi; + btf__new_empty_opts; ring__avail_data_size; ring__consume; ring__consumer_pos; -- 2.31.1