1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0 3# Copyright (c) 2025 Meta Platforms, Inc. and affiliates. 4# 5# This script generates BTF data for the provided ELF file. 6# 7# Kernel BTF generation involves these conceptual steps: 8# 1. pahole generates BTF from DWARF data 9# 2. resolve_btfids applies kernel-specific btf2btf 10# transformations and computes data for .BTF_ids section 11# 3. the result gets linked/objcopied into the target binary 12# 13# How step (3) should be done differs between vmlinux, and 14# kernel modules, which is the primary reason for the existence 15# of this script. 16# 17# For modules the script expects vmlinux passed in as --btf_base. 18# Generated .BTF, .BTF.base and .BTF_ids sections become embedded 19# into the input ELF file with objcopy. 20# 21# For vmlinux the input file remains unchanged and two files are produced: 22# - ${1}.btf.o ready for linking into vmlinux 23# - ${1}.BTF_ids with .BTF_ids data blob 24# This output is consumed by scripts/link-vmlinux.sh 25 26set -e 27 28usage() 29{ 30 echo "Usage: $0 [--btf_base <file>] <target ELF file>" 31 exit 1 32} 33 34BTF_BASE="" 35 36while [ $# -gt 0 ]; do 37 case "$1" in 38 --btf_base) 39 BTF_BASE="$2" 40 shift 2 41 ;; 42 -*) 43 echo "Unknown option: $1" >&2 44 usage 45 ;; 46 *) 47 break 48 ;; 49 esac 50done 51 52if [ $# -ne 1 ]; then 53 usage 54fi 55 56ELF_FILE="$1" 57shift 58 59is_enabled() { 60 grep -q "^$1=y" ${objtree}/include/config/auto.conf 61} 62 63case "${KBUILD_VERBOSE}" in 64*1*) 65 set -x 66 ;; 67esac 68 69gen_btf_data() 70{ 71 btf1="${ELF_FILE}.BTF.1" 72 ${PAHOLE} -J ${PAHOLE_FLAGS} \ 73 ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 74 --btf_encode_detached=${btf1} \ 75 "${ELF_FILE}" 76 77 ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_FLAGS} \ 78 ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 79 --btf ${btf1} "${ELF_FILE}" 80} 81 82gen_btf_o() 83{ 84 btf_data=${ELF_FILE}.btf.o 85 86 # Create ${btf_data} which contains just .BTF section but no symbols. Add 87 # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all 88 # deletes all symbols including __start_BTF and __stop_BTF, which will 89 # be redefined in the linker script. 90 echo "" | ${CC} ${CLANG_FLAGS} ${KBUILD_CPPFLAGS} ${KBUILD_CFLAGS} -fno-lto -c -x c -o ${btf_data} - 91 ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF \ 92 --set-section-flags .BTF=alloc,readonly ${btf_data} 93 ${OBJCOPY} --only-section=.BTF --strip-all ${btf_data} 94 95 # Change e_type to ET_REL so that it can be used to link final vmlinux. 96 # GNU ld 2.35+ and lld do not allow an ET_EXEC input. 97 if is_enabled CONFIG_CPU_BIG_ENDIAN; then 98 et_rel='\0\1' 99 else 100 et_rel='\1\0' 101 fi 102 printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none 103} 104 105embed_btf_data() 106{ 107 ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF ${ELF_FILE} 108 109 # a module might not have a .BTF_ids or .BTF.base section 110 btf_base="${ELF_FILE}.BTF.base" 111 if [ -f "${btf_base}" ]; then 112 ${OBJCOPY} --add-section .BTF.base=${btf_base} ${ELF_FILE} 113 fi 114 btf_ids="${ELF_FILE}.BTF_ids" 115 if [ -f "${btf_ids}" ]; then 116 ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE} 117 fi 118} 119 120cleanup() 121{ 122 rm -f "${ELF_FILE}.BTF.1" 123 rm -f "${ELF_FILE}.BTF" 124 if [ "${BTFGEN_MODE}" = "module" ]; then 125 rm -f "${ELF_FILE}.BTF.base" 126 rm -f "${ELF_FILE}.BTF_ids" 127 fi 128} 129trap cleanup EXIT 130 131BTFGEN_MODE="vmlinux" 132if [ -n "${BTF_BASE}" ]; then 133 BTFGEN_MODE="module" 134fi 135 136gen_btf_data 137 138case "${BTFGEN_MODE}" in 139vmlinux) 140 gen_btf_o 141 ;; 142module) 143 embed_btf_data 144 ;; 145esac 146 147exit 0 148