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# Link of vmlinux.o used for section mismatch analysis 43# ${1} output file 44modpost_link() 45{ 46 local objects 47 48 objects="--whole-archive \ 49 ${KBUILD_VMLINUX_OBJS} \ 50 --no-whole-archive \ 51 --start-group \ 52 ${KBUILD_VMLINUX_LIBS} \ 53 --end-group" 54 55 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects} 56} 57 58# Link of vmlinux 59# ${1} - optional extra .o files 60# ${2} - output file 61vmlinux_link() 62{ 63 local lds="${objtree}/${KBUILD_LDS}" 64 local objects 65 66 if [ "${SRCARCH}" != "um" ]; then 67 objects="--whole-archive \ 68 ${KBUILD_VMLINUX_OBJS} \ 69 --no-whole-archive \ 70 --start-group \ 71 ${KBUILD_VMLINUX_LIBS} \ 72 --end-group \ 73 ${1}" 74 75 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ 76 -T ${lds} ${objects} 77 else 78 objects="-Wl,--whole-archive \ 79 ${KBUILD_VMLINUX_OBJS} \ 80 -Wl,--no-whole-archive \ 81 -Wl,--start-group \ 82 ${KBUILD_VMLINUX_LIBS} \ 83 -Wl,--end-group \ 84 ${1}" 85 86 ${CC} ${CFLAGS_vmlinux} -o ${2} \ 87 -Wl,-T,${lds} \ 88 ${objects} \ 89 -lutil -lrt -lpthread 90 rm -f linux 91 fi 92} 93 94# generate .BTF typeinfo from DWARF debuginfo 95gen_btf() 96{ 97 local pahole_ver; 98 99 pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') 100 if [ "${pahole_ver}" -lt "113" ]; then 101 info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" 102 exit 0 103 fi 104 105 info "BTF" ${1} 106 LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} 107} 108 109# Create ${2} .o file with all symbols from the ${1} object file 110kallsyms() 111{ 112 info KSYM ${2} 113 local kallsymopt; 114 115 if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then 116 kallsymopt="${kallsymopt} --all-symbols" 117 fi 118 119 if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then 120 kallsymopt="${kallsymopt} --absolute-percpu" 121 fi 122 123 if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then 124 kallsymopt="${kallsymopt} --base-relative" 125 fi 126 127 local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ 128 ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" 129 130 local afile="`basename ${2} .o`.S" 131 132 ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile} 133 ${CC} ${aflags} -c -o ${2} ${afile} 134} 135 136# Create map file with all symbols from ${1} 137# See mksymap for additional details 138mksysmap() 139{ 140 ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} 141} 142 143sortextable() 144{ 145 ${objtree}/scripts/sortextable ${1} 146} 147 148# Delete output files in case of error 149cleanup() 150{ 151 rm -f .tmp_System.map 152 rm -f .tmp_kallsyms* 153 rm -f .tmp_vmlinux* 154 rm -f System.map 155 rm -f vmlinux 156 rm -f vmlinux.o 157} 158 159on_exit() 160{ 161 if [ $? -ne 0 ]; then 162 cleanup 163 fi 164} 165trap on_exit EXIT 166 167on_signals() 168{ 169 exit 1 170} 171trap on_signals HUP INT QUIT TERM 172 173# 174# 175# Use "make V=1" to debug this script 176case "${KBUILD_VERBOSE}" in 177*1*) 178 set -x 179 ;; 180esac 181 182if [ "$1" = "clean" ]; then 183 cleanup 184 exit 0 185fi 186 187# We need access to CONFIG_ symbols 188. include/config/auto.conf 189 190# Update version 191info GEN .version 192if [ -r .version ]; then 193 VERSION=$(expr 0$(cat .version) + 1) 194 echo $VERSION > .version 195else 196 rm -f .version 197 echo 1 > .version 198fi; 199 200# final build of init/ 201${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init 202 203#link vmlinux.o 204info LD vmlinux.o 205modpost_link vmlinux.o 206 207# modpost vmlinux.o to check for section mismatches 208${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o 209 210kallsymso="" 211kallsyms_vmlinux="" 212if [ -n "${CONFIG_KALLSYMS}" ]; then 213 214 # kallsyms support 215 # Generate section listing all symbols and add it into vmlinux 216 # It's a three step process: 217 # 1) Link .tmp_vmlinux1 so it has all symbols and sections, 218 # but __kallsyms is empty. 219 # Running kallsyms on that gives us .tmp_kallsyms1.o with 220 # the right size 221 # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of 222 # the right size, but due to the added section, some 223 # addresses have shifted. 224 # From here, we generate a correct .tmp_kallsyms2.o 225 # 3) That link may have expanded the kernel image enough that 226 # more linker branch stubs / trampolines had to be added, which 227 # introduces new names, which further expands kallsyms. Do another 228 # pass if that is the case. In theory it's possible this results 229 # in even more stubs, but unlikely. 230 # KALLSYMS_EXTRA_PASS=1 may also used to debug or work around 231 # other bugs. 232 # 4) The correct ${kallsymso} is linked into the final vmlinux. 233 # 234 # a) Verify that the System.map from vmlinux matches the map from 235 # ${kallsymso}. 236 237 kallsymso=.tmp_kallsyms2.o 238 kallsyms_vmlinux=.tmp_vmlinux2 239 240 # step 1 241 vmlinux_link "" .tmp_vmlinux1 242 kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o 243 244 # step 2 245 vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 246 kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o 247 248 # step 3 249 size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o) 250 size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o) 251 252 if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then 253 kallsymso=.tmp_kallsyms3.o 254 kallsyms_vmlinux=.tmp_vmlinux3 255 256 vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 257 258 kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o 259 fi 260fi 261 262info LD vmlinux 263vmlinux_link "${kallsymso}" vmlinux 264 265if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then 266 gen_btf vmlinux 267fi 268 269if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then 270 info SORTEX vmlinux 271 sortextable vmlinux 272fi 273 274info SYSMAP System.map 275mksysmap vmlinux System.map 276 277# step a (see comment above) 278if [ -n "${CONFIG_KALLSYMS}" ]; then 279 mksysmap ${kallsyms_vmlinux} .tmp_System.map 280 281 if ! cmp -s System.map .tmp_System.map; then 282 echo >&2 Inconsistent kallsyms data 283 echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround 284 exit 1 285 fi 286fi 287