Skip to content

Commit 28bbfc3

Browse files
author
Alexei Starovoitov
committed
Merge branch 'btf-api-extensions'
Andrii Nakryiko says: ==================== This patchset introduces a set of new APIs that make it possible to work with BTF more effectively (and without involving kernel) for applications like pahole that need to manipulate .BTF and .BTF.ext data. Patch #1 changes existing btf__new() API call to only load and initialize struct btf, while exposing new btf__load() API to attempt to load and validate BTF in kernel. Patch #2 adds btf__get_raw_data() API allowing to get access to raw BTF data from struct btf. Patch #3 adds similar btf_ext__get_raw_data() API for working with struct btf_ext. Patch #4 removes not-yet-stable btf__get_strings() API which was added to be able to test contents of struct btf for btf__dedup(). It's now superseded by raw APIs. v3->v4: - formatting fixes - renamed btf_ext functions/structs to use "setup" language instead of "copy" - removed btf__get_strings from libbpf.map v2->v3: - const void* variants of btf__get_raw_data() - added btf_ext__get_raw_data() - removed btf__get_strings() and adapted test_btf.c to use btf__get_raw_data() v1->v2: - btf_load() returns just error, not fd - fix ordering in libbpf.map ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents a4021a3 + 49b57e0 commit 28bbfc3

File tree

5 files changed

+121
-93
lines changed

5 files changed

+121
-93
lines changed

tools/lib/bpf/btf.c

Lines changed: 87 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,22 @@ struct btf {
4242

4343
struct btf_ext_info {
4444
/*
45-
* info points to a deep copy of the individual info section
46-
* (e.g. func_info and line_info) from the .BTF.ext.
47-
* It does not include the __u32 rec_size.
45+
* info points to the individual info section (e.g. func_info and
46+
* line_info) from the .BTF.ext. It does not include the __u32 rec_size.
4847
*/
4948
void *info;
5049
__u32 rec_size;
5150
__u32 len;
5251
};
5352

5453
struct btf_ext {
54+
union {
55+
struct btf_ext_header *hdr;
56+
void *data;
57+
};
5558
struct btf_ext_info func_info;
5659
struct btf_ext_info line_info;
60+
__u32 data_size;
5761
};
5862

5963
struct btf_ext_info_sec {
@@ -367,8 +371,6 @@ void btf__free(struct btf *btf)
367371

368372
struct btf *btf__new(__u8 *data, __u32 size)
369373
{
370-
__u32 log_buf_size = 0;
371-
char *log_buf = NULL;
372374
struct btf *btf;
373375
int err;
374376

@@ -378,15 +380,6 @@ struct btf *btf__new(__u8 *data, __u32 size)
378380

379381
btf->fd = -1;
380382

381-
log_buf = malloc(BPF_LOG_BUF_SIZE);
382-
if (!log_buf) {
383-
err = -ENOMEM;
384-
goto done;
385-
}
386-
387-
*log_buf = 0;
388-
log_buf_size = BPF_LOG_BUF_SIZE;
389-
390383
btf->data = malloc(size);
391384
if (!btf->data) {
392385
err = -ENOMEM;
@@ -396,17 +389,6 @@ struct btf *btf__new(__u8 *data, __u32 size)
396389
memcpy(btf->data, data, size);
397390
btf->data_size = size;
398391

399-
btf->fd = bpf_load_btf(btf->data, btf->data_size,
400-
log_buf, log_buf_size, false);
401-
402-
if (btf->fd == -1) {
403-
err = -errno;
404-
pr_warning("Error loading BTF: %s(%d)\n", strerror(errno), errno);
405-
if (log_buf && *log_buf)
406-
pr_warning("%s\n", log_buf);
407-
goto done;
408-
}
409-
410392
err = btf_parse_hdr(btf);
411393
if (err)
412394
goto done;
@@ -418,8 +400,6 @@ struct btf *btf__new(__u8 *data, __u32 size)
418400
err = btf_parse_type_sec(btf);
419401

420402
done:
421-
free(log_buf);
422-
423403
if (err) {
424404
btf__free(btf);
425405
return ERR_PTR(err);
@@ -428,16 +408,45 @@ struct btf *btf__new(__u8 *data, __u32 size)
428408
return btf;
429409
}
430410

411+
int btf__load(struct btf *btf)
412+
{
413+
__u32 log_buf_size = BPF_LOG_BUF_SIZE;
414+
char *log_buf = NULL;
415+
int err = 0;
416+
417+
if (btf->fd >= 0)
418+
return -EEXIST;
419+
420+
log_buf = malloc(log_buf_size);
421+
if (!log_buf)
422+
return -ENOMEM;
423+
424+
*log_buf = 0;
425+
426+
btf->fd = bpf_load_btf(btf->data, btf->data_size,
427+
log_buf, log_buf_size, false);
428+
if (btf->fd < 0) {
429+
err = -errno;
430+
pr_warning("Error loading BTF: %s(%d)\n", strerror(errno), errno);
431+
if (*log_buf)
432+
pr_warning("%s\n", log_buf);
433+
goto done;
434+
}
435+
436+
done:
437+
free(log_buf);
438+
return err;
439+
}
440+
431441
int btf__fd(const struct btf *btf)
432442
{
433443
return btf->fd;
434444
}
435445

436-
void btf__get_strings(const struct btf *btf, const char **strings,
437-
__u32 *str_len)
446+
const void *btf__get_raw_data(const struct btf *btf, __u32 *size)
438447
{
439-
*strings = btf->strings;
440-
*str_len = btf->hdr->str_len;
448+
*size = btf->data_size;
449+
return btf->data;
441450
}
442451

443452
const char *btf__name_by_offset(const struct btf *btf, __u32 offset)
@@ -584,45 +593,38 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
584593
return 0;
585594
}
586595

587-
struct btf_ext_sec_copy_param {
596+
struct btf_ext_sec_setup_param {
588597
__u32 off;
589598
__u32 len;
590599
__u32 min_rec_size;
591600
struct btf_ext_info *ext_info;
592601
const char *desc;
593602
};
594603

595-
static int btf_ext_copy_info(struct btf_ext *btf_ext,
596-
__u8 *data, __u32 data_size,
597-
struct btf_ext_sec_copy_param *ext_sec)
604+
static int btf_ext_setup_info(struct btf_ext *btf_ext,
605+
struct btf_ext_sec_setup_param *ext_sec)
598606
{
599-
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
600607
const struct btf_ext_info_sec *sinfo;
601608
struct btf_ext_info *ext_info;
602609
__u32 info_left, record_size;
603610
/* The start of the info sec (including the __u32 record_size). */
604-
const void *info;
605-
606-
/* data and data_size do not include btf_ext_header from now on */
607-
data = data + hdr->hdr_len;
608-
data_size -= hdr->hdr_len;
611+
void *info;
609612

610613
if (ext_sec->off & 0x03) {
611614
pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
612615
ext_sec->desc);
613616
return -EINVAL;
614617
}
615618

616-
if (data_size < ext_sec->off ||
617-
ext_sec->len > data_size - ext_sec->off) {
619+
info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
620+
info_left = ext_sec->len;
621+
622+
if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) {
618623
pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
619-
ext_sec->desc, ext_sec->off, ext_sec->len);
624+
ext_sec->desc, ext_sec->off, ext_sec->len);
620625
return -EINVAL;
621626
}
622627

623-
info = data + ext_sec->off;
624-
info_left = ext_sec->len;
625-
626628
/* At least a record size */
627629
if (info_left < sizeof(__u32)) {
628630
pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);
@@ -634,7 +636,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
634636
if (record_size < ext_sec->min_rec_size ||
635637
record_size & 0x03) {
636638
pr_debug("%s section in .BTF.ext has invalid record size %u\n",
637-
ext_sec->desc, record_size);
639+
ext_sec->desc, record_size);
638640
return -EINVAL;
639641
}
640642

@@ -680,42 +682,35 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
680682
ext_info = ext_sec->ext_info;
681683
ext_info->len = ext_sec->len - sizeof(__u32);
682684
ext_info->rec_size = record_size;
683-
ext_info->info = malloc(ext_info->len);
684-
if (!ext_info->info)
685-
return -ENOMEM;
686-
memcpy(ext_info->info, info + sizeof(__u32), ext_info->len);
685+
ext_info->info = info + sizeof(__u32);
687686

688687
return 0;
689688
}
690689

691-
static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
692-
__u8 *data, __u32 data_size)
690+
static int btf_ext_setup_func_info(struct btf_ext *btf_ext)
693691
{
694-
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
695-
struct btf_ext_sec_copy_param param = {
696-
.off = hdr->func_info_off,
697-
.len = hdr->func_info_len,
692+
struct btf_ext_sec_setup_param param = {
693+
.off = btf_ext->hdr->func_info_off,
694+
.len = btf_ext->hdr->func_info_len,
698695
.min_rec_size = sizeof(struct bpf_func_info_min),
699696
.ext_info = &btf_ext->func_info,
700697
.desc = "func_info"
701698
};
702699

703-
return btf_ext_copy_info(btf_ext, data, data_size, &param);
700+
return btf_ext_setup_info(btf_ext, &param);
704701
}
705702

706-
static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
707-
__u8 *data, __u32 data_size)
703+
static int btf_ext_setup_line_info(struct btf_ext *btf_ext)
708704
{
709-
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
710-
struct btf_ext_sec_copy_param param = {
711-
.off = hdr->line_info_off,
712-
.len = hdr->line_info_len,
705+
struct btf_ext_sec_setup_param param = {
706+
.off = btf_ext->hdr->line_info_off,
707+
.len = btf_ext->hdr->line_info_len,
713708
.min_rec_size = sizeof(struct bpf_line_info_min),
714709
.ext_info = &btf_ext->line_info,
715710
.desc = "line_info",
716711
};
717712

718-
return btf_ext_copy_info(btf_ext, data, data_size, &param);
713+
return btf_ext_setup_info(btf_ext, &param);
719714
}
720715

721716
static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)
@@ -755,9 +750,7 @@ void btf_ext__free(struct btf_ext *btf_ext)
755750
{
756751
if (!btf_ext)
757752
return;
758-
759-
free(btf_ext->func_info.info);
760-
free(btf_ext->line_info.info);
753+
free(btf_ext->data);
761754
free(btf_ext);
762755
}
763756

@@ -774,13 +767,23 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
774767
if (!btf_ext)
775768
return ERR_PTR(-ENOMEM);
776769

777-
err = btf_ext_copy_func_info(btf_ext, data, size);
778-
if (err) {
779-
btf_ext__free(btf_ext);
780-
return ERR_PTR(err);
770+
btf_ext->data_size = size;
771+
btf_ext->data = malloc(size);
772+
if (!btf_ext->data) {
773+
err = -ENOMEM;
774+
goto done;
781775
}
776+
memcpy(btf_ext->data, data, size);
782777

783-
err = btf_ext_copy_line_info(btf_ext, data, size);
778+
err = btf_ext_setup_func_info(btf_ext);
779+
if (err)
780+
goto done;
781+
782+
err = btf_ext_setup_line_info(btf_ext);
783+
if (err)
784+
goto done;
785+
786+
done:
784787
if (err) {
785788
btf_ext__free(btf_ext);
786789
return ERR_PTR(err);
@@ -789,6 +792,12 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
789792
return btf_ext;
790793
}
791794

795+
const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size)
796+
{
797+
*size = btf_ext->data_size;
798+
return btf_ext->data;
799+
}
800+
792801
static int btf_ext_reloc_info(const struct btf *btf,
793802
const struct btf_ext_info *ext_info,
794803
const char *sec_name, __u32 insns_cnt,
@@ -837,15 +846,17 @@ static int btf_ext_reloc_info(const struct btf *btf,
837846
return -ENOENT;
838847
}
839848

840-
int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ext,
849+
int btf_ext__reloc_func_info(const struct btf *btf,
850+
const struct btf_ext *btf_ext,
841851
const char *sec_name, __u32 insns_cnt,
842852
void **func_info, __u32 *cnt)
843853
{
844854
return btf_ext_reloc_info(btf, &btf_ext->func_info, sec_name,
845855
insns_cnt, func_info, cnt);
846856
}
847857

848-
int btf_ext__reloc_line_info(const struct btf *btf, const struct btf_ext *btf_ext,
858+
int btf_ext__reloc_line_info(const struct btf *btf,
859+
const struct btf_ext *btf_ext,
849860
const char *sec_name, __u32 insns_cnt,
850861
void **line_info, __u32 *cnt)
851862
{

tools/lib/bpf/btf.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct btf_ext_header {
5757

5858
LIBBPF_API void btf__free(struct btf *btf);
5959
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size);
60+
LIBBPF_API int btf__load(struct btf *btf);
6061
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
6162
const char *type_name);
6263
LIBBPF_API __u32 btf__get_nr_types(const struct btf *btf);
@@ -65,8 +66,7 @@ LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
6566
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
6667
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
6768
LIBBPF_API int btf__fd(const struct btf *btf);
68-
LIBBPF_API void btf__get_strings(const struct btf *btf, const char **strings,
69-
__u32 *str_len);
69+
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
7070
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
7171
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
7272
LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
@@ -76,6 +76,8 @@ LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
7676

7777
LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
7878
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
79+
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext* btf_ext,
80+
__u32 *size);
7981
LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf,
8082
const struct btf_ext *btf_ext,
8183
const char *sec_name, __u32 insns_cnt,

tools/lib/bpf/libbpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
836836
obj->efile.maps_shndx = idx;
837837
else if (strcmp(name, BTF_ELF_SEC) == 0) {
838838
obj->btf = btf__new(data->d_buf, data->d_size);
839-
if (IS_ERR(obj->btf)) {
839+
if (IS_ERR(obj->btf) || btf__load(obj->btf)) {
840840
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
841841
BTF_ELF_SEC, PTR_ERR(obj->btf));
842842
obj->btf = NULL;

tools/lib/bpf/libbpf.map

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,11 @@ LIBBPF_0.0.2 {
136136
btf__dedup;
137137
btf__get_map_kv_tids;
138138
btf__get_nr_types;
139-
btf__get_strings;
139+
btf__get_raw_data;
140+
btf__load;
140141
btf_ext__free;
141142
btf_ext__func_info_rec_size;
143+
btf_ext__get_raw_data;
142144
btf_ext__line_info_rec_size;
143145
btf_ext__new;
144146
btf_ext__reloc_func_info;

0 commit comments

Comments
 (0)