• 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_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