1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0 3# 4# link vmlinux 5# 6# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_OBJS) and 7# $(KBUILD_VMLINUX_LIBS). Most are built-in.a files from top-level directories 8# in the kernel tree, others are specified in arch/$(ARCH)/Makefile. 9# $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally 10# (not within --whole-archive), and do not require symbol indexes added. 11# 12# vmlinux 13# ^ 14# | 15# +--< $(KBUILD_VMLINUX_OBJS) 16# | +--< init/built-in.a drivers/built-in.a mm/built-in.a + more 17# | 18# +--< $(KBUILD_VMLINUX_LIBS) 19# | +--< lib/lib.a + more 20# | 21# +-< ${kallsymso} (see description in KALLSYMS section) 22# 23# vmlinux version (uname -v) cannot be updated during normal 24# descending-into-subdirs phase since we do not yet know if we need to 25# update vmlinux. 26# Therefore this step is delayed until just before final link of vmlinux. 27# 28# System.map is generated to document addresses of all kernel symbols 29 30# Error out on error 31set -e 32 33# Nice output in kbuild format 34# Will be supressed by "make -s" 35info() 36{ 37 if [ "${quiet}" != "silent_" ]; then 38 printf " %-7s %s\n" "${1}" "${2}" 39 fi 40} 41 42# If CONFIG_LTO_CLANG is selected, generate a linker script to ensure correct 43# ordering of initcalls, and with CONFIG_MODVERSIONS also enabled, collect the 44# previously generated symbol versions into the same script. 45lto_lds() 46{ 47 if [ -z "${CONFIG_LTO_CLANG}" ]; then 48 return 49 fi 50 51 ${srctree}/scripts/generate_initcall_order.pl \ 52 ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \ 53 > .tmp_lto.lds 54 55 if [ -n "${CONFIG_MODVERSIONS}" ]; then 56 for a in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do 57 for o in $(${AR} t $a 2>/dev/null); do 58 if [ -f ${o}.symversions ]; then 59 cat ${o}.symversions >> .tmp_lto.lds 60 fi 61 done 62 done 63 fi 64 65 echo "-T .tmp_lto.lds" 66} 67 68# Link of vmlinux.o used for section mismatch analysis 69# ${1} output file 70modpost_link() 71{ 72 local objects 73 74 objects="--whole-archive \ 75 ${KBUILD_VMLINUX_OBJS} \ 76 --no-whole-archive \ 77 --start-group \ 78 ${KBUILD_VMLINUX_LIBS} \ 79 --end-group" 80 81 if [ -n "${CONFIG_LTO_CLANG}" ]; then 82 # This might take a while, so indicate that we're doing 83 # an LTO link 84 info LTO ${1} 85 else 86 info LD ${1} 87 fi 88 89 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} $(lto_lds) ${objects} 90} 91 92# If CONFIG_LTO_CLANG is selected, we postpone running recordmcount until 93# we have compiled LLVM IR to an object file. 94recordmcount() 95{ 96 if [ -z "${CONFIG_LTO_CLANG}" ]; then 97 return 98 fi 99 100 if [ -n "${CONFIG_FTRACE_MCOUNT_RECORD}" ]; then 101 scripts/recordmcount ${RECORDMCOUNT_FLAGS} $* 102 fi 103} 104 105# Link of vmlinux 106# ${1} - output file 107# ${2}, ${3}, ... - optional extra .o files 108vmlinux_link() 109{ 110 local lds="${objtree}/${KBUILD_LDS}" 111 local output=${1} 112 local objects 113 114 info LD ${output} 115 116 # skip output file argument 117 shift 118 119 if [ "${SRCARCH}" != "um" ]; then 120 if [ -n "${CONFIG_LTO_CLANG}" ]; then 121 # Use vmlinux.o instead of performing the slow LTO 122 # link again. 123 objects="--whole-archive \ 124 vmlinux.o \ 125 --no-whole-archive \ 126 ${@}" 127 else 128 objects="--whole-archive \ 129 ${KBUILD_VMLINUX_OBJS} \ 130 --no-whole-archive \ 131 --start-group \ 132 ${KBUILD_VMLINUX_LIBS} \ 133 --end-group \ 134 ${@}" 135 fi 136 137 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \ 138 -o ${output} \ 139 -T ${lds} ${objects} 140 else 141 objects="-Wl,--whole-archive \ 142 ${KBUILD_VMLINUX_OBJS} \ 143 -Wl,--no-whole-archive \ 144 -Wl,--start-group \ 145 ${KBUILD_VMLINUX_LIBS} \ 146 -Wl,--end-group \ 147 ${@}" 148 149 ${CC} ${CFLAGS_vmlinux} \ 150 -o ${output} \ 151 -Wl,-T,${lds} \ 152 ${objects} \ 153 -lutil -lrt -lpthread 154 rm -f linux 155 fi 156} 157 158# generate .BTF typeinfo from DWARF debuginfo 159# ${1} - vmlinux image 160# ${2} - file to dump raw BTF data into 161gen_btf() 162{ 163 local pahole_ver 164 local bin_arch 165 166 if ! [ -x "$(command -v ${PAHOLE})" ]; then 167 info "BTF" "${1}: pahole (${PAHOLE}) is not available" 168 return 1 169 fi 170 171 pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') 172 if [ "${pahole_ver}" -lt "113" ]; then 173 info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" 174 return 1 175 fi 176 177 info "BTF" ${2} 178 vmlinux_link ${1} 179 LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} 180 181 # dump .BTF section into raw binary file to link with final vmlinux 182 bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \ 183 cut -d, -f1 | cut -d' ' -f2) 184 bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \ 185 awk '{print $4}') 186 ${OBJCOPY} --change-section-address .BTF=0 \ 187 --set-section-flags .BTF=alloc -O binary \ 188 --only-section=.BTF ${1} .btf.vmlinux.bin 189 ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \ 190 --rename-section .data=.BTF .btf.vmlinux.bin ${2} 191} 192 193# Create ${2} .o file with all symbols from the ${1} object file 194kallsyms() 195{ 196 info KSYM ${2} 197 local kallsymopt; 198 199 if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then 200 kallsymopt="${kallsymopt} --all-symbols" 201 fi 202 203 if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then 204 kallsymopt="${kallsymopt} --absolute-percpu" 205 fi 206 207 if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then 208 kallsymopt="${kallsymopt} --base-relative" 209 fi 210 211 local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ 212 ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" 213 214 local afile="`basename ${2} .o`.S" 215 216 ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile} 217 ${CC} ${aflags} -c -o ${2} ${afile} 218} 219 220# Perform one step in kallsyms generation, including temporary linking of 221# vmlinux. 222kallsyms_step() 223{ 224 kallsymso_prev=${kallsymso} 225 kallsymso=.tmp_kallsyms${1}.o 226 kallsyms_vmlinux=.tmp_vmlinux${1} 227 228 vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} 229 kallsyms ${kallsyms_vmlinux} ${kallsymso} 230} 231 232# Create map file with all symbols from ${1} 233# See mksymap for additional details 234mksysmap() 235{ 236 ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} 237} 238 239sortextable() 240{ 241 ${objtree}/scripts/sortextable ${1} 242} 243 244# Delete output files in case of error 245cleanup() 246{ 247 rm -f .btf.* 248 rm -f .tmp_System.map 249 rm -f .tmp_kallsyms* 250 rm -f .tmp_lto.lds 251 rm -f .tmp_vmlinux* 252 rm -f System.map 253 rm -f vmlinux 254 rm -f vmlinux.o 255} 256 257on_exit() 258{ 259 if [ $? -ne 0 ]; then 260 cleanup 261 fi 262} 263trap on_exit EXIT 264 265on_signals() 266{ 267 exit 1 268} 269trap on_signals HUP INT QUIT TERM 270 271# 272# 273# Use "make V=1" to debug this script 274case "${KBUILD_VERBOSE}" in 275*1*) 276 set -x 277 ;; 278esac 279 280if [ "$1" = "clean" ]; then 281 cleanup 282 exit 0 283fi 284 285# We need access to CONFIG_ symbols 286. include/config/auto.conf 287 288# Update version 289info GEN .version 290if [ -r .version ]; then 291 VERSION=$(expr 0$(cat .version) + 1) 292 echo $VERSION > .version 293else 294 rm -f .version 295 echo 1 > .version 296fi; 297 298# final build of init/ 299${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init 300 301#link vmlinux.o 302modpost_link vmlinux.o 303 304# modpost vmlinux.o to check for section mismatches 305${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 306 307if [ -n "${CONFIG_LTO_CLANG}" ]; then 308 # Call recordmcount if needed 309 recordmcount vmlinux.o 310fi 311 312info MODINFO modules.builtin.modinfo 313${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo 314 315btf_vmlinux_bin_o="" 316if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then 317 if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then 318 btf_vmlinux_bin_o=.btf.vmlinux.bin.o 319 else 320 echo >&2 "Failed to generate BTF for vmlinux" 321 echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" 322 exit 1 323 fi 324fi 325 326kallsymso="" 327kallsymso_prev="" 328kallsyms_vmlinux="" 329if [ -n "${CONFIG_KALLSYMS}" ]; then 330 331 # kallsyms support 332 # Generate section listing all symbols and add it into vmlinux 333 # It's a three step process: 334 # 1) Link .tmp_vmlinux1 so it has all symbols and sections, 335 # but __kallsyms is empty. 336 # Running kallsyms on that gives us .tmp_kallsyms1.o with 337 # the right size 338 # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of 339 # the right size, but due to the added section, some 340 # addresses have shifted. 341 # From here, we generate a correct .tmp_kallsyms2.o 342 # 3) That link may have expanded the kernel image enough that 343 # more linker branch stubs / trampolines had to be added, which 344 # introduces new names, which further expands kallsyms. Do another 345 # pass if that is the case. In theory it's possible this results 346 # in even more stubs, but unlikely. 347 # KALLSYMS_EXTRA_PASS=1 may also used to debug or work around 348 # other bugs. 349 # 4) The correct ${kallsymso} is linked into the final vmlinux. 350 # 351 # a) Verify that the System.map from vmlinux matches the map from 352 # ${kallsymso}. 353 354 kallsyms_step 1 355 kallsyms_step 2 356 357 # step 3 358 size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev}) 359 size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) 360 361 if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then 362 kallsyms_step 3 363 fi 364fi 365 366vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} 367 368if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then 369 info SORTEX vmlinux 370 sortextable vmlinux 371fi 372 373info SYSMAP System.map 374mksysmap vmlinux System.map 375 376# step a (see comment above) 377if [ -n "${CONFIG_KALLSYMS}" ]; then 378 mksysmap ${kallsyms_vmlinux} .tmp_System.map 379 380 if ! cmp -s System.map .tmp_System.map; then 381 echo >&2 Inconsistent kallsyms data 382 echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround 383 exit 1 384 fi 385fi 386