1*26ad5d6eSIhor Solodrai#!/bin/sh 2522397d0SIhor Solodrai# SPDX-License-Identifier: GPL-2.0 3522397d0SIhor Solodrai# Copyright (c) 2025 Meta Platforms, Inc. and affiliates. 4522397d0SIhor Solodrai# 5522397d0SIhor Solodrai# This script generates BTF data for the provided ELF file. 6522397d0SIhor Solodrai# 7522397d0SIhor Solodrai# Kernel BTF generation involves these conceptual steps: 8522397d0SIhor Solodrai# 1. pahole generates BTF from DWARF data 9522397d0SIhor Solodrai# 2. resolve_btfids applies kernel-specific btf2btf 10522397d0SIhor Solodrai# transformations and computes data for .BTF_ids section 11522397d0SIhor Solodrai# 3. the result gets linked/objcopied into the target binary 12522397d0SIhor Solodrai# 13522397d0SIhor Solodrai# How step (3) should be done differs between vmlinux, and 14522397d0SIhor Solodrai# kernel modules, which is the primary reason for the existence 15522397d0SIhor Solodrai# of this script. 16522397d0SIhor Solodrai# 17522397d0SIhor Solodrai# For modules the script expects vmlinux passed in as --btf_base. 18522397d0SIhor Solodrai# Generated .BTF, .BTF.base and .BTF_ids sections become embedded 19522397d0SIhor Solodrai# into the input ELF file with objcopy. 20522397d0SIhor Solodrai# 21522397d0SIhor Solodrai# For vmlinux the input file remains unchanged and two files are produced: 22522397d0SIhor Solodrai# - ${1}.btf.o ready for linking into vmlinux 23522397d0SIhor Solodrai# - ${1}.BTF_ids with .BTF_ids data blob 24522397d0SIhor Solodrai# This output is consumed by scripts/link-vmlinux.sh 25522397d0SIhor Solodrai 26522397d0SIhor Solodraiset -e 27522397d0SIhor Solodrai 28522397d0SIhor Solodraiusage() 29522397d0SIhor Solodrai{ 30522397d0SIhor Solodrai echo "Usage: $0 [--btf_base <file>] <target ELF file>" 31522397d0SIhor Solodrai exit 1 32522397d0SIhor Solodrai} 33522397d0SIhor Solodrai 34522397d0SIhor SolodraiBTF_BASE="" 35522397d0SIhor Solodrai 36522397d0SIhor Solodraiwhile [ $# -gt 0 ]; do 37522397d0SIhor Solodrai case "$1" in 38522397d0SIhor Solodrai --btf_base) 39522397d0SIhor Solodrai BTF_BASE="$2" 40522397d0SIhor Solodrai shift 2 41522397d0SIhor Solodrai ;; 42522397d0SIhor Solodrai -*) 43522397d0SIhor Solodrai echo "Unknown option: $1" >&2 44522397d0SIhor Solodrai usage 45522397d0SIhor Solodrai ;; 46522397d0SIhor Solodrai *) 47522397d0SIhor Solodrai break 48522397d0SIhor Solodrai ;; 49522397d0SIhor Solodrai esac 50522397d0SIhor Solodraidone 51522397d0SIhor Solodrai 52522397d0SIhor Solodraiif [ $# -ne 1 ]; then 53522397d0SIhor Solodrai usage 54522397d0SIhor Solodraifi 55522397d0SIhor Solodrai 56522397d0SIhor SolodraiELF_FILE="$1" 57522397d0SIhor Solodraishift 58522397d0SIhor Solodrai 59522397d0SIhor Solodraiis_enabled() { 60522397d0SIhor Solodrai grep -q "^$1=y" ${objtree}/include/config/auto.conf 61522397d0SIhor Solodrai} 62522397d0SIhor Solodrai 63522397d0SIhor Solodraicase "${KBUILD_VERBOSE}" in 64522397d0SIhor Solodrai*1*) 65522397d0SIhor Solodrai set -x 66522397d0SIhor Solodrai ;; 67522397d0SIhor Solodraiesac 68522397d0SIhor Solodrai 69522397d0SIhor Solodraigen_btf_data() 70522397d0SIhor Solodrai{ 71522397d0SIhor Solodrai btf1="${ELF_FILE}.BTF.1" 72522397d0SIhor Solodrai ${PAHOLE} -J ${PAHOLE_FLAGS} \ 73522397d0SIhor Solodrai ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 74522397d0SIhor Solodrai --btf_encode_detached=${btf1} \ 75522397d0SIhor Solodrai "${ELF_FILE}" 76522397d0SIhor Solodrai 77522397d0SIhor Solodrai ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_FLAGS} \ 78522397d0SIhor Solodrai ${BTF_BASE:+--btf_base ${BTF_BASE}} \ 79522397d0SIhor Solodrai --btf ${btf1} "${ELF_FILE}" 80522397d0SIhor Solodrai} 81522397d0SIhor Solodrai 82522397d0SIhor Solodraigen_btf_o() 83522397d0SIhor Solodrai{ 84*26ad5d6eSIhor Solodrai btf_data=${ELF_FILE}.btf.o 85522397d0SIhor Solodrai 86522397d0SIhor Solodrai # Create ${btf_data} which contains just .BTF section but no symbols. Add 87522397d0SIhor Solodrai # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all 88522397d0SIhor Solodrai # deletes all symbols including __start_BTF and __stop_BTF, which will 89522397d0SIhor Solodrai # be redefined in the linker script. 9024216497SNathan Chancellor echo "" | ${CC} ${CLANG_FLAGS} ${KBUILD_CPPFLAGS} ${KBUILD_CFLAGS} -fno-lto -c -x c -o ${btf_data} - 91522397d0SIhor Solodrai ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF \ 92522397d0SIhor Solodrai --set-section-flags .BTF=alloc,readonly ${btf_data} 93522397d0SIhor Solodrai ${OBJCOPY} --only-section=.BTF --strip-all ${btf_data} 94522397d0SIhor Solodrai 95522397d0SIhor Solodrai # Change e_type to ET_REL so that it can be used to link final vmlinux. 96522397d0SIhor Solodrai # GNU ld 2.35+ and lld do not allow an ET_EXEC input. 97522397d0SIhor Solodrai if is_enabled CONFIG_CPU_BIG_ENDIAN; then 98522397d0SIhor Solodrai et_rel='\0\1' 99522397d0SIhor Solodrai else 100522397d0SIhor Solodrai et_rel='\1\0' 101522397d0SIhor Solodrai fi 102522397d0SIhor Solodrai printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none 103522397d0SIhor Solodrai} 104522397d0SIhor Solodrai 105522397d0SIhor Solodraiembed_btf_data() 106522397d0SIhor Solodrai{ 107522397d0SIhor Solodrai ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF ${ELF_FILE} 108522397d0SIhor Solodrai 109522397d0SIhor Solodrai # a module might not have a .BTF_ids or .BTF.base section 110*26ad5d6eSIhor Solodrai btf_base="${ELF_FILE}.BTF.base" 111522397d0SIhor Solodrai if [ -f "${btf_base}" ]; then 112522397d0SIhor Solodrai ${OBJCOPY} --add-section .BTF.base=${btf_base} ${ELF_FILE} 113522397d0SIhor Solodrai fi 114*26ad5d6eSIhor Solodrai btf_ids="${ELF_FILE}.BTF_ids" 115522397d0SIhor Solodrai if [ -f "${btf_ids}" ]; then 1161a8fa7faSIhor Solodrai ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE} 117522397d0SIhor Solodrai fi 118522397d0SIhor Solodrai} 119522397d0SIhor Solodrai 120522397d0SIhor Solodraicleanup() 121522397d0SIhor Solodrai{ 122522397d0SIhor Solodrai rm -f "${ELF_FILE}.BTF.1" 123522397d0SIhor Solodrai rm -f "${ELF_FILE}.BTF" 124522397d0SIhor Solodrai if [ "${BTFGEN_MODE}" = "module" ]; then 125522397d0SIhor Solodrai rm -f "${ELF_FILE}.BTF.base" 126522397d0SIhor Solodrai rm -f "${ELF_FILE}.BTF_ids" 127522397d0SIhor Solodrai fi 128522397d0SIhor Solodrai} 129522397d0SIhor Solodraitrap cleanup EXIT 130522397d0SIhor Solodrai 131522397d0SIhor SolodraiBTFGEN_MODE="vmlinux" 132522397d0SIhor Solodraiif [ -n "${BTF_BASE}" ]; then 133522397d0SIhor Solodrai BTFGEN_MODE="module" 134522397d0SIhor Solodraifi 135522397d0SIhor Solodrai 136522397d0SIhor Solodraigen_btf_data 137522397d0SIhor Solodrai 138522397d0SIhor Solodraicase "${BTFGEN_MODE}" in 139522397d0SIhor Solodraivmlinux) 140522397d0SIhor Solodrai gen_btf_o 141522397d0SIhor Solodrai ;; 142522397d0SIhor Solodraimodule) 143522397d0SIhor Solodrai embed_btf_data 144522397d0SIhor Solodrai ;; 145522397d0SIhor Solodraiesac 146522397d0SIhor Solodrai 147522397d0SIhor Solodraiexit 0 148