Skip to content

Commit b860424

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
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 <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: John Fastabend <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 740e69c commit b860424

File tree

3 files changed

+60
-43
lines changed

3 files changed

+60
-43
lines changed

tools/lib/bpf/bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ int bpf_raw_tracepoint_open(const char *name, int prog_fd)
846846
return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
847847
}
848848

849-
int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
849+
int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
850850
bool do_log)
851851
{
852852
union bpf_attr attr = {};

tools/lib/bpf/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
234234
__u32 query_flags, __u32 *attach_flags,
235235
__u32 *prog_ids, __u32 *prog_cnt);
236236
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
237-
LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
237+
LIBBPF_API int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf,
238238
__u32 log_buf_size, bool do_log);
239239
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
240240
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type,

tools/lib/bpf/btf.c

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,37 @@
2727
static struct btf_type btf_void;
2828

2929
struct btf {
30-
union {
31-
struct btf_header *hdr;
32-
void *data;
33-
};
30+
void *raw_data;
31+
__u32 raw_size;
32+
33+
/*
34+
* When BTF is loaded from ELF or raw memory it is stored
35+
* in contiguous memory block, pointed to by raw_data pointer, and
36+
* hdr, types_data, and strs_data point inside that memory region to
37+
* respective parts of BTF representation:
38+
*
39+
* +--------------------------------+
40+
* | Header | Types | Strings |
41+
* +--------------------------------+
42+
* ^ ^ ^
43+
* | | |
44+
* hdr | |
45+
* types_data-+ |
46+
* strs_data------------+
47+
*/
48+
struct btf_header *hdr;
49+
void *types_data;
50+
void *strs_data;
51+
52+
/* type ID to `struct btf_type *` lookup index */
3453
__u32 *type_offs;
3554
__u32 type_offs_cap;
36-
const char *strings;
37-
void *nohdr_data;
38-
void *types_data;
3955
__u32 nr_types;
40-
__u32 data_size;
56+
57+
/* BTF object FD, if loaded into kernel */
4158
int fd;
59+
60+
/* Pointer size (in bytes) for a target architecture of this BTF */
4261
int ptr_sz;
4362
};
4463

@@ -80,7 +99,7 @@ static int btf_parse_hdr(struct btf *btf)
8099
const struct btf_header *hdr = btf->hdr;
81100
__u32 meta_left;
82101

83-
if (btf->data_size < sizeof(struct btf_header)) {
102+
if (btf->raw_size < sizeof(struct btf_header)) {
84103
pr_debug("BTF header not found\n");
85104
return -EINVAL;
86105
}
@@ -100,7 +119,7 @@ static int btf_parse_hdr(struct btf *btf)
100119
return -ENOTSUP;
101120
}
102121

103-
meta_left = btf->data_size - sizeof(*hdr);
122+
meta_left = btf->raw_size - sizeof(*hdr);
104123
if (!meta_left) {
105124
pr_debug("BTF has no data\n");
106125
return -EINVAL;
@@ -126,15 +145,13 @@ static int btf_parse_hdr(struct btf *btf)
126145
return -EINVAL;
127146
}
128147

129-
btf->nohdr_data = btf->hdr + 1;
130-
131148
return 0;
132149
}
133150

134151
static int btf_parse_str_sec(struct btf *btf)
135152
{
136153
const struct btf_header *hdr = btf->hdr;
137-
const char *start = btf->nohdr_data + hdr->str_off;
154+
const char *start = btf->strs_data;
138155
const char *end = start + btf->hdr->str_len;
139156

140157
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)
143160
return -EINVAL;
144161
}
145162

146-
btf->strings = start;
147-
148163
return 0;
149164
}
150165

@@ -186,11 +201,9 @@ static int btf_type_size(const struct btf_type *t)
186201
static int btf_parse_type_sec(struct btf *btf)
187202
{
188203
struct btf_header *hdr = btf->hdr;
189-
void *next_type = btf->nohdr_data + hdr->type_off;
204+
void *next_type = btf->types_data;
190205
void *end_type = next_type + hdr->type_len;
191206

192-
btf->types_data = next_type;
193-
194207
while (next_type < end_type) {
195208
int type_size;
196209
int err;
@@ -466,7 +479,7 @@ void btf__free(struct btf *btf)
466479
if (btf->fd >= 0)
467480
close(btf->fd);
468481

469-
free(btf->data);
482+
free(btf->raw_data);
470483
free(btf->type_offs);
471484
free(btf);
472485
}
@@ -482,24 +495,24 @@ struct btf *btf__new(const void *data, __u32 size)
482495

483496
btf->fd = -1;
484497

485-
btf->data = malloc(size);
486-
if (!btf->data) {
498+
btf->raw_data = malloc(size);
499+
if (!btf->raw_data) {
487500
err = -ENOMEM;
488501
goto done;
489502
}
503+
memcpy(btf->raw_data, data, size);
504+
btf->raw_size = size;
490505

491-
memcpy(btf->data, data, size);
492-
btf->data_size = size;
493-
506+
btf->hdr = btf->raw_data;
494507
err = btf_parse_hdr(btf);
495508
if (err)
496509
goto done;
497510

498-
err = btf_parse_str_sec(btf);
499-
if (err)
500-
goto done;
511+
btf->strs_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->str_off;
512+
btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off;
501513

502-
err = btf_parse_type_sec(btf);
514+
err = btf_parse_str_sec(btf);
515+
err = err ?: btf_parse_type_sec(btf);
503516

504517
done:
505518
if (err) {
@@ -820,8 +833,9 @@ int btf__finalize_data(struct bpf_object *obj, struct btf *btf)
820833

821834
int btf__load(struct btf *btf)
822835
{
823-
__u32 log_buf_size = 0;
836+
__u32 log_buf_size = 0, raw_size;
824837
char *log_buf = NULL;
838+
const void *raw_data;
825839
int err = 0;
826840

827841
if (btf->fd >= 0)
@@ -836,8 +850,13 @@ int btf__load(struct btf *btf)
836850
*log_buf = 0;
837851
}
838852

839-
btf->fd = bpf_load_btf(btf->data, btf->data_size,
840-
log_buf, log_buf_size, false);
853+
raw_data = btf__get_raw_data(btf, &raw_size);
854+
if (!raw_data) {
855+
err = -ENOMEM;
856+
goto done;
857+
}
858+
859+
btf->fd = bpf_load_btf(raw_data, raw_size, log_buf, log_buf_size, false);
841860
if (btf->fd < 0) {
842861
if (!log_buf || errno == ENOSPC) {
843862
log_buf_size = max((__u32)BPF_LOG_BUF_SIZE,
@@ -870,14 +889,14 @@ void btf__set_fd(struct btf *btf, int fd)
870889

871890
const void *btf__get_raw_data(const struct btf *btf, __u32 *size)
872891
{
873-
*size = btf->data_size;
874-
return btf->data;
892+
*size = btf->raw_size;
893+
return btf->raw_data;
875894
}
876895

877896
const char *btf__name_by_offset(const struct btf *btf, __u32 offset)
878897
{
879898
if (offset < btf->hdr->str_len)
880-
return &btf->strings[offset];
899+
return btf->strs_data + offset;
881900
else
882901
return NULL;
883902
}
@@ -1860,8 +1879,7 @@ static int btf_str_remap_offset(__u32 *str_off_ptr, void *ctx)
18601879
*/
18611880
static int btf_dedup_strings(struct btf_dedup *d)
18621881
{
1863-
const struct btf_header *hdr = d->btf->hdr;
1864-
char *start = (char *)d->btf->nohdr_data + hdr->str_off;
1882+
char *start = d->btf->strs_data;
18651883
char *end = start + d->btf->hdr->str_len;
18661884
char *p = start, *tmp_strs = NULL;
18671885
struct btf_str_ptrs strs = {
@@ -2970,12 +2988,11 @@ static int btf_dedup_compact_types(struct btf_dedup *d)
29702988
d->btf->type_offs = new_offs;
29712989

29722990
/* make sure string section follows type information without gaps */
2973-
d->btf->hdr->str_off = p - d->btf->nohdr_data;
2974-
memmove(p, d->btf->strings, d->btf->hdr->str_len);
2975-
d->btf->strings = p;
2976-
p += d->btf->hdr->str_len;
2991+
d->btf->hdr->str_off = p - d->btf->types_data;
2992+
memmove(p, d->btf->strs_data, d->btf->hdr->str_len);
2993+
d->btf->strs_data = p;
29772994

2978-
d->btf->data_size = p - d->btf->data;
2995+
d->btf->raw_size = d->btf->hdr->hdr_len + d->btf->hdr->type_len + d->btf->hdr->str_len;
29792996
return 0;
29802997
}
29812998

0 commit comments

Comments
 (0)