1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2024, Oracle and/or its affiliates. */
3
4 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE
6 #endif
7
8 #ifdef __KERNEL__
9 #include <linux/bpf.h>
10 #include <linux/bsearch.h>
11 #include <linux/btf.h>
12 #include <linux/sort.h>
13 #include <linux/string.h>
14 #include <linux/bpf_verifier.h>
15
16 #define btf_type_by_id (struct btf_type *)btf_type_by_id
17 #define btf__type_cnt btf_nr_types
18 #define btf__base_btf btf_base_btf
19 #define btf__name_by_offset btf_name_by_offset
20 #define btf__str_by_offset btf_str_by_offset
21 #define btf_kflag btf_type_kflag
22
23 #define calloc(nmemb, sz) kvcalloc(nmemb, sz, GFP_KERNEL | __GFP_NOWARN)
24 #define free(ptr) kvfree(ptr)
25 #define qsort(base, num, sz, cmp) sort(base, num, sz, cmp, NULL)
26
27 #else
28
29 #include "btf.h"
30 #include "bpf.h"
31 #include "libbpf.h"
32 #include "libbpf_internal.h"
33
34 #endif /* __KERNEL__ */
35
36 struct btf;
37
38 struct btf_relocate {
39 struct btf *btf;
40 const struct btf *base_btf;
41 const struct btf *dist_base_btf;
42 unsigned int nr_base_types;
43 unsigned int nr_split_types;
44 unsigned int nr_dist_base_types;
45 int dist_str_len;
46 int base_str_len;
47 __u32 *id_map;
48 __u32 *str_map;
49 };
50
51 /* Set temporarily in relocation id_map if distilled base struct/union is
52 * embedded in a split BTF struct/union; in such a case, size information must
53 * match between distilled base BTF and base BTF representation of type.
54 */
55 #define BTF_IS_EMBEDDED ((__u32)-1)
56
57 /* <name, size, id> triple used in sorting/searching distilled base BTF. */
58 struct btf_name_info {
59 const char *name;
60 /* set when search requires a size match */
61 bool needs_size: 1;
62 unsigned int size: 31;
63 __u32 id;
64 };
65
btf_relocate_rewrite_type_id(struct btf_relocate * r,__u32 i)66 static int btf_relocate_rewrite_type_id(struct btf_relocate *r, __u32 i)
67 {
68 struct btf_type *t = btf_type_by_id(r->btf, i);
69 struct btf_field_iter it;
70 __u32 *id;
71 int err;
72
73 err = btf_field_iter_init(&it, t, BTF_FIELD_ITER_IDS);
74 if (err)
75 return err;
76
77 while ((id = btf_field_iter_next(&it)))
78 *id = r->id_map[*id];
79 return 0;
80 }
81
82 /* Simple string comparison used for sorting within BTF, since all distilled
83 * types are named. If strings match, and size is non-zero for both elements
84 * fall back to using size for ordering.
85 */
cmp_btf_name_size(const void * n1,const void * n2)86 static int cmp_btf_name_size(const void *n1, const void *n2)
87 {
88 const struct btf_name_info *ni1 = n1;
89 const struct btf_name_info *ni2 = n2;
90 int name_diff = strcmp(ni1->name, ni2->name);
91
92 if (!name_diff && ni1->needs_size && ni2->needs_size)
93 return ni2->size - ni1->size;
94 return name_diff;
95 }
96
97 /* Binary search with a small twist; find leftmost element that matches
98 * so that we can then iterate through all exact matches. So for example
99 * searching { "a", "bb", "bb", "c" } we would always match on the
100 * leftmost "bb".
101 */
search_btf_name_size(struct btf_name_info * key,struct btf_name_info * vals,int nelems)102 static struct btf_name_info *search_btf_name_size(struct btf_name_info *key,
103 struct btf_name_info *vals,
104 int nelems)
105 {
106 struct btf_name_info *ret = NULL;
107 int high = nelems - 1;
108 int low = 0;
109
110 while (low <= high) {
111 int mid = (low + high)/2;
112 struct btf_name_info *val = &vals[mid];
113 int diff = cmp_btf_name_size(key, val);
114
115 if (diff == 0)
116 ret = val;
117 /* even if found, keep searching for leftmost match */
118 if (diff <= 0)
119 high = mid - 1;
120 else
121 low = mid + 1;
122 }
123 return ret;
124 }
125
126 /* If a member of a split BTF struct/union refers to a base BTF
127 * struct/union, mark that struct/union id temporarily in the id_map
128 * with BTF_IS_EMBEDDED. Members can be const/restrict/volatile/typedef
129 * reference types, but if a pointer is encountered, the type is no longer
130 * considered embedded.
131 */
btf_mark_embedded_composite_type_ids(struct btf_relocate * r,__u32 i)132 static int btf_mark_embedded_composite_type_ids(struct btf_relocate *r, __u32 i)
133 {
134 struct btf_type *t = btf_type_by_id(r->btf, i);
135 struct btf_field_iter it;
136 __u32 *id;
137 int err;
138
139 if (!btf_is_composite(t))
140 return 0;
141
142 err = btf_field_iter_init(&it, t, BTF_FIELD_ITER_IDS);
143 if (err)
144 return err;
145
146 while ((id = btf_field_iter_next(&it))) {
147 __u32 next_id = *id;
148
149 while (next_id) {
150 t = btf_type_by_id(r->btf, next_id);
151 switch (btf_kind(t)) {
152 case BTF_KIND_CONST:
153 case BTF_KIND_RESTRICT:
154 case BTF_KIND_VOLATILE:
155 case BTF_KIND_TYPEDEF:
156 case BTF_KIND_TYPE_TAG:
157 next_id = t->type;
158 break;
159 case BTF_KIND_ARRAY: {
160 struct btf_array *a = btf_array(t);
161
162 next_id = a->type;
163 break;
164 }
165 case BTF_KIND_STRUCT:
166 case BTF_KIND_UNION:
167 if (next_id < r->nr_dist_base_types)
168 r->id_map[next_id] = BTF_IS_EMBEDDED;
169 next_id = 0;
170 break;
171 default:
172 next_id = 0;
173 break;
174 }
175 }
176 }
177
178 return 0;
179 }
180
181 /* Build a map from distilled base BTF ids to base BTF ids. To do so, iterate
182 * through base BTF looking up distilled type (using binary search) equivalents.
183 */
btf_relocate_map_distilled_base(struct btf_relocate * r)184 static int btf_relocate_map_distilled_base(struct btf_relocate *r)
185 {
186 struct btf_name_info *info, *info_end;
187 struct btf_type *base_t, *dist_t;
188 __u8 *base_name_cnt = NULL;
189 int err = 0;
190 __u32 id;
191
192 /* generate a sort index array of name/type ids sorted by name for
193 * distilled base BTF to speed name-based lookups.
194 */
195 info = calloc(r->nr_dist_base_types, sizeof(*info));
196 if (!info) {
197 err = -ENOMEM;
198 goto done;
199 }
200 info_end = info + r->nr_dist_base_types;
201 for (id = 0; id < r->nr_dist_base_types; id++) {
202 dist_t = btf_type_by_id(r->dist_base_btf, id);
203 info[id].name = btf__name_by_offset(r->dist_base_btf, dist_t->name_off);
204 info[id].id = id;
205 info[id].size = dist_t->size;
206 info[id].needs_size = true;
207 }
208 qsort(info, r->nr_dist_base_types, sizeof(*info), cmp_btf_name_size);
209
210 /* Mark distilled base struct/union members of split BTF structs/unions
211 * in id_map with BTF_IS_EMBEDDED; this signals that these types
212 * need to match both name and size, otherwise embedding the base
213 * struct/union in the split type is invalid.
214 */
215 for (id = r->nr_dist_base_types; id < r->nr_split_types; id++) {
216 err = btf_mark_embedded_composite_type_ids(r, id);
217 if (err)
218 goto done;
219 }
220
221 /* Collect name counts for composite types in base BTF. If multiple
222 * instances of a struct/union of the same name exist, we need to use
223 * size to determine which to map to since name alone is ambiguous.
224 */
225 base_name_cnt = calloc(r->base_str_len, sizeof(*base_name_cnt));
226 if (!base_name_cnt) {
227 err = -ENOMEM;
228 goto done;
229 }
230 for (id = 1; id < r->nr_base_types; id++) {
231 base_t = btf_type_by_id(r->base_btf, id);
232 if (!btf_is_composite(base_t) || !base_t->name_off)
233 continue;
234 if (base_name_cnt[base_t->name_off] < 255)
235 base_name_cnt[base_t->name_off]++;
236 }
237
238 /* Now search base BTF for matching distilled base BTF types. */
239 for (id = 1; id < r->nr_base_types; id++) {
240 struct btf_name_info *dist_info, base_info = {};
241 int dist_kind, base_kind;
242
243 base_t = btf_type_by_id(r->base_btf, id);
244 /* distilled base consists of named types only. */
245 if (!base_t->name_off)
246 continue;
247 base_kind = btf_kind(base_t);
248 base_info.id = id;
249 base_info.name = btf__name_by_offset(r->base_btf, base_t->name_off);
250 switch (base_kind) {
251 case BTF_KIND_INT:
252 case BTF_KIND_FLOAT:
253 case BTF_KIND_ENUM:
254 case BTF_KIND_ENUM64:
255 /* These types should match both name and size */
256 base_info.needs_size = true;
257 base_info.size = base_t->size;
258 break;
259 case BTF_KIND_FWD:
260 /* No size considerations for fwds. */
261 break;
262 case BTF_KIND_STRUCT:
263 case BTF_KIND_UNION:
264 /* Size only needs to be used for struct/union if there
265 * are multiple types in base BTF with the same name.
266 * If there are multiple _distilled_ types with the same
267 * name (a very unlikely scenario), that doesn't matter
268 * unless corresponding _base_ types to match them are
269 * missing.
270 */
271 base_info.needs_size = base_name_cnt[base_t->name_off] > 1;
272 base_info.size = base_t->size;
273 break;
274 default:
275 continue;
276 }
277 /* iterate over all matching distilled base types */
278 for (dist_info = search_btf_name_size(&base_info, info, r->nr_dist_base_types);
279 dist_info != NULL && dist_info < info_end &&
280 cmp_btf_name_size(&base_info, dist_info) == 0;
281 dist_info++) {
282 if (!dist_info->id || dist_info->id >= r->nr_dist_base_types) {
283 pr_warn("base BTF id [%d] maps to invalid distilled base BTF id [%d]\n",
284 id, dist_info->id);
285 err = -EINVAL;
286 goto done;
287 }
288 dist_t = btf_type_by_id(r->dist_base_btf, dist_info->id);
289 dist_kind = btf_kind(dist_t);
290
291 /* Validate that the found distilled type is compatible.
292 * Do not error out on mismatch as another match may
293 * occur for an identically-named type.
294 */
295 switch (dist_kind) {
296 case BTF_KIND_FWD:
297 switch (base_kind) {
298 case BTF_KIND_FWD:
299 if (btf_kflag(dist_t) != btf_kflag(base_t))
300 continue;
301 break;
302 case BTF_KIND_STRUCT:
303 if (btf_kflag(base_t))
304 continue;
305 break;
306 case BTF_KIND_UNION:
307 if (!btf_kflag(base_t))
308 continue;
309 break;
310 default:
311 continue;
312 }
313 break;
314 case BTF_KIND_INT:
315 if (dist_kind != base_kind ||
316 btf_int_encoding(base_t) != btf_int_encoding(dist_t))
317 continue;
318 break;
319 case BTF_KIND_FLOAT:
320 if (dist_kind != base_kind)
321 continue;
322 break;
323 case BTF_KIND_ENUM:
324 /* ENUM and ENUM64 are encoded as sized ENUM in
325 * distilled base BTF.
326 */
327 if (base_kind != dist_kind && base_kind != BTF_KIND_ENUM64)
328 continue;
329 break;
330 case BTF_KIND_STRUCT:
331 case BTF_KIND_UNION:
332 /* size verification is required for embedded
333 * struct/unions.
334 */
335 if (r->id_map[dist_info->id] == BTF_IS_EMBEDDED &&
336 base_t->size != dist_t->size)
337 continue;
338 break;
339 default:
340 continue;
341 }
342 if (r->id_map[dist_info->id] &&
343 r->id_map[dist_info->id] != BTF_IS_EMBEDDED) {
344 /* we already have a match; this tells us that
345 * multiple base types of the same name
346 * have the same size, since for cases where
347 * multiple types have the same name we match
348 * on name and size. In this case, we have
349 * no way of determining which to relocate
350 * to in base BTF, so error out.
351 */
352 pr_warn("distilled base BTF type '%s' [%u], size %u has multiple candidates of the same size (ids [%u, %u]) in base BTF\n",
353 base_info.name, dist_info->id,
354 base_t->size, id, r->id_map[dist_info->id]);
355 err = -EINVAL;
356 goto done;
357 }
358 /* map id and name */
359 r->id_map[dist_info->id] = id;
360 r->str_map[dist_t->name_off] = base_t->name_off;
361 }
362 }
363 /* ensure all distilled BTF ids now have a mapping... */
364 for (id = 1; id < r->nr_dist_base_types; id++) {
365 const char *name;
366
367 if (r->id_map[id] && r->id_map[id] != BTF_IS_EMBEDDED)
368 continue;
369 dist_t = btf_type_by_id(r->dist_base_btf, id);
370 name = btf__name_by_offset(r->dist_base_btf, dist_t->name_off);
371 pr_warn("distilled base BTF type '%s' [%d] is not mapped to base BTF id\n",
372 name, id);
373 err = -EINVAL;
374 break;
375 }
376 done:
377 free(base_name_cnt);
378 free(info);
379 return err;
380 }
381
382 /* distilled base should only have named int/float/enum/fwd/struct/union types. */
btf_relocate_validate_distilled_base(struct btf_relocate * r)383 static int btf_relocate_validate_distilled_base(struct btf_relocate *r)
384 {
385 unsigned int i;
386
387 for (i = 1; i < r->nr_dist_base_types; i++) {
388 struct btf_type *t = btf_type_by_id(r->dist_base_btf, i);
389 int kind = btf_kind(t);
390
391 switch (kind) {
392 case BTF_KIND_INT:
393 case BTF_KIND_FLOAT:
394 case BTF_KIND_ENUM:
395 case BTF_KIND_STRUCT:
396 case BTF_KIND_UNION:
397 case BTF_KIND_FWD:
398 if (t->name_off)
399 break;
400 pr_warn("type [%d], kind [%d] is invalid for distilled base BTF; it is anonymous\n",
401 i, kind);
402 return -EINVAL;
403 default:
404 pr_warn("type [%d] in distilled based BTF has unexpected kind [%d]\n",
405 i, kind);
406 return -EINVAL;
407 }
408 }
409 return 0;
410 }
411
btf_relocate_rewrite_strs(struct btf_relocate * r,__u32 i)412 static int btf_relocate_rewrite_strs(struct btf_relocate *r, __u32 i)
413 {
414 struct btf_type *t = btf_type_by_id(r->btf, i);
415 struct btf_field_iter it;
416 __u32 *str_off;
417 int off, err;
418
419 err = btf_field_iter_init(&it, t, BTF_FIELD_ITER_STRS);
420 if (err)
421 return err;
422
423 while ((str_off = btf_field_iter_next(&it))) {
424 if (!*str_off)
425 continue;
426 if (*str_off >= r->dist_str_len) {
427 *str_off += r->base_str_len - r->dist_str_len;
428 } else {
429 off = r->str_map[*str_off];
430 if (!off) {
431 pr_warn("string '%s' [offset %u] is not mapped to base BTF",
432 btf__str_by_offset(r->btf, off), *str_off);
433 return -ENOENT;
434 }
435 *str_off = off;
436 }
437 }
438 return 0;
439 }
440
441 /* If successful, output of relocation is updated BTF with base BTF pointing
442 * at base_btf, and type ids, strings adjusted accordingly.
443 */
btf_relocate(struct btf * btf,const struct btf * base_btf,__u32 ** id_map)444 int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map)
445 {
446 unsigned int nr_types = btf__type_cnt(btf);
447 const struct btf_header *dist_base_hdr;
448 const struct btf_header *base_hdr;
449 struct btf_relocate r = {};
450 int err = 0;
451 __u32 id, i;
452
453 r.dist_base_btf = btf__base_btf(btf);
454 if (!base_btf || r.dist_base_btf == base_btf)
455 return -EINVAL;
456
457 r.nr_dist_base_types = btf__type_cnt(r.dist_base_btf);
458 r.nr_base_types = btf__type_cnt(base_btf);
459 r.nr_split_types = nr_types - r.nr_dist_base_types;
460 r.btf = btf;
461 r.base_btf = base_btf;
462
463 r.id_map = calloc(nr_types, sizeof(*r.id_map));
464 r.str_map = calloc(btf_header(r.dist_base_btf)->str_len, sizeof(*r.str_map));
465 dist_base_hdr = btf_header(r.dist_base_btf);
466 base_hdr = btf_header(r.base_btf);
467 r.dist_str_len = dist_base_hdr->str_len;
468 r.base_str_len = base_hdr->str_len;
469 if (!r.id_map || !r.str_map) {
470 err = -ENOMEM;
471 goto err_out;
472 }
473
474 err = btf_relocate_validate_distilled_base(&r);
475 if (err)
476 goto err_out;
477
478 /* Split BTF ids need to be adjusted as base and distilled base
479 * have different numbers of types, changing the start id of split
480 * BTF.
481 */
482 for (id = r.nr_dist_base_types; id < nr_types; id++)
483 r.id_map[id] = id + r.nr_base_types - r.nr_dist_base_types;
484
485 /* Build a map from distilled base ids to actual base BTF ids; it is used
486 * to update split BTF id references. Also build a str_map mapping from
487 * distilled base BTF names to base BTF names.
488 */
489 err = btf_relocate_map_distilled_base(&r);
490 if (err)
491 goto err_out;
492
493 /* Next, rewrite type ids in split BTF, replacing split ids with updated
494 * ids based on number of types in base BTF, and base ids with
495 * relocated ids from base_btf.
496 */
497 for (i = 0, id = r.nr_dist_base_types; i < r.nr_split_types; i++, id++) {
498 err = btf_relocate_rewrite_type_id(&r, id);
499 if (err)
500 goto err_out;
501 }
502 /* String offsets now need to be updated using the str_map. */
503 for (i = 0; i < r.nr_split_types; i++) {
504 err = btf_relocate_rewrite_strs(&r, i + r.nr_dist_base_types);
505 if (err)
506 goto err_out;
507 }
508 /* Finally reset base BTF to be base_btf */
509 btf_set_base_btf(btf, base_btf);
510
511 if (id_map) {
512 *id_map = r.id_map;
513 r.id_map = NULL;
514 }
515 err_out:
516 free(r.id_map);
517 free(r.str_map);
518 return err;
519 }
520