diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-10-11 14:18:07 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-11 14:18:07 +0000 |
| commit | ac1dff2daebb04816766106740042e7ad92859dd (patch) | |
| tree | abdf06d1a35a148b690237a4390acf81d764c718 /include | |
| parent | 4411c854408c05f083c828b69e72e3cc22384fbf (diff) | |
| parent | 400f0881c912af87091973f231c1b573c2b24292 (diff) | |
Merge branch 'kbuild-bpf-support-inline-info-in-btf'
Alan Maguire says:
====================
kbuild, bpf: Support inline info in BTF
If CONFIG_DEBUG_INFO_BTF_INLINE=y|m, add the "inline" BTF feature
and encode inline site info in BTF alongside standard BTF data.
resolve_btfids will then partition into non- and inline-related
info and split BTF will be used to store inline info in a
.BTF.inline section in vmlinux and modules. For
CONFIG_DEBUG_INFO_BTF=m, vmlinux inline info will be stored
in btf_vmlinux_inline.ko and will be loaded on-demand if used
via /sys/kernel/btf/vmlinux.inline. A .BTF.inline.link section
in vmlinux stores the module name, the SHA of the BTF and the
size so that even without loading the kernel can size the
sysfs representation correctly. This approach is based on [1]
and the .BTF.inline.link section is modeled on .GNU_debuglink.
Because a module can be built with .BTF.base to allow for
BTF relocation, its inline info needs to be relocated also
so a bit more work needs to be done to handle this.
Patches 1, 2 add resolve_btfids support to partition BTF
into .BTF and .BTF.inline and to support populating
a BTF link section for BTF_INLINE=m. Patch 3 handles
vmlinux.inline exposure in sysfs. Patch 4 does prep
work for relocation needed in patch 5 prior to exposing
relocated BTF in sysfs, and patches 6 and 7 test BTF
sysfs representations and inline validity using
bpf_testmod respectively.
To generate inline info the latest pahole is needed [2].
Inline info for vmlinux can be quite large ~10Mb for
over 600,000 inline sites in the kernel, so
CONFIG_DEBUG_INFO_BTF_INLINE=m
is recommended; this brings the on-disk size down below
4Mb for a gzip-compressed btf_vmlinux_inline.ko.
Changes since v3 [3]:
- Retain original BTF in resolve_btfids and be careful about
free order (bots, patch 1)
- Add more failure diagnostics to patching of BTF links
(bots, patch 2)
- Guard vmallocs for zero-sized inline data (bots, patch 3)
- Fix potential NULL pointer BTF deref (bots, patch 5)
- Fix up leaks in sysfs test (bots, patch 6)
- Fix up tests to use kallsyms lookup directly, and improve
validation of location info (bots, patch 7)
Changes since v2 [4]
- Delivered the libbpf, bpftool parts are prerequisites
- Switched to using Eduard's neater BTF partitioning approach which
is fully in resolve_btfids instead of libbpf (Eduard, patch 1)
- Supports mmap()ed vmlinux.inline (Alexei, patch 3, test patch 7)
- Moved to using .BTF.inline.link to store inline BTF size
which avoids need to switch to using kernfs; also allows us
to SHA-verify BTF inline info
[1] https://lore.kernel.org/bpf/20260925224229.1850-1-wanjay@amazon.com/
[2] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/
[3] https://lore.kernel.org/bpf/20261003194323.817885-1-alan.maguire@oracle.com/
[4] https://lore.kernel.org/bpf/20260901165757.801449-1-alan.maguire@oracle.com/
====================
Link: https://patch.msgid.link/20261009112324.1442319-1-alan.maguire@oracle.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 31 | ||||
| -rw-r--r-- | include/linux/btf.h | 42 | ||||
| -rw-r--r-- | include/linux/module.h | 4 |
3 files changed, 75 insertions, 2 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index b2988aa12f66..b17251bc63f5 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -675,12 +675,43 @@ /* * .BTF */ +#ifdef CONFIG_DEBUG_INFO_BTF_INLINE +#define BTF_INLINE \ + . = ALIGN(PAGE_SIZE); \ + .BTF.inline : AT(ADDR(.BTF.inline) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.BTF.inline, _BTF_inline) \ + } +#else +#define BTF_INLINE +#endif + +#ifdef CONFIG_DEBUG_INFO_BTF_INLINE_MODULE +/* __MODULE_NAME_LEN + SHA-256 digest + u32 BTF size */ +#ifdef CONFIG_64BIT +#define BTF_LINK_SIZE (64 - 8 + 32 + 4) +#else +#define BTF_LINK_SIZE (64 - 4 + 32 + 4) +#endif +#define BTF_INLINE_LINK \ + . = ALIGN(PAGE_SIZE); \ + .BTF.inline.link : AT(ADDR(.BTF.inline.link) - LOAD_OFFSET) { \ + __start_BTF_inline_link = .; \ + BYTE(0) \ + . += BTF_LINK_SIZE - 1; \ + __stop_BTF_inline_link = .; \ + } +#else +#define BTF_INLINE_LINK +#endif + #ifdef CONFIG_DEBUG_INFO_BTF #define BTF \ . = ALIGN(PAGE_SIZE); \ .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) { \ BOUNDED_SECTION_BY(.BTF, _BTF) \ } \ + BTF_INLINE \ + BTF_INLINE_LINK \ . = ALIGN(PAGE_SIZE); \ .BTF_ids : AT(ADDR(.BTF_ids) - LOAD_OFFSET) { \ *(.BTF_ids) \ diff --git a/include/linux/btf.h b/include/linux/btf.h index 4b63bb91550a..b66e20a18c54 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -5,6 +5,7 @@ #define _LINUX_BTF_H 1 #include <linux/types.h> +#include <linux/module.h> #include <linux/bpfptr.h> #include <linux/bsearch.h> #include <linux/btf_ids.h> @@ -118,6 +119,19 @@ struct btf_show; struct btf_id_set; struct bpf_prog; +#define BTF_LINK_SHA256_LEN 32 + +/* + * A .BTF.link or .BTF.inline.link section identifies the module which + * carries a vmlinux BTF section. The module name is NUL terminated and the + * field is padded to __MODULE_NAME_LEN. + */ +struct btf_link { + char module_name[__MODULE_NAME_LEN]; + u8 sha256[BTF_LINK_SHA256_LEN]; + u32 btf_size; +} __packed; + typedef int (*btf_kfunc_filter_t)(const struct bpf_prog *prog, u32 kfunc_id); struct btf_kfunc_id_set { @@ -594,7 +608,8 @@ struct btf_field_iter { #ifdef CONFIG_BPF_SYSCALL const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id); void btf_set_base_btf(struct btf *btf, const struct btf *base_btf); -int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **map_ids); +int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **map_ids, + __u32 **map_strs); int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t, enum btf_field_iter_kind iter_kind); __u32 *btf_field_iter_next(struct btf_field_iter *it); @@ -624,6 +639,29 @@ bool btf_types_are_same(const struct btf *btf1, u32 id1, const struct btf *btf2, u32 id2); int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx); +#if IS_ENABLED(CONFIG_SYSFS) +struct bin_attribute *sysfs_btf_add(const char *name, void *data, size_t data_size, + bool mmap, const char *lazy_module_name); +bool sysfs_btf_update(struct bin_attribute *attr, void *data); +void sysfs_btf_remove(struct bin_attribute *attr); +#else +static inline struct bin_attribute * +sysfs_btf_add(const char *name, void *data, size_t data_size, bool mmap, + const char *lazy_module_name) +{ + return NULL; +} + +static inline bool sysfs_btf_update(struct bin_attribute *attr, void *data) +{ + return false; +} + +static inline void sysfs_btf_remove(struct bin_attribute *attr) +{ +} +#endif + static inline bool btf_type_is_struct_ptr(struct btf *btf, const struct btf_type *t) { if (!btf_type_is_ptr(t)) @@ -645,7 +683,7 @@ static inline void btf_set_base_btf(struct btf *btf, const struct btf *base_btf) } static inline int btf_relocate(void *log, struct btf *btf, const struct btf *base_btf, - __u32 **map_ids) + __u32 **map_ids, __u32 **map_strs) { return -EOPNOTSUPP; } diff --git a/include/linux/module.h b/include/linux/module.h index 96cc98568eea..a6abde12a458 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -503,6 +503,10 @@ struct module { void *btf_data; void *btf_base_data; #endif +#if IS_ENABLED(CONFIG_DEBUG_INFO_BTF_INLINE) + unsigned int btf_inline_data_size; + void *btf_inline_data; +#endif #ifdef CONFIG_JUMP_LABEL struct jump_entry *jump_entries; unsigned int num_jump_entries; |
