aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSami Tolvanen2020-04-13 16:10:13 -0700
committerKees Cook2021-02-23 12:46:57 -0800
commitb1a1a1a09b4606d41723a426110382d2077c26fb (patch)
tree4c6672f8aa90443585f2ceb4cb4e65425d800c6a
parent41425ebe20245c99b44d6ba0f017be9bfc28414f (diff)
kbuild: lto: postpone objtool
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>
-rw-r--r--scripts/Makefile.build22
-rw-r--r--scripts/Makefile.lib12
-rw-r--r--scripts/Makefile.modfinal19
-rwxr-xr-xscripts/link-vmlinux.sh28
4 files changed, 55 insertions, 26 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 59fabd9685ee..3f6bf0ea7c0e 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -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.
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 3ff3dbb3a830..6d004143c4d7 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -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)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 6de2c35b64e8..735e11e9041b 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -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, $^); \
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 18aed761f9c0..3b261b0f74f0 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -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
}