Skip to content

Commit

Permalink
kbuild: lto: fix module versioning
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Divyanshu-Modi <[email protected]>
Signed-off-by: Tashfin Shakeer Rhythm <[email protected]>
  • Loading branch information
samitolvanen authored and Tashar02 committed Dec 7, 2022
1 parent 3000382 commit 267a212
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
*.so.dbg
*.su
*.symtypes
*.symversions
*.tab.[ch]
*.tar
*.xz
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1720,7 +1720,8 @@ clean: $(clean-dirs)
-o -name modules.builtin -o -name '.tmp_*.o.*' \
-o -name '*.c.[012]*.*' \
-o -name '*.ll' \
-o -name '*.gcno' \) -type f -print | xargs rm -f
-o -name '*.gcno' \
-o -name '*.*.symversions' \) -type f -print | xargs rm -f

# Generate tags for editors
# ---------------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,6 @@ config HAS_LTO_CLANG
depends on !FTRACE_MCOUNT_USE_RECORDMCOUNT
depends on !KASAN
depends on !GCOV_KERNEL
depends on !MODVERSIONS
help
The compiler and Kconfig options support building with Clang's
LTO.
Expand Down
34 changes: 31 additions & 3 deletions scripts/Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,15 @@ ifdef CONFIG_MODVERSIONS
# the actual value of the checksum generated by genksyms
# o remove .tmp_<file>.o to <file>.o


ifdef CONFIG_LTO_CLANG
# Generate .o.symversions files for each .o with exported symbols, and link these
# to the kernel and/or modules at the end.
cmd_modversions_c = \
if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> [email protected]; \
fi;
else
cmd_modversions_c = \
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
Expand All @@ -197,6 +205,7 @@ cmd_modversions_c = \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
fi;
endif
endif

ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
Expand Down Expand Up @@ -416,6 +425,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
# To build objects in subdirs, we need to descend into the directories
$(sort $(subdir-obj-y)): $(subdir-ym) ;

# combine symversions for later processing
quiet_cmd_update_lto_symversions = SYMVER $@
ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
cmd_update_lto_symversions = \
rm -f [email protected] \
$(foreach n, $(filter-out FORCE,$^), \
$(if $(wildcard $(n).symversions), \
; cat $(n).symversions >> [email protected]))
else
cmd_update_lto_symversions = echo >/dev/null
endif

#
# Rule to compile a set of .o files into one .a file (without symbol table)
#
Expand All @@ -424,8 +445,11 @@ quiet_cmd_ar_builtin = AR $@
cmd_ar_builtin = rm -f $@; \
$(AR) rcSTP$(KBUILD_ARFLAGS) $@ $(filter $(real-obj-y), $^)

quiet_cmd_ar_and_symver = AR $@
cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)

$(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin)
$(call if_changed,ar_and_symver)

targets += $(builtin-target)

Expand All @@ -445,14 +469,18 @@ $(modorder-target): $(subdir-ym) FORCE
#
# Rule to compile a set of .o files into one .a file (with symbol table)
#
quiet_cmd_ar_lib = AR $@
cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)

$(obj)/lib.a: $(lib-y) FORCE
$(call if_changed,ar)
$(call if_changed,ar_lib)

targets += $(lib-target)

ifdef CONFIG_LTO_CLANG
quiet_cmd_link_multi-m = AR [M] $@
cmd_link_multi-m = \
$(cmd_update_lto_symversions); \
rm -f $@; \
$(AR) cDPrsT $@ $(filter %.o,$^)
else
Expand Down
23 changes: 22 additions & 1 deletion scripts/link-vmlinux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,26 @@ info()
fi
}

# 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
}

# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
{
local objects
local lds=""

objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
Expand All @@ -53,14 +68,19 @@ modpost_link()
--end-group"

if [ -n "${CONFIG_LTO_CLANG}" ]; then
if [ -n "${CONFIG_MODVERSIONS}" ]; then
gen_symversions
lds="${lds} -T .tmp_symversions.lds"
fi

# This might take a while, so indicate that we're doing
# an LTO link
info LTO ${1}
else
info LD ${1}
fi

${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
}

# Link of vmlinux
Expand Down Expand Up @@ -176,6 +196,7 @@ sortextable()
cleanup()
{
rm -f .tmp_System.map
rm -f .tmp_symversions.lds
rm -f .tmp_kallsyms*
rm -f .tmp_vmlinux*
rm -f System.map
Expand Down

0 comments on commit 267a212

Please sign in to comment.