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 33LD="$1" 34KBUILD_LDFLAGS="$2" 35LDFLAGS_vmlinux="$3" 36 37# Nice output in kbuild format 38# Will be supressed by "make -s" 39info() 40{ 41 if [ "${quiet}" != "silent_" ]; then 42 printf " %-7s %s\n" "${1}" "${2}" 43 fi 44} 45 46# Link of vmlinux.o used for section mismatch analysis 47# ${1} output file 48modpost_link() 49{ 50 local objects 51 52 objects="--whole-archive \ 53 ${KBUILD_VMLINUX_OBJS} \ 54 --no-whole-archive \ 55 --start-group \ 56 ${KBUILD_VMLINUX_LIBS} \ 57 --end-group" 58 59 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects} 60} 61 62objtool_link() 63{ 64 local objtoolopt; 65 66 if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then 67 objtoolopt="check" 68 if [ -z "${CONFIG_FRAME_POINTER}" ]; then 69 objtoolopt="${objtoolopt} --no-fp" 70 fi 71 if [ -n "${CONFIG_GCOV_KERNEL}" ]; then 72 objtoolopt="${objtoolopt} --no-unreachable" 73 fi 74 if [ -n "${CONFIG_RETPOLINE}" ]; then 75 objtoolopt="${objtoolopt} --retpoline" 76 fi 77 if [ -n "${CONFIG_X86_SMAP}" ]; then 78 objtoolopt="${objtoolopt} --uaccess" 79 fi 80 info OBJTOOL ${1} 81 tools/objtool/objtool ${objtoolopt} ${1} 82 fi 83} 84 85# Link of vmlinux 86# ${1} - output file 87# ${2}, ${3}, ... - optional extra .o files 88vmlinux_link() 89{ 90 local lds="${objtree}/${KBUILD_LDS}" 91 local output=${1} 92 local objects 93 local strip_debug 94 95 info LD ${output} 96 97 # skip output file argument 98 shift 99 100 # The kallsyms linking does not need debug symbols included. 101 if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then 102 strip_debug=-Wl,--strip-debug 103 fi 104 105 if [ "${SRCARCH}" != "um" ]; then 106 objects="--whole-archive \ 107 ${KBUILD_VMLINUX_OBJS} \ 108 --no-whole-archive \ 109 --start-group \ 110 ${KBUILD_VMLINUX_LIBS} \ 111 --end-group \ 112 ${@}" 113 114 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \ 115 ${strip_debug#-Wl,} \ 116 -o ${output} \ 117 -T ${lds} ${objects} 118 else 119 objects="-Wl,--whole-archive \ 120 ${KBUILD_VMLINUX_OBJS} \ 121 -Wl,--no-whole-archive \ 122 -Wl,--start-group \ 123 ${KBUILD_VMLINUX_LIBS} \ 124 -Wl,--end-group \ 125 ${@}" 126 127 ${CC} ${CFLAGS_vmlinux} \ 128 ${strip_debug} \ 129 -o ${output} \ 130 -Wl,-T,${lds} \ 131 ${objects} \ 132 -lutil -lrt -lpthread 133 rm -f linux 134 fi 135} 136 137# generate .BTF typeinfo from DWARF debuginfo 138# ${1} - vmlinux image 139# ${2} - file to dump raw BTF data into 140gen_btf() 141{ 142 local pahole_ver 143 144 if ! [ -x "$(command -v ${PAHOLE})" ]; then 145 echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available" 146 return 1 147 fi 148 149 pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') 150 if [ "${pahole_ver}" -lt "116" ]; then 151 echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.16" 152 return 1 153 fi 154 155 vmlinux_link ${1} 156 157 info "BTF" ${2} 158 LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} 159 160 # Create ${2} which contains just .BTF section but no symbols. Add 161 # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all 162 # deletes all symbols including __start_BTF and __stop_BTF, which will 163 # be redefined in the linker script. Add 2>/dev/null to suppress GNU 164 # objcopy warnings: "empty loadable segment detected at ..." 165 ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \ 166 --strip-all ${1} ${2} 2>/dev/null 167 # Change e_type to ET_REL so that it can be used to link final vmlinux. 168 # Unlike GNU ld, lld does not allow an ET_EXEC input. 169 printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none 170} 171 172# Create ${2} .o file with all symbols from the ${1} object file 173kallsyms() 174{ 175 info KSYM ${2} 176 local kallsymopt; 177 178 if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then 179 kallsymopt="${kallsymopt} --all-symbols" 180 fi 181 182 if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then 183 kallsymopt="${kallsymopt} --absolute-percpu" 184 fi 185 186 if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then 187 kallsymopt="${kallsymopt} --base-relative" 188 fi 189 190 local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ 191 ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" 192 193 local afile="`basename ${2} .o`.S" 194 195 ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile} 196 ${CC} ${aflags} -c -o ${2} ${afile} 197} 198 199# Perform one step in kallsyms generation, including temporary linking of 200# vmlinux. 201kallsyms_step() 202{ 203 kallsymso_prev=${kallsymso} 204 kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1} 205 kallsymso=${kallsyms_vmlinux}.o 206 207 vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} 208 kallsyms ${kallsyms_vmlinux} ${kallsymso} 209} 210 211# Create map file with all symbols from ${1} 212# See mksymap for additional details 213mksysmap() 214{ 215 ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} 216} 217 218sorttable() 219{ 220 ${objtree}/scripts/sorttable ${1} 221} 222 223# Delete output files in case of error 224cleanup() 225{ 226 rm -f .btf.* 227 rm -f .tmp_System.map 228 rm -f .tmp_vmlinux* 229 rm -f System.map 230 rm -f vmlinux 231 rm -f vmlinux.o 232} 233 234on_exit() 235{ 236 if [ $? -ne 0 ]; then 237 cleanup 238 fi 239} 240trap on_exit EXIT 241 242on_signals() 243{ 244 exit 1 245} 246trap on_signals HUP INT QUIT TERM 247 248# Use "make V=1" to debug this script 249case "${KBUILD_VERBOSE}" in 250*1*) 251 set -x 252 ;; 253esac 254 255if [ "$1" = "clean" ]; then 256 cleanup 257 exit 0 258fi 259 260# We need access to CONFIG_ symbols 261. include/config/auto.conf 262 263# Update version 264info GEN .version 265if [ -r .version ]; then 266 VERSION=$(expr 0$(cat .version) + 1) 267 echo $VERSION > .version 268else 269 rm -f .version 270 echo 1 > .version 271fi; 272 273# final build of init/ 274${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 275 276#link vmlinux.o 277info LD vmlinux.o 278modpost_link vmlinux.o 279objtool_link vmlinux.o 280 281# modpost vmlinux.o to check for section mismatches 282${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 283 284info MODINFO modules.builtin.modinfo 285${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo 286info GEN modules.builtin 287# The second line aids cases where multiple modules share the same object. 288tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | 289 tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin 290 291btf_vmlinux_bin_o="" 292if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then 293 btf_vmlinux_bin_o=.btf.vmlinux.bin.o 294 if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then 295 echo >&2 "Failed to generate BTF for vmlinux" 296 echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" 297 exit 1 298 fi 299fi 300 301kallsymso="" 302kallsymso_prev="" 303kallsyms_vmlinux="" 304if [ -n "${CONFIG_KALLSYMS}" ]; then 305 306 # kallsyms support 307 # Generate section listing all symbols and add it into vmlinux 308 # It's a three step process: 309 # 1) Link .tmp_vmlinux1 so it has all symbols and sections, 310 # but __kallsyms is empty. 311 # Running kallsyms on that gives us .tmp_kallsyms1.o with 312 # the right size 313 # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of 314 # the right size, but due to the added section, some 315 # addresses have shifted. 316 # From here, we generate a correct .tmp_kallsyms2.o 317 # 3) That link may have expanded the kernel image enough that 318 # more linker branch stubs / trampolines had to be added, which 319 # introduces new names, which further expands kallsyms. Do another 320 # pass if that is the case. In theory it's possible this results 321 # in even more stubs, but unlikely. 322 # KALLSYMS_EXTRA_PASS=1 may also used to debug or work around 323 # other bugs. 324 # 4) The correct ${kallsymso} is linked into the final vmlinux. 325 # 326 # a) Verify that the System.map from vmlinux matches the map from 327 # ${kallsymso}. 328 329 kallsyms_step 1 330 kallsyms_step 2 331 332 # step 3 333 size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev}) 334 size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) 335 336 if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then 337 kallsyms_step 3 338 fi 339fi 340 341vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} 342 343# fill in BTF IDs 344if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then 345info BTFIDS vmlinux 346${RESOLVE_BTFIDS} vmlinux 347fi 348 349if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then 350 info SORTTAB vmlinux 351 if ! sorttable vmlinux; then 352 echo >&2 Failed to sort kernel tables 353 exit 1 354 fi 355fi 356 357info SYSMAP System.map 358mksysmap vmlinux System.map 359 360# step a (see comment above) 361if [ -n "${CONFIG_KALLSYMS}" ]; then 362 mksysmap ${kallsyms_vmlinux} .tmp_System.map 363 364 if ! cmp -s System.map .tmp_System.map; then 365 echo >&2 Inconsistent kallsyms data 366 echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround 367 exit 1 368 fi 369fi 370