link-vmlinux.sh 9.9 KB
Newer Older
1
#!/bin/sh
2
# SPDX-License-Identifier: GPL-2.0
3
4
5
#
# link vmlinux
#
6
7
8
9
10
# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_OBJS) and
# $(KBUILD_VMLINUX_LIBS). Most are built-in.a files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
# $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally
# (not within --whole-archive), and do not require symbol indexes added.
11
12
13
14
#
# vmlinux
#   ^
#   |
15
16
#   +--< $(KBUILD_VMLINUX_OBJS)
#   |    +--< init/built-in.a drivers/built-in.a mm/built-in.a + more
17
#   |
18
19
20
#   +--< $(KBUILD_VMLINUX_LIBS)
#   |    +--< lib/lib.a + more
#   |
21
22
23
24
25
26
27
28
29
30
31
32
#   +-< ${kallsymso} (see description in KALLSYMS section)
#
# vmlinux version (uname -v) cannot be updated during normal
# descending-into-subdirs phase since we do not yet know if we need to
# update vmlinux.
# Therefore this step is delayed until just before final link of vmlinux.
#
# System.map is generated to document addresses of all kernel symbols

# Error out on error
set -e

33
34
35
36
LD="$1"
KBUILD_LDFLAGS="$2"
LDFLAGS_vmlinux="$3"

37
38
39
40
41
# Nice output in kbuild format
# Will be supressed by "make -s"
info()
{
	if [ "${quiet}" != "silent_" ]; then
42
		printf "  %-7s %s\n" "${1}" "${2}"
43
44
45
	fi
}

46
47
48
49
50
51
52
53
54
55
56
57
58
59
# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
# .tmp_symversions.lds
gen_symversions()
{
	info GEN .tmp_symversions.lds
	rm -f .tmp_symversions.lds

	for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
		if [ -f ${o}.symversions ]; then
			cat ${o}.symversions >> .tmp_symversions.lds
		fi
	done
}

60
61
62
63
# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
{
64
	local objects
65
	local lds=""
66

67
	objects="--whole-archive				\
68
		${KBUILD_VMLINUX_OBJS}				\
69
70
71
72
73
		--no-whole-archive				\
		--start-group					\
		${KBUILD_VMLINUX_LIBS}				\
		--end-group"

74
	if [ -n "${CONFIG_LTO_CLANG}" ]; then
75
76
77
78
79
		if [ -n "${CONFIG_MODVERSIONS}" ]; then
			gen_symversions
			lds="${lds} -T .tmp_symversions.lds"
		fi

80
81
82
83
84
85
86
		# This might take a while, so indicate that we're doing
		# an LTO link
		info LTO ${1}
	else
		info LD ${1}
	fi

87
	${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
88
89
}

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
objtool_link()
{
	local objtoolopt;

	if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
		objtoolopt="check"
		if [ -z "${CONFIG_FRAME_POINTER}" ]; then
			objtoolopt="${objtoolopt} --no-fp"
		fi
		if [ -n "${CONFIG_GCOV_KERNEL}" ]; then
			objtoolopt="${objtoolopt} --no-unreachable"
		fi
		if [ -n "${CONFIG_RETPOLINE}" ]; then
			objtoolopt="${objtoolopt} --retpoline"
		fi
		if [ -n "${CONFIG_X86_SMAP}" ]; then
			objtoolopt="${objtoolopt} --uaccess"
		fi
		info OBJTOOL ${1}
		tools/objtool/objtool ${objtoolopt} ${1}
	fi
}

113
# Link of vmlinux
114
# ${1} - output file
115
# ${2}, ${3}, ... - optional extra .o files
116
117
118
vmlinux_link()
{
	local lds="${objtree}/${KBUILD_LDS}"
119
	local output=${1}
120
	local objects
121
	local strip_debug
122

123
124
	info LD ${output}

125
126
127
	# skip output file argument
	shift

128
129
130
131
132
	# The kallsyms linking does not need debug symbols included.
	if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
		strip_debug=-Wl,--strip-debug
	fi

133
	if [ "${SRCARCH}" != "um" ]; then
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
		if [ -n "${CONFIG_LTO_CLANG}" ]; then
			# Use vmlinux.o instead of performing the slow LTO
			# link again.
			objects="--whole-archive		\
				vmlinux.o 			\
				--no-whole-archive		\
				${@}"
		else
			objects="--whole-archive		\
				${KBUILD_VMLINUX_OBJS}		\
				--no-whole-archive		\
				--start-group			\
				${KBUILD_VMLINUX_LIBS}		\
				--end-group			\
				${@}"
		fi
150

151
		${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux}	\
152
			${strip_debug#-Wl,}			\
153
			-o ${output}				\
154
			-T ${lds} ${objects}
155
	else
156
		objects="-Wl,--whole-archive			\
157
			${KBUILD_VMLINUX_OBJS}			\
158
159
160
161
			-Wl,--no-whole-archive			\
			-Wl,--start-group			\
			${KBUILD_VMLINUX_LIBS}			\
			-Wl,--end-group				\
162
			${@}"
163

164
		${CC} ${CFLAGS_vmlinux}				\
165
			${strip_debug}				\
166
			-o ${output}				\
167
168
			-Wl,-T,${lds}				\
			${objects}				\
169
			-lutil -lrt -lpthread
170
171
172
173
		rm -f linux
	fi
}

174
# generate .BTF typeinfo from DWARF debuginfo
175
176
# ${1} - vmlinux image
# ${2} - file to dump raw BTF data into
177
178
gen_btf()
{
179
	local pahole_ver
180

181
	if ! [ -x "$(command -v ${PAHOLE})" ]; then
182
		echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
183
		return 1
184
185
	fi

186
	pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
187
188
	if [ "${pahole_ver}" -lt "116" ]; then
		echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.16"
189
		return 1
190
191
	fi

192
	vmlinux_link ${1}
193
194

	info "BTF" ${2}
195
	LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
196

197
198
199
200
201
202
203
204
205
206
	# Create ${2} which contains just .BTF section but no symbols. Add
	# SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
	# deletes all symbols including __start_BTF and __stop_BTF, which will
	# be redefined in the linker script. Add 2>/dev/null to suppress GNU
	# objcopy warnings: "empty loadable segment detected at ..."
	${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
		--strip-all ${1} ${2} 2>/dev/null
	# Change e_type to ET_REL so that it can be used to link final vmlinux.
	# Unlike GNU ld, lld does not allow an ET_EXEC input.
	printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none
207
}
208

209
# Create ${2} .S file with all symbols from the ${1} object file
210
211
212
213
214
kallsyms()
{
	local kallsymopt;

	if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
215
		kallsymopt="${kallsymopt} --all-symbols"
216
217
	fi

218
	if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
219
220
221
		kallsymopt="${kallsymopt} --absolute-percpu"
	fi

222
223
224
225
	if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
		kallsymopt="${kallsymopt} --base-relative"
	fi

226
227
	info KSYMS ${2}
	${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2}
228
229
}

230
231
232
233
234
# Perform one step in kallsyms generation, including temporary linking of
# vmlinux.
kallsyms_step()
{
	kallsymso_prev=${kallsymso}
235
236
	kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1}
	kallsymso=${kallsyms_vmlinux}.o
237
	kallsyms_S=${kallsyms_vmlinux}.S
238

239
	vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
240
241
242
243
244
245
	kallsyms ${kallsyms_vmlinux} ${kallsyms_S}

	info AS ${kallsyms_S}
	${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
	      ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
	      -c -o ${kallsymso} ${kallsyms_S}
246
247
}

248
249
250
251
252
253
254
# Create map file with all symbols from ${1}
# See mksymap for additional details
mksysmap()
{
	${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
}

255
sorttable()
256
{
257
	${objtree}/scripts/sorttable ${1}
258
259
}

260
261
262
# Delete output files in case of error
cleanup()
{
263
	rm -f .btf.*
264
	rm -f .tmp_System.map
265
	rm -f .tmp_symversions.lds
266
267
268
269
270
271
	rm -f .tmp_vmlinux*
	rm -f System.map
	rm -f vmlinux
	rm -f vmlinux.o
}

272
273
274
275
276
277
278
279
280
281
282
283
284
285
on_exit()
{
	if [ $? -ne 0 ]; then
		cleanup
	fi
}
trap on_exit EXIT

on_signals()
{
	exit 1
}
trap on_signals HUP INT QUIT TERM

286
287
288
289
290
291
292
293
294
295
296
297
298
# Use "make V=1" to debug this script
case "${KBUILD_VERBOSE}" in
*1*)
	set -x
	;;
esac

if [ "$1" = "clean" ]; then
	cleanup
	exit 0
fi

# We need access to CONFIG_ symbols
299
. include/config/auto.conf
300
301
302

# Update version
info GEN .version
303
304
305
if [ -r .version ]; then
	VERSION=$(expr 0$(cat .version) + 1)
	echo $VERSION > .version
306
else
307
308
	rm -f .version
	echo 1 > .version
309
310
311
fi;

# final build of init/
312
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
313

314
315
#link vmlinux.o
modpost_link vmlinux.o
316
objtool_link vmlinux.o
317
318

# modpost vmlinux.o to check for section mismatches
319
${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
320

321
322
info MODINFO modules.builtin.modinfo
${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
323
324
325
326
info GEN modules.builtin
# The second line aids cases where multiple modules share the same object.
tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' |
	tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin
327

328
btf_vmlinux_bin_o=""
329
if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
330
331
	btf_vmlinux_bin_o=.btf.vmlinux.bin.o
	if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then
332
333
334
		echo >&2 "Failed to generate BTF for vmlinux"
		echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
		exit 1
335
336
337
	fi
fi

338
kallsymso=""
339
kallsymso_prev=""
340
341
342
343
344
345
346
347
348
349
350
351
352
353
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then

	# kallsyms support
	# Generate section listing all symbols and add it into vmlinux
	# It's a three step process:
	# 1)  Link .tmp_vmlinux1 so it has all symbols and sections,
	#     but __kallsyms is empty.
	#     Running kallsyms on that gives us .tmp_kallsyms1.o with
	#     the right size
	# 2)  Link .tmp_vmlinux2 so it now has a __kallsyms section of
	#     the right size, but due to the added section, some
	#     addresses have shifted.
	#     From here, we generate a correct .tmp_kallsyms2.o
354
355
356
357
358
359
360
361
	# 3)  That link may have expanded the kernel image enough that
	#     more linker branch stubs / trampolines had to be added, which
	#     introduces new names, which further expands kallsyms. Do another
	#     pass if that is the case. In theory it's possible this results
	#     in even more stubs, but unlikely.
	#     KALLSYMS_EXTRA_PASS=1 may also used to debug or work around
	#     other bugs.
	# 4)  The correct ${kallsymso} is linked into the final vmlinux.
362
363
364
365
	#
	# a)  Verify that the System.map from vmlinux matches the map from
	#     ${kallsymso}.

366
367
	kallsyms_step 1
	kallsyms_step 2
368

369
	# step 3
370
371
	size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
	size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
372
373

	if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
374
		kallsyms_step 3
375
376
377
	fi
fi

378
vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
379

380
# fill in BTF IDs
381
382
383
if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then
	info BTFIDS vmlinux
	${RESOLVE_BTFIDS} vmlinux
384
385
fi

386
387
if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
	info SORTTAB vmlinux
388
389
390
391
	if ! sorttable vmlinux; then
		echo >&2 Failed to sort kernel tables
		exit 1
	fi
392
393
fi

394
395
396
397
398
399
400
401
info SYSMAP System.map
mksysmap vmlinux System.map

# step a (see comment above)
if [ -n "${CONFIG_KALLSYMS}" ]; then
	mksysmap ${kallsyms_vmlinux} .tmp_System.map

	if ! cmp -s System.map .tmp_System.map; then
Michal Marek's avatar
Michal Marek committed
402
		echo >&2 Inconsistent kallsyms data
403
		echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
404
405
406
		exit 1
	fi
fi