mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 03:11:11 -04:00
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
This commit is contained in:
committed by
Andrii Nakryiko
parent
2ecbe53e0e
commit
d686d92c40
@@ -29,6 +29,36 @@
|
||||
|
||||
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.
|
||||
*/
|
||||
static struct btf_layout layouts[NR_BTF_KINDS] = {
|
||||
/* singular element size vlen element(s) size flags */
|
||||
[BTF_KIND_UNKN] = { 0, 0, 0 },
|
||||
[BTF_KIND_INT] = { sizeof(__u32), 0, 0 },
|
||||
[BTF_KIND_PTR] = { 0, 0, 0 },
|
||||
[BTF_KIND_ARRAY] = { sizeof(struct btf_array), 0, 0 },
|
||||
[BTF_KIND_STRUCT] = { 0, sizeof(struct btf_member), 0 },
|
||||
[BTF_KIND_UNION] = { 0, sizeof(struct btf_member), 0 },
|
||||
[BTF_KIND_ENUM] = { 0, sizeof(struct btf_enum), 0 },
|
||||
[BTF_KIND_FWD] = { 0, 0, 0 },
|
||||
[BTF_KIND_TYPEDEF] = { 0, 0, 0 },
|
||||
[BTF_KIND_VOLATILE] = { 0, 0, 0 },
|
||||
[BTF_KIND_CONST] = { 0, 0, 0 },
|
||||
[BTF_KIND_RESTRICT] = { 0, 0, 0 },
|
||||
[BTF_KIND_FUNC] = { 0, 0, 0 },
|
||||
[BTF_KIND_FUNC_PROTO] = { 0, sizeof(struct btf_param), 0 },
|
||||
[BTF_KIND_VAR] = { sizeof(struct btf_var), 0, 0 },
|
||||
[BTF_KIND_DATASEC] = { 0, sizeof(struct btf_var_secinfo), 0 },
|
||||
[BTF_KIND_FLOAT] = { 0, 0, 0 },
|
||||
[BTF_KIND_DECL_TAG] = { sizeof(struct btf_decl_tag), 0, 0 },
|
||||
[BTF_KIND_TYPE_TAG] = { 0, 0, 0 },
|
||||
[BTF_KIND_ENUM64] = { 0, sizeof(struct btf_enum64), 0 },
|
||||
};
|
||||
|
||||
struct btf {
|
||||
/* raw BTF data in native endianness */
|
||||
void *raw_data;
|
||||
@@ -1179,8 +1209,10 @@ 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)
|
||||
{
|
||||
bool add_layout = OPTS_GET(opts, add_layout, false);
|
||||
struct btf *base_btf = OPTS_GET(opts, base_btf, NULL);
|
||||
struct btf_header *hdr;
|
||||
struct btf *btf;
|
||||
|
||||
@@ -1205,6 +1237,8 @@ static struct btf *btf_new_empty(struct btf *base_btf)
|
||||
|
||||
/* +1 for empty string at offset 0 */
|
||||
btf->raw_size = sizeof(struct btf_header) + (base_btf ? 0 : 1);
|
||||
if (add_layout)
|
||||
btf->raw_size += sizeof(layouts);
|
||||
btf->raw_data = calloc(1, btf->raw_size);
|
||||
if (!btf->raw_data) {
|
||||
free(btf);
|
||||
@@ -1219,6 +1253,19 @@ static struct btf *btf_new_empty(struct btf *base_btf)
|
||||
btf->types_data = btf->raw_data + hdr->hdr_len;
|
||||
btf->strs_data = btf->raw_data + hdr->hdr_len;
|
||||
hdr->str_len = base_btf ? 0 : 1; /* empty string at offset 0 */
|
||||
|
||||
if (add_layout) {
|
||||
hdr->layout_len = sizeof(layouts);
|
||||
btf->layout = layouts;
|
||||
/*
|
||||
* No need to swap endianness here as btf_get_raw_data()
|
||||
* will do this for us if btf->swapped_endian is true.
|
||||
*/
|
||||
memcpy(btf->raw_data + hdr->hdr_len, layouts, sizeof(layouts));
|
||||
btf->strs_data += sizeof(layouts);
|
||||
hdr->str_off += sizeof(layouts);
|
||||
}
|
||||
|
||||
memcpy(&btf->hdr, hdr, sizeof(*hdr));
|
||||
|
||||
return btf;
|
||||
@@ -1231,7 +1278,19 @@ struct btf *btf__new_empty(void)
|
||||
|
||||
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, bool is_mmap)
|
||||
|
||||
@@ -109,6 +109,26 @@ 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_layout; /* add BTF layout information */
|
||||
size_t:0;
|
||||
};
|
||||
#define btf_new_opts__last_field add_layout
|
||||
|
||||
/**
|
||||
* @brief **btf__new_empty_opts()** creates an unpopulated BTF object with
|
||||
* optional *base_btf* and BTF kind layout description if *add_layout*
|
||||
* is set
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* On error, NULL is returned and the thread-local `errno` variable is
|
||||
* set to the error code.
|
||||
*/
|
||||
LIBBPF_API struct btf *btf__new_empty_opts(struct btf_new_opts *opts);
|
||||
|
||||
/**
|
||||
* @brief **btf__distill_base()** creates new versions of the split BTF
|
||||
* *src_btf* and its base BTF. The new base BTF will only contain the types
|
||||
|
||||
@@ -458,4 +458,6 @@ LIBBPF_1.7.0 {
|
||||
} LIBBPF_1.6.0;
|
||||
|
||||
LIBBPF_1.8.0 {
|
||||
global:
|
||||
btf__new_empty_opts;
|
||||
} LIBBPF_1.7.0;
|
||||
|
||||
Reference in New Issue
Block a user