xref: /linux/scripts/gen-btf.sh (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
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