Skip to content

Commit 38e8918

Browse files
samitolvanenkees
authored andcommitted
kbuild: lto: fix module versioning
With CONFIG_MODVERSIONS, version information is linked into each compilation unit that exports symbols. With LTO, we cannot use this method as all C code is compiled into LLVM bitcode instead. This change collects symbol versions into .symversions files and merges them in link-vmlinux.sh where they are all linked into vmlinux.o at the same time. Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20201211184633.3213045-4-samitolvanen@google.com
1 parent dc5723b commit 38e8918

File tree

6 files changed

+61
-6
lines changed

6 files changed

+61
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
*.so.dbg
4242
*.su
4343
*.symtypes
44+
*.symversions
4445
*.tab.[ch]
4546
*.tar
4647
*.xz

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1837,7 +1837,8 @@ clean: $(clean-dirs)
18371837
-o -name '.tmp_*.o.*' \
18381838
-o -name '*.c.[012]*.*' \
18391839
-o -name '*.ll' \
1840-
-o -name '*.gcno' \) -type f -print | xargs rm -f
1840+
-o -name '*.gcno' \
1841+
-o -name '*.*.symversions' \) -type f -print | xargs rm -f
18411842

18421843
# Generate tags for editors
18431844
# ---------------------------------------------------------------------------

arch/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,6 @@ config HAS_LTO_CLANG
668668
depends on !FTRACE_MCOUNT_USE_RECORDMCOUNT
669669
depends on !KASAN
670670
depends on !GCOV_KERNEL
671-
depends on !MODVERSIONS
672671
help
673672
The compiler and Kconfig options support building with Clang's
674673
LTO.

scripts/Makefile.build

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,15 @@ ifdef CONFIG_MODVERSIONS
166166
# the actual value of the checksum generated by genksyms
167167
# o remove .tmp_<file>.o to <file>.o
168168

169+
ifdef CONFIG_LTO_CLANG
170+
# Generate .o.symversions files for each .o with exported symbols, and link these
171+
# to the kernel and/or modules at the end.
172+
cmd_modversions_c = \
173+
if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
174+
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
175+
> $@.symversions; \
176+
fi;
177+
else
169178
cmd_modversions_c = \
170179
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
171180
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
@@ -177,6 +186,7 @@ cmd_modversions_c = \
177186
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
178187
fi
179188
endif
189+
endif
180190

181191
ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
182192
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
@@ -386,15 +396,30 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
386396
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
387397
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
388398

399+
# combine symversions for later processing
400+
quiet_cmd_update_lto_symversions = SYMVER $@
401+
ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
402+
cmd_update_lto_symversions = \
403+
rm -f $@.symversions \
404+
$(foreach n, $(filter-out FORCE,$^), \
405+
$(if $(wildcard $(n).symversions), \
406+
; cat $(n).symversions >> $@.symversions))
407+
else
408+
cmd_update_lto_symversions = echo >/dev/null
409+
endif
410+
389411
#
390412
# Rule to compile a set of .o files into one .a file (without symbol table)
391413
#
392414

393415
quiet_cmd_ar_builtin = AR $@
394416
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
395417

418+
quiet_cmd_ar_and_symver = AR $@
419+
cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)
420+
396421
$(obj)/built-in.a: $(real-obj-y) FORCE
397-
$(call if_changed,ar_builtin)
422+
$(call if_changed,ar_and_symver)
398423

399424
#
400425
# Rule to create modules.order file
@@ -414,8 +439,11 @@ $(obj)/modules.order: $(obj-m) FORCE
414439
#
415440
# Rule to compile a set of .o files into one .a file (with symbol table)
416441
#
442+
quiet_cmd_ar_lib = AR $@
443+
cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)
444+
417445
$(obj)/lib.a: $(lib-y) FORCE
418-
$(call if_changed,ar)
446+
$(call if_changed,ar_lib)
419447

420448
# NOTE:
421449
# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
@@ -424,6 +452,7 @@ $(obj)/lib.a: $(lib-y) FORCE
424452
ifdef CONFIG_LTO_CLANG
425453
quiet_cmd_link_multi-m = AR [M] $@
426454
cmd_link_multi-m = \
455+
$(cmd_update_lto_symversions); \
427456
rm -f $@; \
428457
$(AR) cDPrsT $@ $(filter %.o,$^)
429458
else

scripts/Makefile.modpost

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ ifdef CONFIG_LTO_CLANG
111111
prelink-ext := .lto
112112

113113
quiet_cmd_cc_lto_link_modules = LTO [M] $@
114-
cmd_cc_lto_link_modules = $(LD) $(ld_flags) -r -o $@ --whole-archive $^
114+
cmd_cc_lto_link_modules = \
115+
$(LD) $(ld_flags) -r -o $@ \
116+
$(shell [ -s $(@:.lto.o=.o.symversions) ] && \
117+
echo -T $(@:.lto.o=.o.symversions)) \
118+
--whole-archive $^
115119

116120
%.lto.o: %.o
117121
$(call if_changed,cc_lto_link_modules)

scripts/link-vmlinux.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,26 @@ info()
4343
fi
4444
}
4545

46+
# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
47+
# .tmp_symversions.lds
48+
gen_symversions()
49+
{
50+
info GEN .tmp_symversions.lds
51+
rm -f .tmp_symversions.lds
52+
53+
for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
54+
if [ -f ${o}.symversions ]; then
55+
cat ${o}.symversions >> .tmp_symversions.lds
56+
fi
57+
done
58+
}
59+
4660
# Link of vmlinux.o used for section mismatch analysis
4761
# ${1} output file
4862
modpost_link()
4963
{
5064
local objects
65+
local lds=""
5166

5267
objects="--whole-archive \
5368
${KBUILD_VMLINUX_OBJS} \
@@ -57,14 +72,19 @@ modpost_link()
5772
--end-group"
5873

5974
if [ -n "${CONFIG_LTO_CLANG}" ]; then
75+
if [ -n "${CONFIG_MODVERSIONS}" ]; then
76+
gen_symversions
77+
lds="${lds} -T .tmp_symversions.lds"
78+
fi
79+
6080
# This might take a while, so indicate that we're doing
6181
# an LTO link
6282
info LTO ${1}
6383
else
6484
info LD ${1}
6585
fi
6686

67-
${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
87+
${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
6888
}
6989

7090
objtool_link()
@@ -242,6 +262,7 @@ cleanup()
242262
{
243263
rm -f .btf.*
244264
rm -f .tmp_System.map
265+
rm -f .tmp_symversions.lds
245266
rm -f .tmp_vmlinux*
246267
rm -f System.map
247268
rm -f vmlinux

0 commit comments

Comments
 (0)