BACKPORT: 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>
Change-Id: Ife57356dd14b9ae0d2e3801eea7c602c6245952f
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Sorayukii <sorayukii69@gmail.com>
This commit is contained in:
Andrii Nakryiko 2019-08-12 11:39:47 -07:00 • committed by Sorayukii
commit 40df54cf02

View file

@ -127,8 +127,8 @@ recordmcount()
}
# Link of vmlinux
# ${1} - optional extra .o files
# ${2} - output file
# ${1} - output file
# ${@:2} - optional extra .o files
vmlinux_link()
{
local lds="${objtree}/${KBUILD_LDS}"
@ -144,28 +144,28 @@ vmlinux_link()
fi
if [[ -n "${CONFIG_THIN_ARCHIVES}" && -z "${CONFIG_LTO_CLANG}" ]]; then
objects="--whole-archive built-in.o ${1}"
objects="--whole-archive built-in.o ${@:2}"
else
objects="${KBUILD_VMLINUX_INIT} \
--start-group \
${KBUILD_VMLINUX_MAIN} \
--end-group \
${1}"
${@:2}"
fi
${ld} ${ldflags} -o ${2} -T ${lds} ${objects}
${ld} ${ldflags} -o ${1} -T ${lds} ${objects}
else
if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
objects="-Wl,--whole-archive built-in.o ${1}"
objects="-Wl,--whole-archive built-in.o ${@:2}"
else
objects="${KBUILD_VMLINUX_INIT} \
-Wl,--start-group \
${KBUILD_VMLINUX_MAIN} \
-Wl,--end-group \
${1}"
${@:2}"
fi
${CC} ${CFLAGS_vmlinux} -o ${2} \
${CC} ${CFLAGS_vmlinux} -o ${1} \
-Wl,-T,${lds} \
${objects} \
-lutil -lrt -lpthread
@ -174,23 +174,34 @@ vmlinux_link()
}
# generate .BTF typeinfo from DWARF debuginfo
# ${1} - vmlinux image
# ${2} - file to dump raw BTF data into
gen_btf()
{
local pahole_ver;
local bin_arch
if ! [ -x "$(command -v ${PAHOLE})" ]; then
info "BTF" "${1}: pahole (${PAHOLE}) is not available"
return 0
return 1
fi
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
if [ "${pahole_ver}" -lt "113" ]; then
info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
return 0
return 1
fi
info "BTF" ${1}
info "BTF" ${2}
vmlinux_link ${1}
LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
# dump .BTF section into raw binary file to link with final vmlinux
bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \
cut -d, -f1 | cut -d' ' -f2)
${OBJCOPY} --dump-section .BTF=.btf.kernel.bin ${1} 2>/dev/null
${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \
--rename-section .data=.BTF .btf.kernel.bin ${2}
}
# Create ${2} .o file with all symbols from the ${1} object file
@ -264,6 +275,7 @@ sortextable()
# Delete output files in case of error
cleanup()
{
rm -f .btf.*
rm -f .old_version
rm -f .tmp_System.map
rm -f .tmp_kallsyms*
@ -356,6 +368,13 @@ if [ ! -z ${RTIC_MPGEN+x} ]; then
KBUILD_VMLINUX_MAIN+=$RTIC_MP_O
fi
btf_kernel_bin_o=""
if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
if gen_btf .tmp_vmlinux.btf .btf.kernel.bin.o ; then
btf_kernel_bin_o=.btf.kernel.bin.o
fi
fi
kallsymso=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
@ -383,11 +402,11 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
kallsyms_vmlinux=.tmp_vmlinux2
# step 1
vmlinux_link "" .tmp_vmlinux1
kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
vmlinux_link .tmp_vmlinux1
kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o ${btf_kernel_bin_o}
# step 2
vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_kernel_bin_o}
kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
# step 2a
@ -395,7 +414,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
kallsymso=.tmp_kallsyms3.o
kallsyms_vmlinux=.tmp_vmlinux3
vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_kernel_bin_o}
kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
fi
@ -418,11 +437,7 @@ if [ ! -z ${RTIC_MP_O} ]; then
fi
info LD vmlinux
vmlinux_link "${kallsymso}" vmlinux
if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
gen_btf vmlinux
fi
vmlinux_link vmlinux "${kallsymso}" "${btf_kernel_bin_o}"
if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
info SORTEX vmlinux