lkml.org 
[lkml]   [2020]   [Nov]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v7 03/17] kbuild: lto: fix module versioning
    From
    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>
    ---
    .gitignore | 1 +
    Makefile | 3 ++-
    arch/Kconfig | 1 -
    scripts/Makefile.build | 33 +++++++++++++++++++++++++++++++--
    scripts/Makefile.modpost | 6 +++++-
    scripts/link-vmlinux.sh | 23 ++++++++++++++++++++++-
    6 files changed, 61 insertions(+), 6 deletions(-)

    diff --git a/.gitignore b/.gitignore
    index d01cda8e1177..44e34991875e 100644
    --- a/.gitignore
    +++ b/.gitignore
    @@ -41,6 +41,7 @@
    *.so.dbg
    *.su
    *.symtypes
    +*.symversions
    *.tab.[ch]
    *.tar
    *.xz
    diff --git a/Makefile b/Makefile
    index 240560e88d69..f27c0da5d05a 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -1831,7 +1831,8 @@ clean: $(clean-dirs)
    -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
    # ---------------------------------------------------------------------------
    diff --git a/arch/Kconfig b/arch/Kconfig
    index a41fcb3ca7c6..736ae228e506 100644
    --- a/arch/Kconfig
    +++ b/arch/Kconfig
    @@ -655,7 +655,6 @@ config LTO_CLANG
    depends on !FTRACE_MCOUNT_USE_RECORDMCOUNT
    depends on !KASAN
    depends on !GCOV_KERNEL
    - depends on !MODVERSIONS
    select LTO
    help
    This option enables Clang's Link Time Optimization (LTO), which
    diff --git a/scripts/Makefile.build b/scripts/Makefile.build
    index ed74b2f986f7..eae2f5386a03 100644
    --- a/scripts/Makefile.build
    +++ b/scripts/Makefile.build
    @@ -166,6 +166,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)) \
    + > $@.symversions; \
    + fi;
    +else
    cmd_modversions_c = \
    if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
    $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
    @@ -177,6 +186,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
    @@ -390,6 +400,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
    $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
    $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;

    +# 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 $@.symversions \
    + $(foreach n, $(filter-out FORCE,$^), \
    + $(if $(wildcard $(n).symversions), \
    + ; cat $(n).symversions >> $@.symversions))
    +else
    + cmd_update_lto_symversions = echo >/dev/null
    +endif
    +
    #
    # Rule to compile a set of .o files into one .a file (without symbol table)
    #
    @@ -397,8 +419,11 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
    quiet_cmd_ar_builtin = AR $@
    cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)

    +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)

    #
    # Rule to create modules.order file
    @@ -418,8 +443,11 @@ $(obj)/modules.order: $(obj-m) 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)

    # NOTE:
    # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
    @@ -428,6 +456,7 @@ $(obj)/lib.a: $(lib-y) FORCE
    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
    diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
    index 9ff8bfdb574d..066beffca09a 100644
    --- a/scripts/Makefile.modpost
    +++ b/scripts/Makefile.modpost
    @@ -111,7 +111,11 @@ ifdef CONFIG_LTO_CLANG
    prelink-ext := .lto

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

    %.lto.o: %.o
    $(call if_changed,cc_lto_link_modules)
    diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
    index 596507573a48..78e55fe7210b 100755
    --- a/scripts/link-vmlinux.sh
    +++ b/scripts/link-vmlinux.sh
    @@ -43,11 +43,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} \
    @@ -57,6 +72,11 @@ 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}
    @@ -64,7 +84,7 @@ modpost_link()
    info LD ${1}
    fi

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

    objtool_link()
    @@ -242,6 +262,7 @@ cleanup()
    {
    rm -f .btf.*
    rm -f .tmp_System.map
    + rm -f .tmp_symversions.lds
    rm -f .tmp_vmlinux*
    rm -f System.map
    rm -f vmlinux
    --
    2.29.2.299.gdc1121823c-goog
    \
     
     \ /
      Last update: 2020-11-18 23:10    [W:5.430 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site