• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	local strip_debug
114
115	info LD ${output}
116
117	# skip output file argument
118	shift
119
120	# The kallsyms linking does not need debug symbols included.
121	if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
122		strip_debug=-Wl,--strip-debug
123	fi
124
125	if [ "${SRCARCH}" != "um" ]; then
126		if [ -n "${CONFIG_LTO_CLANG}" ]; then
127			# Use vmlinux.o instead of performing the slow LTO
128			# link again.
129			objects="--whole-archive		\
130				vmlinux.o 			\
131				--no-whole-archive		\
132				${@}"
133		else
134			objects="--whole-archive		\
135				${KBUILD_VMLINUX_OBJS}		\
136				--no-whole-archive		\
137				--start-group			\
138				${KBUILD_VMLINUX_LIBS}		\
139				--end-group			\
140				${@}"
141		fi
142
143		${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux}	\
144			${strip_debug#-Wl,}			\
145			-o ${output}				\
146			-T ${lds} ${objects}
147	else
148		objects="-Wl,--whole-archive			\
149			${KBUILD_VMLINUX_OBJS}			\
150			-Wl,--no-whole-archive			\
151			-Wl,--start-group			\
152			${KBUILD_VMLINUX_LIBS}			\
153			-Wl,--end-group				\
154			${@}"
155
156		${CC} ${CFLAGS_vmlinux}				\
157			${strip_debug}				\
158			-o ${output}				\
159			-Wl,-T,${lds}				\
160			${objects}				\
161			-lutil -lrt -lpthread
162		rm -f linux
163	fi
164}
165
166# generate .BTF typeinfo from DWARF debuginfo
167# ${1} - vmlinux image
168# ${2} - file to dump raw BTF data into
169gen_btf()
170{
171	local pahole_ver
172
173	if ! [ -x "$(command -v ${PAHOLE})" ]; then
174		echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
175		return 1
176	fi
177
178	pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
179	if [ "${pahole_ver}" -lt "113" ]; then
180		echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
181		return 1
182	fi
183
184	vmlinux_link ${1}
185
186	info "BTF" ${2}
187	LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
188
189	# Create ${2} which contains just .BTF section but no symbols. Add
190	# SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
191	# deletes all symbols including __start_BTF and __stop_BTF, which will
192	# be redefined in the linker script. Add 2>/dev/null to suppress GNU
193	# objcopy warnings: "empty loadable segment detected at ..."
194	${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
195		--strip-all ${1} ${2} 2>/dev/null
196	# Change e_type to ET_REL so that it can be used to link final vmlinux.
197	# GNU ld 2.35+ and lld do not allow an ET_EXEC input.
198	if [ -n "${CONFIG_CPU_BIG_ENDIAN}" ]; then
199		et_rel='\0\1'
200	else
201		et_rel='\1\0'
202	fi
203	printf "${et_rel}" | dd of=${2} conv=notrunc bs=1 seek=16 status=none
204}
205
206# Create ${2} .o file with all symbols from the ${1} object file
207kallsyms()
208{
209	info KSYM ${2}
210	local kallsymopt;
211
212	if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
213		kallsymopt="${kallsymopt} --all-symbols"
214	fi
215
216	if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
217		kallsymopt="${kallsymopt} --absolute-percpu"
218	fi
219
220	if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
221		kallsymopt="${kallsymopt} --base-relative"
222	fi
223
224	local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
225		      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
226
227	local afile="`basename ${2} .o`.S"
228
229	${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile}
230	${CC} ${aflags} -c -o ${2} ${afile}
231}
232
233# Perform one step in kallsyms generation, including temporary linking of
234# vmlinux.
235kallsyms_step()
236{
237	kallsymso_prev=${kallsymso}
238	kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1}
239	kallsymso=${kallsyms_vmlinux}.o
240
241	vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
242	kallsyms ${kallsyms_vmlinux} ${kallsymso}
243}
244
245# Create map file with all symbols from ${1}
246# See mksymap for additional details
247mksysmap()
248{
249	${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
250}
251
252sortextable()
253{
254	${objtree}/scripts/sortextable ${1}
255}
256
257# Delete output files in case of error
258cleanup()
259{
260	rm -f .btf.*
261	rm -f .tmp_System.map
262	rm -f .tmp_lto.lds
263	rm -f .tmp_vmlinux*
264	rm -f System.map
265	rm -f vmlinux
266	rm -f vmlinux.o
267}
268
269on_exit()
270{
271	if [ $? -ne 0 ]; then
272		cleanup
273	fi
274}
275trap on_exit EXIT
276
277on_signals()
278{
279	exit 1
280}
281trap on_signals HUP INT QUIT TERM
282
283#
284#
285# Use "make V=1" to debug this script
286case "${KBUILD_VERBOSE}" in
287*1*)
288	set -x
289	;;
290esac
291
292if [ "$1" = "clean" ]; then
293	cleanup
294	exit 0
295fi
296
297# We need access to CONFIG_ symbols
298. include/config/auto.conf
299
300# Update version
301info GEN .version
302if [ -r .version ]; then
303	VERSION=$(expr 0$(cat .version) + 1)
304	echo $VERSION > .version
305else
306	rm -f .version
307	echo 1 > .version
308fi;
309
310# final build of init/
311${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
312
313#link vmlinux.o
314modpost_link vmlinux.o
315
316# modpost vmlinux.o to check for section mismatches
317${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
318
319if [ -n "${CONFIG_LTO_CLANG}" ]; then
320	# Call recordmcount if needed
321	recordmcount vmlinux.o
322fi
323
324info MODINFO modules.builtin.modinfo
325${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
326
327btf_vmlinux_bin_o=""
328if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
329	btf_vmlinux_bin_o=.btf.vmlinux.bin.o
330	if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then
331		echo >&2 "Failed to generate BTF for vmlinux"
332		echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
333		exit 1
334	fi
335fi
336
337kallsymso=""
338kallsymso_prev=""
339kallsyms_vmlinux=""
340if [ -n "${CONFIG_KALLSYMS}" ]; then
341
342	# kallsyms support
343	# Generate section listing all symbols and add it into vmlinux
344	# It's a three step process:
345	# 1)  Link .tmp_vmlinux1 so it has all symbols and sections,
346	#     but __kallsyms is empty.
347	#     Running kallsyms on that gives us .tmp_kallsyms1.o with
348	#     the right size
349	# 2)  Link .tmp_vmlinux2 so it now has a __kallsyms section of
350	#     the right size, but due to the added section, some
351	#     addresses have shifted.
352	#     From here, we generate a correct .tmp_kallsyms2.o
353	# 3)  That link may have expanded the kernel image enough that
354	#     more linker branch stubs / trampolines had to be added, which
355	#     introduces new names, which further expands kallsyms. Do another
356	#     pass if that is the case. In theory it's possible this results
357	#     in even more stubs, but unlikely.
358	#     KALLSYMS_EXTRA_PASS=1 may also used to debug or work around
359	#     other bugs.
360	# 4)  The correct ${kallsymso} is linked into the final vmlinux.
361	#
362	# a)  Verify that the System.map from vmlinux matches the map from
363	#     ${kallsymso}.
364
365	kallsyms_step 1
366	kallsyms_step 2
367
368	# step 3
369	size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
370	size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
371
372	if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
373		kallsyms_step 3
374	fi
375fi
376
377vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
378
379if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
380	info SORTEX vmlinux
381	sortextable vmlinux
382fi
383
384info SYSMAP System.map
385mksysmap vmlinux System.map
386
387# step a (see comment above)
388if [ -n "${CONFIG_KALLSYMS}" ]; then
389	mksysmap ${kallsyms_vmlinux} .tmp_System.map
390
391	if ! cmp -s System.map .tmp_System.map; then
392		echo >&2 Inconsistent kallsyms data
393		echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
394		exit 1
395	fi
396fi
397