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