147 lines · 3.3 KB · Shell
RawDownload
#!/bin/sh# SPDX-License-Identifier: GPL-2.0# Copyright (c) 2025 Meta Platforms, Inc. and affiliates.## This script generates BTF data for the provided ELF file.## Kernel BTF generation involves these conceptual steps:#   1. pahole generates BTF from DWARF data#   2. resolve_btfids applies kernel-specific btf2btf#      transformations and computes data for .BTF_ids section#   3. the result gets linked/objcopied into the target binary## How step (3) should be done differs between vmlinux, and# kernel modules, which is the primary reason for the existence# of this script.## For modules the script expects vmlinux passed in as --btf_base.# Generated .BTF, .BTF.base and .BTF_ids sections become embedded# into the input ELF file with objcopy.## For vmlinux the input file remains unchanged and two files are produced:#   - ${1}.btf.o ready for linking into vmlinux#   - ${1}.BTF_ids with .BTF_ids data blob# This output is consumed by scripts/link-vmlinux.sh set -e usage(){	echo "Usage: $0 [--btf_base <file>] <target ELF file>"	exit 1} BTF_BASE="" while [ $# -gt 0 ]; do	case "$1" in	--btf_base)		BTF_BASE="$2"		shift 2		;;	-*)		echo "Unknown option: $1" >&2		usage		;;	*)		break		;;	esacdone if [ $# -ne 1 ]; then	usagefi ELF_FILE="$1"shift is_enabled() {	grep -q "^$1=y" ${objtree}/include/config/auto.conf} case "${KBUILD_VERBOSE}" in*1*)	set -x	;;esac gen_btf_data(){	btf1="${ELF_FILE}.BTF.1"	${PAHOLE} -J ${PAHOLE_FLAGS}			\		${BTF_BASE:+--btf_base ${BTF_BASE}}	\		--btf_encode_detached=${btf1}		\		"${ELF_FILE}" 	${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_FLAGS}	\		${BTF_BASE:+--btf_base ${BTF_BASE}}	\		--btf ${btf1} "${ELF_FILE}"} gen_btf_o(){	btf_data=${ELF_FILE}.btf.o 	# Create ${btf_data} which contains just .BTF section but no symbols. Add	# SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all	# deletes all symbols including __start_BTF and __stop_BTF, which will	# be redefined in the linker script.	echo "" | ${CC} ${CLANG_FLAGS} ${KBUILD_CPPFLAGS} ${KBUILD_CFLAGS} -fno-lto -c -x c -o ${btf_data} -	${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF \		--set-section-flags .BTF=alloc,readonly ${btf_data}	${OBJCOPY} --only-section=.BTF --strip-all ${btf_data} 	# Change e_type to ET_REL so that it can be used to link final vmlinux.	# GNU ld 2.35+ and lld do not allow an ET_EXEC input.	if is_enabled CONFIG_CPU_BIG_ENDIAN; then		et_rel='\0\1'	else		et_rel='\1\0'	fi	printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none} embed_btf_data(){	${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF ${ELF_FILE} 	# a module might not have a .BTF_ids or .BTF.base section	btf_base="${ELF_FILE}.BTF.base"	if [ -f "${btf_base}" ]; then		${OBJCOPY} --add-section .BTF.base=${btf_base} ${ELF_FILE}	fi	btf_ids="${ELF_FILE}.BTF_ids"	if [ -f "${btf_ids}" ]; then		${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE}	fi} cleanup(){	rm -f "${ELF_FILE}.BTF.1"	rm -f "${ELF_FILE}.BTF"	if [ "${BTFGEN_MODE}" = "module" ]; then		rm -f "${ELF_FILE}.BTF.base"		rm -f "${ELF_FILE}.BTF_ids"	fi}trap cleanup EXIT BTFGEN_MODE="vmlinux"if [ -n "${BTF_BASE}" ]; then	BTFGEN_MODE="module"fi gen_btf_data case "${BTFGEN_MODE}" invmlinux)	gen_btf_o	;;module)	embed_btf_data	;;esac exit 0