// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2024, Oracle and/or its affiliates. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef __KERNEL__ #include <linux/bpf.h> #include <linux/bsearch.h> #include <linux/btf.h> #include <linux/sort.h> #include <linux/string.h> #include <linux/bpf_verifier.h> #define btf_type_by_id … #define btf__type_cnt … #define btf__base_btf … #define btf__name_by_offset … #define btf__str_by_offset … #define btf_kflag … #define calloc(nmemb, sz) … #define free(ptr) … #define qsort(base, num, sz, cmp) … #else #include "btf.h" #include "bpf.h" #include "libbpf.h" #include "libbpf_internal.h" #endif /* __KERNEL__ */ struct btf; struct btf_relocate { … }; /* Set temporarily in relocation id_map if distilled base struct/union is * embedded in a split BTF struct/union; in such a case, size information must * match between distilled base BTF and base BTF representation of type. */ #define BTF_IS_EMBEDDED … /* <name, size, id> triple used in sorting/searching distilled base BTF. */ struct btf_name_info { … }; static int btf_relocate_rewrite_type_id(struct btf_relocate *r, __u32 i) { … } /* Simple string comparison used for sorting within BTF, since all distilled * types are named. If strings match, and size is non-zero for both elements * fall back to using size for ordering. */ static int cmp_btf_name_size(const void *n1, const void *n2) { … } /* Binary search with a small twist; find leftmost element that matches * so that we can then iterate through all exact matches. So for example * searching { "a", "bb", "bb", "c" } we would always match on the * leftmost "bb". */ static struct btf_name_info *search_btf_name_size(struct btf_name_info *key, struct btf_name_info *vals, int nelems) { … } /* If a member of a split BTF struct/union refers to a base BTF * struct/union, mark that struct/union id temporarily in the id_map * with BTF_IS_EMBEDDED. Members can be const/restrict/volatile/typedef * reference types, but if a pointer is encountered, the type is no longer * considered embedded. */ static int btf_mark_embedded_composite_type_ids(struct btf_relocate *r, __u32 i) { … } /* Build a map from distilled base BTF ids to base BTF ids. To do so, iterate * through base BTF looking up distilled type (using binary search) equivalents. */ static int btf_relocate_map_distilled_base(struct btf_relocate *r) { … } /* distilled base should only have named int/float/enum/fwd/struct/union types. */ static int btf_relocate_validate_distilled_base(struct btf_relocate *r) { … } static int btf_relocate_rewrite_strs(struct btf_relocate *r, __u32 i) { … } /* If successful, output of relocation is updated BTF with base BTF pointing * at base_btf, and type ids, strings adjusted accordingly. */ int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map) { … }