mirror of
https://github.com/netdata/libbpf.git
synced 2026-04-12 11:39:06 +08:00
libbpf: Remove assumption of single contiguous memory for BTF data
Refactor internals of struct btf to remove assumptions that BTF header, type data, and string data are layed out contiguously in a memory in a single memory allocation. Now we have three separate pointers pointing to the start of each respective are: header, types, strings. In the next patches, these pointers will be re-assigned to point to independently allocated memory areas, if BTF needs to be modified. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20200926011357.2366158-3-andriin@fb.com
This commit is contained in:
committed by
Andrii Nakryiko
parent
4023fbd99e
commit
71e8af71c5
@@ -846,7 +846,7 @@ int bpf_raw_tracepoint_open(const char *name, int prog_fd)
|
|||||||
return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
|
return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
|
int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
|
||||||
bool do_log)
|
bool do_log)
|
||||||
{
|
{
|
||||||
union bpf_attr attr = {};
|
union bpf_attr attr = {};
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
|
|||||||
__u32 query_flags, __u32 *attach_flags,
|
__u32 query_flags, __u32 *attach_flags,
|
||||||
__u32 *prog_ids, __u32 *prog_cnt);
|
__u32 *prog_ids, __u32 *prog_cnt);
|
||||||
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
|
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
|
||||||
LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
|
LIBBPF_API int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf,
|
||||||
__u32 log_buf_size, bool do_log);
|
__u32 log_buf_size, bool do_log);
|
||||||
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
|
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
|
||||||
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
|
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
|
||||||
|
|||||||
99
src/btf.c
99
src/btf.c
@@ -27,18 +27,37 @@
|
|||||||
static struct btf_type btf_void;
|
static struct btf_type btf_void;
|
||||||
|
|
||||||
struct btf {
|
struct btf {
|
||||||
union {
|
void *raw_data;
|
||||||
struct btf_header *hdr;
|
__u32 raw_size;
|
||||||
void *data;
|
|
||||||
};
|
/*
|
||||||
|
* When BTF is loaded from ELF or raw memory it is stored
|
||||||
|
* in contiguous memory block, pointed to by raw_data pointer, and
|
||||||
|
* hdr, types_data, and strs_data point inside that memory region to
|
||||||
|
* respective parts of BTF representation:
|
||||||
|
*
|
||||||
|
* +--------------------------------+
|
||||||
|
* | Header | Types | Strings |
|
||||||
|
* +--------------------------------+
|
||||||
|
* ^ ^ ^
|
||||||
|
* | | |
|
||||||
|
* hdr | |
|
||||||
|
* types_data-+ |
|
||||||
|
* strs_data------------+
|
||||||
|
*/
|
||||||
|
struct btf_header *hdr;
|
||||||
|
void *types_data;
|
||||||
|
void *strs_data;
|
||||||
|
|
||||||
|
/* type ID to `struct btf_type *` lookup index */
|
||||||
__u32 *type_offs;
|
__u32 *type_offs;
|
||||||
__u32 type_offs_cap;
|
__u32 type_offs_cap;
|
||||||
const char *strings;
|
|
||||||
void *nohdr_data;
|
|
||||||
void *types_data;
|
|
||||||
__u32 nr_types;
|
__u32 nr_types;
|
||||||
__u32 data_size;
|
|
||||||
|
/* BTF object FD, if loaded into kernel */
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
/* Pointer size (in bytes) for a target architecture of this BTF */
|
||||||
int ptr_sz;
|
int ptr_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +99,7 @@ static int btf_parse_hdr(struct btf *btf)
|
|||||||
const struct btf_header *hdr = btf->hdr;
|
const struct btf_header *hdr = btf->hdr;
|
||||||
__u32 meta_left;
|
__u32 meta_left;
|
||||||
|
|
||||||
if (btf->data_size < sizeof(struct btf_header)) {
|
if (btf->raw_size < sizeof(struct btf_header)) {
|
||||||
pr_debug("BTF header not found\n");
|
pr_debug("BTF header not found\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -100,7 +119,7 @@ static int btf_parse_hdr(struct btf *btf)
|
|||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_left = btf->data_size - sizeof(*hdr);
|
meta_left = btf->raw_size - sizeof(*hdr);
|
||||||
if (!meta_left) {
|
if (!meta_left) {
|
||||||
pr_debug("BTF has no data\n");
|
pr_debug("BTF has no data\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -126,15 +145,13 @@ static int btf_parse_hdr(struct btf *btf)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
btf->nohdr_data = btf->hdr + 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btf_parse_str_sec(struct btf *btf)
|
static int btf_parse_str_sec(struct btf *btf)
|
||||||
{
|
{
|
||||||
const struct btf_header *hdr = btf->hdr;
|
const struct btf_header *hdr = btf->hdr;
|
||||||
const char *start = btf->nohdr_data + hdr->str_off;
|
const char *start = btf->strs_data;
|
||||||
const char *end = start + btf->hdr->str_len;
|
const char *end = start + btf->hdr->str_len;
|
||||||
|
|
||||||
if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_STR_OFFSET ||
|
if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_STR_OFFSET ||
|
||||||
@@ -143,8 +160,6 @@ static int btf_parse_str_sec(struct btf *btf)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
btf->strings = start;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,11 +201,9 @@ static int btf_type_size(const struct btf_type *t)
|
|||||||
static int btf_parse_type_sec(struct btf *btf)
|
static int btf_parse_type_sec(struct btf *btf)
|
||||||
{
|
{
|
||||||
struct btf_header *hdr = btf->hdr;
|
struct btf_header *hdr = btf->hdr;
|
||||||
void *next_type = btf->nohdr_data + hdr->type_off;
|
void *next_type = btf->types_data;
|
||||||
void *end_type = next_type + hdr->type_len;
|
void *end_type = next_type + hdr->type_len;
|
||||||
|
|
||||||
btf->types_data = next_type;
|
|
||||||
|
|
||||||
while (next_type < end_type) {
|
while (next_type < end_type) {
|
||||||
int type_size;
|
int type_size;
|
||||||
int err;
|
int err;
|
||||||
@@ -466,7 +479,7 @@ void btf__free(struct btf *btf)
|
|||||||
if (btf->fd >= 0)
|
if (btf->fd >= 0)
|
||||||
close(btf->fd);
|
close(btf->fd);
|
||||||
|
|
||||||
free(btf->data);
|
free(btf->raw_data);
|
||||||
free(btf->type_offs);
|
free(btf->type_offs);
|
||||||
free(btf);
|
free(btf);
|
||||||
}
|
}
|
||||||
@@ -482,24 +495,24 @@ struct btf *btf__new(const void *data, __u32 size)
|
|||||||
|
|
||||||
btf->fd = -1;
|
btf->fd = -1;
|
||||||
|
|
||||||
btf->data = malloc(size);
|
btf->raw_data = malloc(size);
|
||||||
if (!btf->data) {
|
if (!btf->raw_data) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
memcpy(btf->raw_data, data, size);
|
||||||
|
btf->raw_size = size;
|
||||||
|
|
||||||
memcpy(btf->data, data, size);
|
btf->hdr = btf->raw_data;
|
||||||
btf->data_size = size;
|
|
||||||
|
|
||||||
err = btf_parse_hdr(btf);
|
err = btf_parse_hdr(btf);
|
||||||
if (err)
|
if (err)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
err = btf_parse_str_sec(btf);
|
btf->strs_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->str_off;
|
||||||
if (err)
|
btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off;
|
||||||
goto done;
|
|
||||||
|
|
||||||
err = btf_parse_type_sec(btf);
|
err = btf_parse_str_sec(btf);
|
||||||
|
err = err ?: btf_parse_type_sec(btf);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -826,8 +839,9 @@ int btf__finalize_data(struct bpf_object *obj, struct btf *btf)
|
|||||||
|
|
||||||
int btf__load(struct btf *btf)
|
int btf__load(struct btf *btf)
|
||||||
{
|
{
|
||||||
__u32 log_buf_size = 0;
|
__u32 log_buf_size = 0, raw_size;
|
||||||
char *log_buf = NULL;
|
char *log_buf = NULL;
|
||||||
|
const void *raw_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (btf->fd >= 0)
|
if (btf->fd >= 0)
|
||||||
@@ -842,8 +856,13 @@ retry_load:
|
|||||||
*log_buf = 0;
|
*log_buf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
btf->fd = bpf_load_btf(btf->data, btf->data_size,
|
raw_data = btf__get_raw_data(btf, &raw_size);
|
||||||
log_buf, log_buf_size, false);
|
if (!raw_data) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
btf->fd = bpf_load_btf(raw_data, raw_size, log_buf, log_buf_size, false);
|
||||||
if (btf->fd < 0) {
|
if (btf->fd < 0) {
|
||||||
if (!log_buf || errno == ENOSPC) {
|
if (!log_buf || errno == ENOSPC) {
|
||||||
log_buf_size = max((__u32)BPF_LOG_BUF_SIZE,
|
log_buf_size = max((__u32)BPF_LOG_BUF_SIZE,
|
||||||
@@ -876,14 +895,14 @@ void btf__set_fd(struct btf *btf, int fd)
|
|||||||
|
|
||||||
const void *btf__get_raw_data(const struct btf *btf, __u32 *size)
|
const void *btf__get_raw_data(const struct btf *btf, __u32 *size)
|
||||||
{
|
{
|
||||||
*size = btf->data_size;
|
*size = btf->raw_size;
|
||||||
return btf->data;
|
return btf->raw_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *btf__name_by_offset(const struct btf *btf, __u32 offset)
|
const char *btf__name_by_offset(const struct btf *btf, __u32 offset)
|
||||||
{
|
{
|
||||||
if (offset < btf->hdr->str_len)
|
if (offset < btf->hdr->str_len)
|
||||||
return &btf->strings[offset];
|
return btf->strs_data + offset;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1866,8 +1885,7 @@ static int btf_str_remap_offset(__u32 *str_off_ptr, void *ctx)
|
|||||||
*/
|
*/
|
||||||
static int btf_dedup_strings(struct btf_dedup *d)
|
static int btf_dedup_strings(struct btf_dedup *d)
|
||||||
{
|
{
|
||||||
const struct btf_header *hdr = d->btf->hdr;
|
char *start = d->btf->strs_data;
|
||||||
char *start = (char *)d->btf->nohdr_data + hdr->str_off;
|
|
||||||
char *end = start + d->btf->hdr->str_len;
|
char *end = start + d->btf->hdr->str_len;
|
||||||
char *p = start, *tmp_strs = NULL;
|
char *p = start, *tmp_strs = NULL;
|
||||||
struct btf_str_ptrs strs = {
|
struct btf_str_ptrs strs = {
|
||||||
@@ -2976,12 +2994,11 @@ static int btf_dedup_compact_types(struct btf_dedup *d)
|
|||||||
d->btf->type_offs = new_offs;
|
d->btf->type_offs = new_offs;
|
||||||
|
|
||||||
/* make sure string section follows type information without gaps */
|
/* make sure string section follows type information without gaps */
|
||||||
d->btf->hdr->str_off = p - d->btf->nohdr_data;
|
d->btf->hdr->str_off = p - d->btf->types_data;
|
||||||
memmove(p, d->btf->strings, d->btf->hdr->str_len);
|
memmove(p, d->btf->strs_data, d->btf->hdr->str_len);
|
||||||
d->btf->strings = p;
|
d->btf->strs_data = p;
|
||||||
p += d->btf->hdr->str_len;
|
|
||||||
|
|
||||||
d->btf->data_size = p - d->btf->data;
|
d->btf->raw_size = d->btf->hdr->hdr_len + d->btf->hdr->type_len + d->btf->hdr->str_len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user