summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrii Nakryiko <andriin@fb.com>2019-08-12 14:39:47 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2019-08-13 10:14:15 -0400
commit341dfcf8d78eaa3a2dc96dea06f0392eb2978364 (patch)
tree5a4f45f7703c707a91712224603f64744cd1a99c
parenta664a834579ae8a6166ac9e5a3232976cab2c24d (diff)
btf: expose BTF info through sysfs
Make .BTF section allocated and expose its contents through sysfs. /sys/kernel/btf directory is created to contain all the BTFs present inside kernel. Currently there is only kernel's main BTF, represented as /sys/kernel/btf/kernel file. Once kernel modules' BTFs are supported, each module will expose its BTF as /sys/kernel/btf/<module-name> file. Current approach relies on a few pieces coming together: 1. pahole is used to take almost final vmlinux image (modulo .BTF and kallsyms) and generate .BTF section by converting DWARF info into BTF. This section is not allocated and not mapped to any segment, though, so is not yet accessible from inside kernel at runtime. 2. objcopy dumps .BTF contents into binary file and subsequently convert binary file into linkable object file with automatically generated symbols _binary__btf_kernel_bin_start and _binary__btf_kernel_bin_end, pointing to start and end, respectively, of BTF raw data. 3. final vmlinux image is generated by linking this object file (and kallsyms, if necessary). sysfs_btf.c then creates /sys/kernel/btf/kernel file and exposes embedded BTF contents through it. This allows, e.g., libbpf and bpftool access BTF info at well-known location, without resorting to searching for vmlinux image on disk (location of which is not standardized and vmlinux image might not be even available in some scenarios, e.g., inside qemu during testing). Alternative approach using .incbin assembler directive to embed BTF contents directly was attempted but didn't work, because sysfs_proc.o is not re-compiled during link-vmlinux.sh stage. This is required, though, to update embedded BTF data (initially empty data is embedded, then pahole generates BTF info and we need to regenerate sysfs_btf.o with updated contents, but it's too late at that point). If BTF couldn't be generated due to missing or too old pahole, sysfs_btf.c handles that gracefully by detecting that _binary__btf_kernel_bin_start (weak symbol) is 0 and not creating /sys/kernel/btf at all. v2->v3: - added Documentation/ABI/testing/sysfs-kernel-btf (Greg K-H); - created proper kobject (btf_kobj) for btf directory (Greg K-H); - undo v2 change of reusing vmlinux, as it causes extra kallsyms pass due to initially missing __binary__btf_kernel_bin_{start/end} symbols; v1->v2: - allow kallsyms stage to re-use vmlinux generated by gen_btf(); Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-btf17
-rw-r--r--kernel/bpf/Makefile3
-rw-r--r--kernel/bpf/sysfs_btf.c51
-rwxr-xr-xscripts/link-vmlinux.sh52
4 files changed, 104 insertions, 19 deletions
diff --git a/Documentation/ABI/testing/sysfs-kernel-btf b/Documentation/ABI/testing/sysfs-kernel-btf
new file mode 100644
index 000000000000..5390f8001f96
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-btf
@@ -0,0 +1,17 @@
1What: /sys/kernel/btf
2Date: Aug 2019
3KernelVersion: 5.5
4Contact: bpf@vger.kernel.org
5Description:
6 Contains BTF type information and related data for kernel and
7 kernel modules.
8
9What: /sys/kernel/btf/kernel
10Date: Aug 2019
11KernelVersion: 5.5
12Contact: bpf@vger.kernel.org
13Description:
14 Read-only binary attribute exposing kernel's own BTF type
15 information with description of all internal kernel types. See
16 Documentation/bpf/btf.rst for detailed description of format
17 itself.
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 29d781061cd5..e1d9adb212f9 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -22,3 +22,6 @@ obj-$(CONFIG_CGROUP_BPF) += cgroup.o
22ifeq ($(CONFIG_INET),y) 22ifeq ($(CONFIG_INET),y)
23obj-$(CONFIG_BPF_SYSCALL) += reuseport_array.o 23obj-$(CONFIG_BPF_SYSCALL) += reuseport_array.o
24endif 24endif
25ifeq ($(CONFIG_SYSFS),y)
26obj-$(CONFIG_DEBUG_INFO_BTF) += sysfs_btf.o
27endif
diff --git a/kernel/bpf/sysfs_btf.c b/kernel/bpf/sysfs_btf.c
new file mode 100644
index 000000000000..092e63b9758b
--- /dev/null
+++ b/kernel/bpf/sysfs_btf.c
@@ -0,0 +1,51 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Provide kernel BTF information for introspection and use by eBPF tools.
4 */
5#include <linux/kernel.h>
6#include <linux/module.h>
7#include <linux/kobject.h>
8#include <linux/init.h>
9#include <linux/sysfs.h>
10
11/* See scripts/link-vmlinux.sh, gen_btf() func for details */
12extern char __weak _binary__btf_kernel_bin_start[];
13extern char __weak _binary__btf_kernel_bin_end[];
14
15static ssize_t
16btf_kernel_read(struct file *file, struct kobject *kobj,
17 struct bin_attribute *bin_attr,
18 char *buf, loff_t off, size_t len)
19{
20 memcpy(buf, _binary__btf_kernel_bin_start + off, len);
21 return len;
22}
23
24static struct bin_attribute bin_attr_btf_kernel __ro_after_init = {
25 .attr = { .name = "kernel", .mode = 0444, },
26 .read = btf_kernel_read,
27};
28
29static struct kobject *btf_kobj;
30
31static int __init btf_kernel_init(void)
32{
33 int err;
34
35 if (!_binary__btf_kernel_bin_start)
36 return 0;
37
38 btf_kobj = kobject_create_and_add("btf", kernel_kobj);
39 if (IS_ERR(btf_kobj)) {
40 err = PTR_ERR(btf_kobj);
41 btf_kobj = NULL;
42 return err;
43 }
44
45 bin_attr_btf_kernel.size = _binary__btf_kernel_bin_end -
46 _binary__btf_kernel_bin_start;
47
48 return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_kernel);
49}
50
51subsys_initcall(btf_kernel_init);
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index a7124f895b24..cb93832c6ad7 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -56,8 +56,8 @@ modpost_link()
56} 56}
57 57
58# Link of vmlinux 58# Link of vmlinux
59# ${1} - optional extra .o files 59# ${1} - output file
60# ${2} - output file 60# ${@:2} - optional extra .o files
61vmlinux_link() 61vmlinux_link()
62{ 62{
63 local lds="${objtree}/${KBUILD_LDS}" 63 local lds="${objtree}/${KBUILD_LDS}"
@@ -70,9 +70,9 @@ vmlinux_link()
70 --start-group \ 70 --start-group \
71 ${KBUILD_VMLINUX_LIBS} \ 71 ${KBUILD_VMLINUX_LIBS} \
72 --end-group \ 72 --end-group \
73 ${1}" 73 ${@:2}"
74 74
75 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ 75 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${1} \
76 -T ${lds} ${objects} 76 -T ${lds} ${objects}
77 else 77 else
78 objects="-Wl,--whole-archive \ 78 objects="-Wl,--whole-archive \
@@ -81,9 +81,9 @@ vmlinux_link()
81 -Wl,--start-group \ 81 -Wl,--start-group \
82 ${KBUILD_VMLINUX_LIBS} \ 82 ${KBUILD_VMLINUX_LIBS} \
83 -Wl,--end-group \ 83 -Wl,--end-group \
84 ${1}" 84 ${@:2}"
85 85
86 ${CC} ${CFLAGS_vmlinux} -o ${2} \ 86 ${CC} ${CFLAGS_vmlinux} -o ${1} \
87 -Wl,-T,${lds} \ 87 -Wl,-T,${lds} \
88 ${objects} \ 88 ${objects} \
89 -lutil -lrt -lpthread 89 -lutil -lrt -lpthread
@@ -92,23 +92,34 @@ vmlinux_link()
92} 92}
93 93
94# generate .BTF typeinfo from DWARF debuginfo 94# generate .BTF typeinfo from DWARF debuginfo
95# ${1} - vmlinux image
96# ${2} - file to dump raw BTF data into
95gen_btf() 97gen_btf()
96{ 98{
97 local pahole_ver; 99 local pahole_ver
100 local bin_arch
98 101
99 if ! [ -x "$(command -v ${PAHOLE})" ]; then 102 if ! [ -x "$(command -v ${PAHOLE})" ]; then
100 info "BTF" "${1}: pahole (${PAHOLE}) is not available" 103 info "BTF" "${1}: pahole (${PAHOLE}) is not available"
101 return 0 104 return 1
102 fi 105 fi
103 106
104 pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') 107 pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
105 if [ "${pahole_ver}" -lt "113" ]; then 108 if [ "${pahole_ver}" -lt "113" ]; then
106 info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" 109 info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
107 return 0 110 return 1
108 fi 111 fi
109 112
110 info "BTF" ${1} 113 info "BTF" ${2}
114 vmlinux_link ${1}
111 LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} 115 LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
116
117 # dump .BTF section into raw binary file to link with final vmlinux
118 bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \
119 cut -d, -f1 | cut -d' ' -f2)
120 ${OBJCOPY} --dump-section .BTF=.btf.kernel.bin ${1} 2>/dev/null
121 ${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \
122 --rename-section .data=.BTF .btf.kernel.bin ${2}
112} 123}
113 124
114# Create ${2} .o file with all symbols from the ${1} object file 125# Create ${2} .o file with all symbols from the ${1} object file
@@ -153,6 +164,7 @@ sortextable()
153# Delete output files in case of error 164# Delete output files in case of error
154cleanup() 165cleanup()
155{ 166{
167 rm -f .btf.*
156 rm -f .tmp_System.map 168 rm -f .tmp_System.map
157 rm -f .tmp_kallsyms* 169 rm -f .tmp_kallsyms*
158 rm -f .tmp_vmlinux* 170 rm -f .tmp_vmlinux*
@@ -215,6 +227,13 @@ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
215info MODINFO modules.builtin.modinfo 227info MODINFO modules.builtin.modinfo
216${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo 228${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
217 229
230btf_kernel_bin_o=""
231if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
232 if gen_btf .tmp_vmlinux.btf .btf.kernel.bin.o ; then
233 btf_kernel_bin_o=.btf.kernel.bin.o
234 fi
235fi
236
218kallsymso="" 237kallsymso=""
219kallsyms_vmlinux="" 238kallsyms_vmlinux=""
220if [ -n "${CONFIG_KALLSYMS}" ]; then 239if [ -n "${CONFIG_KALLSYMS}" ]; then
@@ -246,11 +265,11 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
246 kallsyms_vmlinux=.tmp_vmlinux2 265 kallsyms_vmlinux=.tmp_vmlinux2
247 266
248 # step 1 267 # step 1
249 vmlinux_link "" .tmp_vmlinux1 268 vmlinux_link .tmp_vmlinux1 ${btf_kernel_bin_o}
250 kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o 269 kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
251 270
252 # step 2 271 # step 2
253 vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 272 vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_kernel_bin_o}
254 kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o 273 kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
255 274
256 # step 3 275 # step 3
@@ -261,18 +280,13 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
261 kallsymso=.tmp_kallsyms3.o 280 kallsymso=.tmp_kallsyms3.o
262 kallsyms_vmlinux=.tmp_vmlinux3 281 kallsyms_vmlinux=.tmp_vmlinux3
263 282
264 vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 283 vmlinux_link .tmp_vmlinux3 .tmp_kallsyms2.o ${btf_kernel_bin_o}
265
266 kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o 284 kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
267 fi 285 fi
268fi 286fi
269 287
270info LD vmlinux 288info LD vmlinux
271vmlinux_link "${kallsymso}" vmlinux 289vmlinux_link vmlinux "${kallsymso}" "${btf_kernel_bin_o}"
272
273if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
274 gen_btf vmlinux
275fi
276 290
277if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then 291if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
278 info SORTEX vmlinux 292 info SORTEX vmlinux