| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #!/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
- ;;
- esac
- done
- if [ $# -ne 1 ]; then
- usage
- fi
- 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}" in
- vmlinux)
- gen_btf_o
- ;;
- module)
- embed_btf_data
- ;;
- esac
- exit 0
|