Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'multi-split-btf-fixes-and-test'

Alan Maguire says:

====================
Multi-split BTF fixes and test

This small series consists of a fix to multi-split BTF parsing
(patch 1) and a test which exercises (multi-)split BTF parsing
(patch 2).

Changes since v3 [1]
- add asserts to ensure number of types in original and parsed
BTF are identical, and the calls to btf__type_by_id() return
valid pointers (code review bot, patch 2)

Changes since v2 [2]

- fix Fixes: tag formatting (Andrii, patch 1)
- BPF code-review bot saw we were doing ASSERT_OK_PTR() on wrong
BTF (not multisplit) in patch 2
- ensure cleanup is correctly handled for BTF, unlink in split
tests (Andrii, patch 2)

Changes since v1 [3]

- BPF code-review bot spotted another place that the string offset
needed to be adjusted based upon base start string offset + header
string offset.
- added selftests to extend split BTF testing to parsing

[1] https://lore.kernel.org/bpf/20251028225544.1312356-1-alan.maguire@oracle.com/
[2] https://lore.kernel.org/bpf/20251028155709.1265445-1-alan.maguire@oracle.com/
[3] https://lore.kernel.org/bpf/20251023142812.258870-1-alan.maguire@oracle.com/
====================

Link: https://patch.msgid.link/20251104203309.318429-1-alan.maguire@oracle.com
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

+87 -4
+2 -2
tools/lib/bpf/btf.c
··· 1061 1061 if (base_btf) { 1062 1062 btf->base_btf = base_btf; 1063 1063 btf->start_id = btf__type_cnt(base_btf); 1064 - btf->start_str_off = base_btf->hdr->str_len; 1064 + btf->start_str_off = base_btf->hdr->str_len + base_btf->start_str_off; 1065 1065 } 1066 1066 1067 1067 if (is_mmap) { ··· 5818 5818 { 5819 5819 btf->base_btf = (struct btf *)base_btf; 5820 5820 btf->start_id = btf__type_cnt(base_btf); 5821 - btf->start_str_off = base_btf->hdr->str_len; 5821 + btf->start_str_off = base_btf->hdr->str_len + base_btf->start_str_off; 5822 5822 } 5823 5823 5824 5824 int btf__relocate(struct btf *btf, const struct btf *base_btf)
+85 -2
tools/testing/selftests/bpf/prog_tests/btf_split.c
··· 12 12 vfprintf(ctx, fmt, args); 13 13 } 14 14 15 + /* Write raw BTF to file, return number of bytes written or negative errno */ 16 + static ssize_t btf_raw_write(struct btf *btf, char *file) 17 + { 18 + ssize_t written = 0; 19 + const void *data; 20 + __u32 size = 0; 21 + int fd, ret; 22 + 23 + fd = mkstemp(file); 24 + if (!ASSERT_GE(fd, 0, "create_file")) 25 + return -errno; 26 + 27 + data = btf__raw_data(btf, &size); 28 + if (!ASSERT_OK_PTR(data, "btf__raw_data")) { 29 + close(fd); 30 + return -EINVAL; 31 + } 32 + while (written < size) { 33 + ret = write(fd, data + written, size - written); 34 + if (!ASSERT_GE(ret, 0, "write succeeded")) { 35 + close(fd); 36 + return -errno; 37 + } 38 + written += ret; 39 + } 40 + close(fd); 41 + return written; 42 + } 43 + 15 44 static void __test_btf_split(bool multi) 16 45 { 46 + char multisplit_btf_file[] = "/tmp/test_btf_multisplit.XXXXXX"; 47 + char split_btf_file[] = "/tmp/test_btf_split.XXXXXX"; 48 + char base_btf_file[] = "/tmp/test_btf_base.XXXXXX"; 49 + ssize_t multisplit_btf_sz = 0, split_btf_sz = 0, base_btf_sz = 0; 17 50 struct btf_dump *d = NULL; 18 - const struct btf_type *t; 19 - struct btf *btf1, *btf2, *btf3 = NULL; 51 + const struct btf_type *t, *ot; 52 + struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL; 53 + struct btf *btf4 = NULL, *btf5 = NULL, *btf6 = NULL; 20 54 int str_off, i, err; 21 55 22 56 btf1 = btf__new_empty(); ··· 157 123 " int uf2;\n" 158 124 "};\n\n", "c_dump"); 159 125 126 + /* write base, split BTFs to files and ensure parsing succeeds */ 127 + base_btf_sz = btf_raw_write(btf1, base_btf_file); 128 + if (base_btf_sz < 0) 129 + goto cleanup; 130 + split_btf_sz = btf_raw_write(btf2, split_btf_file); 131 + if (split_btf_sz < 0) 132 + goto cleanup; 133 + btf4 = btf__parse(base_btf_file, NULL); 134 + if (!ASSERT_OK_PTR(btf4, "parse_base")) 135 + goto cleanup; 136 + btf5 = btf__parse_split(split_btf_file, btf4); 137 + if (!ASSERT_OK_PTR(btf5, "parse_split")) 138 + goto cleanup; 139 + if (multi) { 140 + multisplit_btf_sz = btf_raw_write(btf3, multisplit_btf_file); 141 + if (multisplit_btf_sz < 0) 142 + goto cleanup; 143 + btf6 = btf__parse_split(multisplit_btf_file, btf5); 144 + if (!ASSERT_OK_PTR(btf6, "parse_multisplit")) 145 + goto cleanup; 146 + } else { 147 + btf6 = btf5; 148 + } 149 + 150 + if (!ASSERT_EQ(btf__type_cnt(btf3), btf__type_cnt(btf6), "cmp_type_cnt")) 151 + goto cleanup; 152 + 153 + /* compare parsed to original BTF */ 154 + for (i = 1; i < btf__type_cnt(btf6); i++) { 155 + t = btf__type_by_id(btf6, i); 156 + if (!ASSERT_OK_PTR(t, "type_in_parsed_btf")) 157 + goto cleanup; 158 + ot = btf__type_by_id(btf3, i); 159 + if (!ASSERT_OK_PTR(ot, "type_in_orig_btf")) 160 + goto cleanup; 161 + if (!ASSERT_EQ(memcmp(t, ot, sizeof(*ot)), 0, "cmp_parsed_orig_btf")) 162 + goto cleanup; 163 + } 164 + 160 165 cleanup: 161 166 if (dump_buf_file) 162 167 fclose(dump_buf_file); ··· 205 132 btf__free(btf2); 206 133 if (btf2 != btf3) 207 134 btf__free(btf3); 135 + btf__free(btf4); 136 + btf__free(btf5); 137 + if (btf5 != btf6) 138 + btf__free(btf6); 139 + if (base_btf_sz > 0) 140 + unlink(base_btf_file); 141 + if (split_btf_sz > 0) 142 + unlink(split_btf_file); 143 + if (multisplit_btf_sz > 0) 144 + unlink(multisplit_btf_file); 208 145 } 209 146 210 147 void test_btf_split(void)