1#!/bin/bash 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 63info() 64{ 65 printf " %-7s %s\n" "${1}" "${2}" 66} 67 68case "${KBUILD_VERBOSE}" in 69*1*) 70 set -x 71 ;; 72esac 73 74 75gen_btf_data() 76{ 77 info BTF "${ELF_FILE}" 78 btf1="${ELF_FILE}.BTF.1" 79 ${PAHOLE} -J ${PAHOLE_FLAGS} \ 80 ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 81 --btf_encode_detached=${btf1} \ 82 "${ELF_FILE}" 83 84 info BTFIDS "${ELF_FILE}" 85 ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_FLAGS} \ 86 ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 87 --btf ${btf1} "${ELF_FILE}" 88} 89 90gen_btf_o() 91{ 92 local btf_data=${ELF_FILE}.btf.o 93 94 # Create ${btf_data} which contains just .BTF section but no symbols. Add 95 # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all 96 # deletes all symbols including __start_BTF and __stop_BTF, which will 97 # be redefined in the linker script. 98 info OBJCOPY "${btf_data}" 99 echo "" | ${CC} ${CLANG_FLAGS} ${KBUILD_CFLAGS} -c -x c -o ${btf_data} - 100 ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF \ 101 --set-section-flags .BTF=alloc,readonly ${btf_data} 102 ${OBJCOPY} --only-section=.BTF --strip-all ${btf_data} 103 104 # Change e_type to ET_REL so that it can be used to link final vmlinux. 105 # GNU ld 2.35+ and lld do not allow an ET_EXEC input. 106 if is_enabled CONFIG_CPU_BIG_ENDIAN; then 107 et_rel='\0\1' 108 else 109 et_rel='\1\0' 110 fi 111 printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none 112} 113 114embed_btf_data() 115{ 116 info OBJCOPY "${ELF_FILE}.BTF" 117 ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF ${ELF_FILE} 118 119 # a module might not have a .BTF_ids or .BTF.base section 120 local btf_base="${ELF_FILE}.BTF.base" 121 if [ -f "${btf_base}" ]; then 122 ${OBJCOPY} --add-section .BTF.base=${btf_base} ${ELF_FILE} 123 fi 124 local btf_ids="${ELF_FILE}.BTF_ids" 125 if [ -f "${btf_ids}" ]; then 126 ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE} 127 fi 128} 129 130cleanup() 131{ 132 rm -f "${ELF_FILE}.BTF.1" 133 rm -f "${ELF_FILE}.BTF" 134 if [ "${BTFGEN_MODE}" = "module" ]; then 135 rm -f "${ELF_FILE}.BTF.base" 136 rm -f "${ELF_FILE}.BTF_ids" 137 fi 138} 139trap cleanup EXIT 140 141BTFGEN_MODE="vmlinux" 142if [ -n "${BTF_BASE}" ]; then 143 BTFGEN_MODE="module" 144fi 145 146gen_btf_data 147 148case "${BTFGEN_MODE}" in 149vmlinux) 150 gen_btf_o 151 ;; 152module) 153 embed_btf_data 154 ;; 155esac 156 157exit 0 158