1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2024, Oracle and/or its affiliates. */
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>
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
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)
32 #include "libbpf_internal.h"
34 #endif /* __KERNEL__ */
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
;
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.
55 #define BTF_IS_EMBEDDED ((__u32)-1)
57 /* <name, size, id> triple used in sorting/searching distilled base BTF. */
58 struct btf_name_info
{
60 /* set when search requires a size match */
62 unsigned int size
: 31;
66 static int btf_relocate_rewrite_type_id(struct btf_relocate
*r
, __u32 i
)
68 struct btf_type
*t
= btf_type_by_id(r
->btf
, i
);
69 struct btf_field_iter it
;
73 err
= btf_field_iter_init(&it
, t
, BTF_FIELD_ITER_IDS
);
77 while ((id
= btf_field_iter_next(&it
)))
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.
86 static int cmp_btf_name_size(const void *n1
, const void *n2
)
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
);
92 if (!name_diff
&& ni1
->needs_size
&& ni2
->needs_size
)
93 return ni2
->size
- ni1
->size
;
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
102 static struct btf_name_info
*search_btf_name_size(struct btf_name_info
*key
,
103 struct btf_name_info
*vals
,
106 struct btf_name_info
*ret
= NULL
;
107 int high
= nelems
- 1;
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
);
117 /* even if found, keep searching for leftmost match */
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.
132 static int btf_mark_embedded_composite_type_ids(struct btf_relocate
*r
, __u32 i
)
134 struct btf_type
*t
= btf_type_by_id(r
->btf
, i
);
135 struct btf_field_iter it
;
139 if (!btf_is_composite(t
))
142 err
= btf_field_iter_init(&it
, t
, BTF_FIELD_ITER_IDS
);
146 while ((id
= btf_field_iter_next(&it
))) {
150 t
= btf_type_by_id(r
->btf
, next_id
);
151 switch (btf_kind(t
)) {
153 case BTF_KIND_RESTRICT
:
154 case BTF_KIND_VOLATILE
:
155 case BTF_KIND_TYPEDEF
:
156 case BTF_KIND_TYPE_TAG
:
159 case BTF_KIND_ARRAY
: {
160 struct btf_array
*a
= btf_array(t
);
165 case BTF_KIND_STRUCT
:
167 if (next_id
< r
->nr_dist_base_types
)
168 r
->id_map
[next_id
] = BTF_IS_EMBEDDED
;
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.
184 static int btf_relocate_map_distilled_base(struct btf_relocate
*r
)
186 struct btf_name_info
*info
, *info_end
;
187 struct btf_type
*base_t
, *dist_t
;
188 __u8
*base_name_cnt
= NULL
;
192 /* generate a sort index array of name/type ids sorted by name for
193 * distilled base BTF to speed name-based lookups.
195 info
= calloc(r
->nr_dist_base_types
, sizeof(*info
));
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
);
205 info
[id
].size
= dist_t
->size
;
206 info
[id
].needs_size
= true;
208 qsort(info
, r
->nr_dist_base_types
, sizeof(*info
), cmp_btf_name_size
);
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.
215 for (id
= r
->nr_dist_base_types
; id
< r
->nr_split_types
; id
++) {
216 err
= btf_mark_embedded_composite_type_ids(r
, id
);
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.
225 base_name_cnt
= calloc(r
->base_str_len
, sizeof(*base_name_cnt
));
226 if (!base_name_cnt
) {
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
)
234 if (base_name_cnt
[base_t
->name_off
] < 255)
235 base_name_cnt
[base_t
->name_off
]++;
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
;
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
)
247 base_kind
= btf_kind(base_t
);
249 base_info
.name
= btf__name_by_offset(r
->base_btf
, base_t
->name_off
);
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
;
260 /* No size considerations for fwds. */
262 case BTF_KIND_STRUCT
:
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
271 base_info
.needs_size
= base_name_cnt
[base_t
->name_off
] > 1;
272 base_info
.size
= base_t
->size
;
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;
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",
288 dist_t
= btf_type_by_id(r
->dist_base_btf
, dist_info
->id
);
289 dist_kind
= btf_kind(dist_t
);
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.
299 if (btf_kflag(dist_t
) != btf_kflag(base_t
))
302 case BTF_KIND_STRUCT
:
303 if (btf_kflag(base_t
))
307 if (!btf_kflag(base_t
))
315 if (dist_kind
!= base_kind
||
316 btf_int_encoding(base_t
) != btf_int_encoding(dist_t
))
320 if (dist_kind
!= base_kind
)
324 /* ENUM and ENUM64 are encoded as sized ENUM in
325 * distilled base BTF.
327 if (base_kind
!= dist_kind
&& base_kind
!= BTF_KIND_ENUM64
)
330 case BTF_KIND_STRUCT
:
332 /* size verification is required for embedded
335 if (r
->id_map
[dist_info
->id
] == BTF_IS_EMBEDDED
&&
336 base_t
->size
!= dist_t
->size
)
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.
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
]);
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
;
363 /* ensure all distilled BTF ids now have a mapping... */
364 for (id
= 1; id
< r
->nr_dist_base_types
; id
++) {
367 if (r
->id_map
[id
] && r
->id_map
[id
] != BTF_IS_EMBEDDED
)
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",
382 /* distilled base should only have named int/float/enum/fwd/struct/union types. */
383 static int btf_relocate_validate_distilled_base(struct btf_relocate
*r
)
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
);
395 case BTF_KIND_STRUCT
:
400 pr_warn("type [%d], kind [%d] is invalid for distilled base BTF; it is anonymous\n",
404 pr_warn("type [%d] in distilled based BTF has unexpected kind [%d]\n",
412 static int btf_relocate_rewrite_strs(struct btf_relocate
*r
, __u32 i
)
414 struct btf_type
*t
= btf_type_by_id(r
->btf
, i
);
415 struct btf_field_iter it
;
419 err
= btf_field_iter_init(&it
, t
, BTF_FIELD_ITER_STRS
);
423 while ((str_off
= btf_field_iter_next(&it
))) {
426 if (*str_off
>= r
->dist_str_len
) {
427 *str_off
+= r
->base_str_len
- r
->dist_str_len
;
429 off
= r
->str_map
[*str_off
];
431 pr_warn("string '%s' [offset %u] is not mapped to base BTF\n",
432 btf__str_by_offset(r
->btf
, off
), *str_off
);
441 /* If successful, output of relocation is updated BTF with base BTF pointing
442 * at base_btf, and type ids, strings adjusted accordingly.
444 int btf_relocate(struct btf
*btf
, const struct btf
*base_btf
, __u32
**id_map
)
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
= {};
453 r
.dist_base_btf
= btf__base_btf(btf
);
454 if (!base_btf
|| r
.dist_base_btf
== base_btf
)
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
;
461 r
.base_btf
= base_btf
;
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
) {
474 err
= btf_relocate_validate_distilled_base(&r
);
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
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
;
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.
489 err
= btf_relocate_map_distilled_base(&r
);
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.
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
);
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
);
508 /* Finally reset base BTF to be base_btf */
509 btf_set_base_btf(btf
, base_btf
);