kbuild: lto: postpone objtool
authorSami Tolvanen <samitolvanen@google.com>
Mon, 13 Apr 2020 23:10:13 +0000 (16:10 -0700)
committerKees Cook <keescook@chromium.org>
Tue, 23 Feb 2021 20:46:57 +0000 (12:46 -0800)
With LTO, LLVM bitcode won't be compiled into native code until
modpost_link, or modfinal for modules. This change postpones calls
to objtool until after these steps, and moves objtool_args to
Makefile.lib, so the arguments can be reused in Makefile.modfinal.

As we didn't have objects to process earlier, we use --duplicate
when processing vmlinux.o. This change also disables unreachable
instruction warnings with LTO to avoid warnings about the int3
padding between functions.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modfinal
scripts/link-vmlinux.sh

index 59fabd9685eeca5057e034afd7691f85f3d854c6..3f6bf0ea7c0eb28e490610e7d06921eb81f0260a 100644 (file)
@@ -218,30 +218,11 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),
 endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
 
 ifdef CONFIG_STACK_VALIDATION
+ifndef CONFIG_LTO_CLANG
 ifneq ($(SKIP_STACK_VALIDATION),1)
 
 __objtool_obj := $(objtree)/tools/objtool/objtool
 
-objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
-
-objtool_args += $(if $(part-of-module), --module,)
-
-ifndef CONFIG_FRAME_POINTER
-objtool_args += --no-fp
-endif
-ifdef CONFIG_GCOV_KERNEL
-objtool_args += --no-unreachable
-endif
-ifdef CONFIG_RETPOLINE
-  objtool_args += --retpoline
-endif
-ifdef CONFIG_X86_SMAP
-  objtool_args += --uaccess
-endif
-ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
-  objtool_args += --mcount
-endif
-
 # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
 # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
 # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
@@ -253,6 +234,7 @@ objtool_obj = $(if $(patsubst y%,, \
        $(__objtool_obj))
 
 endif # SKIP_STACK_VALIDATION
+endif # CONFIG_LTO_CLANG
 endif # CONFIG_STACK_VALIDATION
 
 # Rebuild all objects when objtool changes, or is enabled/disabled.
index 3ff3dbb3a830cfc60b1074a8361456ff3191f5c0..6d004143c4d7aac0e6c0a089e37b38b2680c0e37 100644 (file)
@@ -220,6 +220,18 @@ dtc_cpp_flags  = -Wp,-MMD,$(depfile).pre.tmp -nostdinc                    \
                 $(addprefix -I,$(DTC_INCLUDE))                          \
                 -undef -D__DTS__
 
+# Objtool arguments are also needed for modfinal with LTO, so we define
+# then here to avoid duplication.
+objtool_args =                                                         \
+       $(if $(CONFIG_UNWINDER_ORC),orc generate,check)                 \
+       $(if $(part-of-module), --module,)                              \
+       $(if $(CONFIG_FRAME_POINTER),, --no-fp)                         \
+       $(if $(or $(CONFIG_GCOV_KERNEL),$(CONFIG_LTO_CLANG)),           \
+               --no-unreachable,)                                      \
+       $(if $(CONFIG_RETPOLINE), --retpoline,)                         \
+       $(if $(CONFIG_X86_SMAP), --uaccess,)                            \
+       $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount,)
+
 # Useful for describing the dependency of composite objects
 # Usage:
 #   $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
index 6de2c35b64e892248fc1d36fa9ae498012a52960..735e11e9041b9d6b8e9c5d7a05aca5b3be24a582 100644 (file)
@@ -9,7 +9,7 @@ __modfinal:
 include include/config/auto.conf
 include $(srctree)/scripts/Kbuild.include
 
-# for c_flags
+# for c_flags and objtool_args
 include $(srctree)/scripts/Makefile.lib
 
 # find all modules listed in modules.order
@@ -34,10 +34,23 @@ ifdef CONFIG_LTO_CLANG
 # With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
 # avoid a second slow LTO link
 prelink-ext := .lto
-endif
+
+# ELF processing was skipped earlier because we didn't have native code,
+# so let's now process the prelinked binary before we link the module.
+
+ifdef CONFIG_STACK_VALIDATION
+ifneq ($(SKIP_STACK_VALIDATION),1)
+cmd_ld_ko_o +=                                                         \
+       $(objtree)/tools/objtool/objtool $(objtool_args)                \
+               $(@:.ko=$(prelink-ext).o);
+
+endif # SKIP_STACK_VALIDATION
+endif # CONFIG_STACK_VALIDATION
+
+endif # CONFIG_LTO_CLANG
 
 quiet_cmd_ld_ko_o = LD [M]  $@
-      cmd_ld_ko_o =                                                     \
+      cmd_ld_ko_o +=                                                   \
        $(LD) -r $(KBUILD_LDFLAGS)                                      \
                $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)              \
                -T scripts/module.lds -o $@ $(filter %.o, $^);          \
index 18aed761f9c04aea62f293927d7020fd90c55225..3b261b0f74f0a7609dafbea36a19c647062ce8d9 100755 (executable)
@@ -103,14 +103,36 @@ modpost_link()
 
 objtool_link()
 {
+       local objtoolcmd;
        local objtoolopt;
 
+       if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then
+               # Don't perform vmlinux validation unless explicitly requested,
+               # but run objtool on vmlinux.o now that we have an object file.
+               if [ -n "${CONFIG_UNWINDER_ORC}" ]; then
+                       objtoolcmd="orc generate"
+               fi
+
+               objtoolopt="${objtoolopt} --duplicate"
+
+               if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then
+                       objtoolopt="${objtoolopt} --mcount"
+               fi
+       fi
+
        if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
-               objtoolopt="check --vmlinux --noinstr"
+               objtoolopt="${objtoolopt} --noinstr"
+       fi
+
+       if [ -n "${objtoolopt}" ]; then
+               if [ -z "${objtoolcmd}" ]; then
+                       objtoolcmd="check"
+               fi
+               objtoolopt="${objtoolopt} --vmlinux"
                if [ -z "${CONFIG_FRAME_POINTER}" ]; then
                        objtoolopt="${objtoolopt} --no-fp"
                fi
-               if [ -n "${CONFIG_GCOV_KERNEL}" ]; then
+               if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then
                        objtoolopt="${objtoolopt} --no-unreachable"
                fi
                if [ -n "${CONFIG_RETPOLINE}" ]; then
@@ -120,7 +142,7 @@ objtool_link()
                        objtoolopt="${objtoolopt} --uaccess"
                fi
                info OBJTOOL ${1}
-               tools/objtool/objtool ${objtoolopt} ${1}
+               tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
        fi
 }