FROMLIST: init: lto: ensure initcall ordering

With LTO, the compiler doesn't necessarily obey the link order for
initcalls, and initcall variables need globally unique names to avoid
collisions at link time.

This change exports __KBUILD_MODNAME and adds the initcall_id() macro,
which uses it together with __COUNTER__ and __LINE__ to help ensure
these variables have unique names, and moves each variable to its own
section when LTO is enabled, so the correct order can be specified using
a linker script.

The generate_initcall_ordering.pl script uses nm to find initcalls from
the object files passed to the linker, and generates a linker script
that specifies the same order for initcalls that we would have without
LTO. With LTO enabled, the script is called in link-vmlinux.sh through
jobserver-exec to limit the number of jobs spawned.

Bug: 145210207
Change-Id: I80619eac3674acd9c6d2566443d16b3d09515351
Link: https://lore.kernel.org/lkml/20201211184633.3213045-8-samitolvanen@google.com/
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Sami Tolvanen
2017-12-08 15:49:24 -08:00
parent 3ea19301f7
commit 110784e046
4 changed files with 334 additions and 9 deletions

View File

@@ -43,6 +43,17 @@ info()
fi
}
# Generate a linker script to ensure correct ordering of initcalls.
gen_initcalls()
{
info GEN .tmp_initcalls.lds
${PYTHON} ${srctree}/scripts/jobserver-exec \
${PERL} ${srctree}/scripts/generate_initcall_order.pl \
${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
> .tmp_initcalls.lds
}
# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
# .tmp_symversions.lds
gen_symversions()
@@ -72,6 +83,9 @@ modpost_link()
--end-group"
if [ -n "${CONFIG_LTO_CLANG}" ]; then
gen_initcalls
lds="-T .tmp_initcalls.lds"
if [ -n "${CONFIG_MODVERSIONS}" ]; then
gen_symversions
lds="${lds} -T .tmp_symversions.lds"
@@ -262,6 +276,7 @@ cleanup()
{
rm -f .btf.*
rm -f .tmp_System.map
rm -f .tmp_initcalls.lds
rm -f .tmp_symversions.lds
rm -f .tmp_vmlinux*
rm -f System.map