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