summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-10-11 14:18:07 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-10-11 14:18:07 +0000
commitac1dff2daebb04816766106740042e7ad92859dd (patch)
treeabdf06d1a35a148b690237a4390acf81d764c718 /include
parent4411c854408c05f083c828b69e72e3cc22384fbf (diff)
parent400f0881c912af87091973f231c1b573c2b24292 (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.h31
-rw-r--r--include/linux/btf.h42
-rw-r--r--include/linux/module.h4
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;