Instead of compile-time checks for libbpf version, use __weak declarations of the required API functions and do runtime checks at the call sites. This will help with compatibility when libbpf is dynamically linked to pahole [1]. [1] https://lore.kernel.org/dwarves/deff78f8-1f99-4c79-a302-cff8dce4d803@xxxxxxxxxx/ Signed-off-by: Ihor Solodrai <ihor.solodrai@xxxxxxxxx> --- btf_encoder.c | 48 +++++++++++++++++++----------------------------- dwarves.h | 11 ++++++++++- pahole.c | 2 -- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 2bea5ee..12a040f 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -34,6 +34,7 @@ #include <search.h> /* for tsearch(), tfind() and tdestroy() */ #include <pthread.h> +#define BTF_BASE_ELF_SEC ".BTF.base" #define BTF_IDS_SECTION ".BTF_ids" #define BTF_ID_FUNC_PFX "__BTF_ID__func__" #define BTF_ID_SET8_PFX "__BTF_ID__set8__" @@ -625,29 +626,6 @@ static int32_t btf_encoder__add_struct(struct btf_encoder *encoder, uint8_t kind return id; } -#if LIBBPF_MAJOR_VERSION < 1 -static inline int libbpf_err(int ret) -{ - if (ret < 0) - errno = -ret; - return ret; -} - -static -int btf__add_enum64(struct btf *btf __maybe_unused, const char *name __maybe_unused, - __u32 byte_sz __maybe_unused, bool is_signed __maybe_unused) -{ - return libbpf_err(-ENOTSUP); -} - -static -int btf__add_enum64_value(struct btf *btf __maybe_unused, const char *name __maybe_unused, - __u64 value __maybe_unused) -{ - return libbpf_err(-ENOTSUP); -} -#endif - static int32_t btf_encoder__add_enum(struct btf_encoder *encoder, const char *name, struct type *etype, struct conf_load *conf_load) { @@ -660,8 +638,13 @@ static int32_t btf_encoder__add_enum(struct btf_encoder *encoder, const char *na is_enum32 = size <= 4 || conf_load->skip_encoding_btf_enum64; if (is_enum32) id = btf__add_enum(btf, name, size); - else + else if (btf__add_enum64) id = btf__add_enum64(btf, name, size, etype->is_signed_enum); + else { + fprintf(stderr, "btf__add_enum64 is not available, is libbpf < 1.0?\n"); + return -ENOTSUP; + } + if (id > 0) { t = btf__type_by_id(btf, id); btf_encoder__log_type(encoder, t, false, true, "size=%u", t->size); @@ -684,10 +667,14 @@ static int btf_encoder__add_enum_val(struct btf_encoder *encoder, const char *na */ if (conf_load->skip_encoding_btf_enum64) err = btf__add_enum_value(encoder->btf, name, (uint32_t)value); - else if (etype->size > 32) - err = btf__add_enum64_value(encoder->btf, name, value); - else + else if (etype->size <= 32) err = btf__add_enum_value(encoder->btf, name, value); + else if (btf__add_enum64_value) + err = btf__add_enum64_value(encoder->btf, name, value); + else { + fprintf(stderr, "btf__add_enum64_value is not available, is libbpf < 1.0?\n"); + return -ENOTSUP; + } if (!err) { if (encoder->verbose) { @@ -2035,10 +2022,14 @@ int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf) * silently ignore the feature request if libbpf does not * support it. */ -#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 5 if (encoder->gen_distilled_base) { struct btf *btf = NULL, *distilled_base = NULL; + if (!btf__distill_base) { + fprintf(stderr, "btf__distill_base is not available, is libbpf < 1.5?\n"); + return -ENOTSUP; + } + if (btf__distill_base(encoder->btf, &distilled_base, &btf) < 0) { fprintf(stderr, "could not generate distilled base BTF: %s\n", strerror(errno)); @@ -2051,7 +2042,6 @@ int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf) btf__free(distilled_base); return err; } -#endif err = btf_encoder__write_elf(encoder, encoder->btf, BTF_ELF_SEC); } diff --git a/dwarves.h b/dwarves.h index 8234e1a..ab32204 100644 --- a/dwarves.h +++ b/dwarves.h @@ -14,6 +14,7 @@ #include <obstack.h> #include <dwarf.h> #include <elfutils/libdwfl.h> +#include <linux/types.h> #include <sys/types.h> #include "dutil.h" @@ -44,13 +45,21 @@ enum load_steal_kind { LSK__STOP_LOADING, }; +/* + * Weak declarations of libbpf APIs that are version-dependent + */ +#define __weak __attribute__((weak)) +struct btf; +__weak extern int btf__add_enum64(struct btf *btf, const char *name, __u32 byte_sz, bool is_signed); +__weak extern int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value); +__weak extern int btf__distill_base(const struct btf *src_btf, struct btf **new_base_btf, struct btf **new_split_btf); + /* * BTF combines all the types into one big CU using btf_dedup(), so for something * like a allyesconfig vmlinux kernel we can get over 65535 types. */ typedef uint32_t type_id_t; -struct btf; struct conf_fprintf; /** struct conf_load - load configuration diff --git a/pahole.c b/pahole.c index af3e1cf..09aed1c 100644 --- a/pahole.c +++ b/pahole.c @@ -1206,9 +1206,7 @@ struct btf_feature { BTF_DEFAULT_FEATURE(consistent_func, skip_encoding_btf_inconsistent_proto, false), BTF_DEFAULT_FEATURE(decl_tag_kfuncs, btf_decl_tag_kfuncs, false), BTF_NON_DEFAULT_FEATURE(reproducible_build, reproducible_build, false), -#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 5 BTF_NON_DEFAULT_FEATURE(distilled_base, btf_gen_distilled_base, false), -#endif BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false), }; -- 2.48.1