History

Merge tag 'clang-lto-v5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull clang LTO updates from Kees Cook: "Clang Link Time Optimization. This is built on the work done preparing for LTO by arm64 folks, tracing folks, etc. This includes the core changes as well as the remaining pieces for arm64 (LTO has been the default build method on Android for about 3 years now, as it is the prerequisite for the Control Flow Integrity protections). While x86 LTO enablement is done, it depends on some pending objtool clean-ups. It's possible that I'll send a "part 2" pull request for LTO that includes x86 support. For merge log posterity, and as detailed in commit dc5723b02e52 ("kbuild: add support for Clang LTO"), here is the lt;dr to do an LTO build: make LLVM=1 LLVM_IAS=1 defconfig scripts/config -e LTO_CLANG_THIN make LLVM=1 LLVM_IAS=1 (To do a cross-compile of arm64, add "CROSS_COMPILE=aarch64-linux-gnu-" and "ARCH=arm64" to the "make" command lines.) Summary: - Clang LTO build infrastructure and arm64-specific enablement (Sami Tolvanen) - Recursive build CC_FLAGS_LTO fix (Alexander Lobakin)" * tag 'clang-lto-v5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: kbuild: prevent CC_FLAGS_LTO self-bloating on recursive rebuilds arm64: allow LTO to be selected arm64: disable recordmcount with DYNAMIC_FTRACE_WITH_REGS arm64: vdso: disable LTO drivers/misc/lkdtm: disable LTO for rodata.o efi/libstub: disable LTO scripts/mod: disable LTO for empty.c modpost: lto: strip .lto from module names PCI: Fix PREL32 relocations for LTO init: lto: fix PREL32 relocations init: lto: ensure initcall ordering kbuild: lto: add a default list of used symbols kbuild: lto: merge module sections kbuild: lto: limit inlining kbuild: lto: fix module versioning kbuild: add support for Clang LTO tracing: move function tracer options to Kconfig

Linus Torvalds committed 5 years ago

Commit 79db4d22 parents 3b9cdaf 2b8689524 files · +704 −59Browse files

Showing the changes to scripts (12 of 24 files). Show all

Unified · Split

12 files
  1. scripts/Makefile.build +41 −7
  2. scripts/Makefile.lib +4 −2
  3. scripts/Makefile.modfinal +8 −1
  4. scripts/Makefile.modpost +23 −2
  5. scripts/generate_initcall_order.pl +270 −0
  6. scripts/link-vmlinux.sh +61 −9
  7. scripts/lto-used-symbollist.txt +5 −0
  8. scripts/mod/Makefile +1 −0
  9. scripts/mod/modpost.c +7 −9
  10. scripts/mod/modpost.h +9 −0
  11. scripts/mod/sumversion.c +5 −1
  12. scripts/module.lds.S +24 −0
scripts/Makefile.build+41−7
@@ -111,7 +111,7 @@ endif · 110 unmodified lines
111# ---------------------------------------------------------------------------111# ---------------------------------------------------------------------------
112 112
113quiet_cmd_cc_s_c = CC $(quiet_modtag) $@113quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
114 cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $<114 cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS) $(CC_FLAGS_LTO), $(c_flags)) -fverbose-asm -S -o $@ $<
115 115
116$(obj)/%.s: $(src)/%.c FORCE116$(obj)/%.s: $(src)/%.c FORCE
117 $(call if_changed_dep,cc_s_c)117 $(call if_changed_dep,cc_s_c)
@@ -166,6 +166,15 @@ ifdef CONFIG_MODVERSIONS · 48 unmodified lines
166# the actual value of the checksum generated by genksyms166# the actual value of the checksum generated by genksyms
167# o remove .tmp_<file>.o to <file>.o167# o remove .tmp_<file>.o to <file>.o
168 168
169ifdef CONFIG_LTO_CLANG
170# Generate .o.symversions files for each .o with exported symbols, and link these
171# to the kernel and/or modules at the end.
172cmd_modversions_c = \
173 if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
174 $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
175 > $@.symversions; \
176 fi;
177else
169cmd_modversions_c = \178cmd_modversions_c = \
170 if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \179 if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
171 $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \180 $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
@@ -177,9 +186,9 @@ cmd_modversions_c = \ · 5 unmodified lines
177 rm -f $(@D)/.tmp_$(@F:.o=.ver); \186 rm -f $(@D)/.tmp_$(@F:.o=.ver); \
178 fi187 fi
179endif188endif
189endif
180 190
181ifdef CONFIG_FTRACE_MCOUNT_RECORD191ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
182ifndef CC_USING_RECORD_MCOUNT
183# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl192# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
184ifdef BUILD_C_RECORDMCOUNT193ifdef BUILD_C_RECORDMCOUNT
185ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")194ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
@@ -206,8 +215,7 @@ recordmcount_source := $(srctree)/scripts/recordmcount.pl · 20 unmodified lines
206endif # BUILD_C_RECORDMCOUNT215endif # BUILD_C_RECORDMCOUNT
207cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \216cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
208 $(sub_cmd_record_mcount))217 $(sub_cmd_record_mcount))
209endif # CC_USING_RECORD_MCOUNT218endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
210endif # CONFIG_FTRACE_MCOUNT_RECORD
211 219
212ifdef CONFIG_STACK_VALIDATION220ifdef CONFIG_STACK_VALIDATION
213ifneq ($(SKIP_STACK_VALIDATION),1)221ifneq ($(SKIP_STACK_VALIDATION),1)
@@ -388,6 +396,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler · 174 unmodified lines
388$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;396$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
389$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;397$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
390 398
399# combine symversions for later processing
400quiet_cmd_update_lto_symversions = SYMVER $@
401ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
402 cmd_update_lto_symversions = \
403 rm -f $@.symversions \
404 $(foreach n, $(filter-out FORCE,$^), \
405 $(if $(wildcard $(n).symversions), \
406 ; cat $(n).symversions >> $@.symversions))
407else
408 cmd_update_lto_symversions = echo >/dev/null
409endif
410
391#411#
392# Rule to compile a set of .o files into one .a file (without symbol table)412# Rule to compile a set of .o files into one .a file (without symbol table)
393#413#
@@ -395,8 +415,11 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ; · 1 unmodified line
395quiet_cmd_ar_builtin = AR $@415quiet_cmd_ar_builtin = AR $@
396 cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)416 cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
397 417
418quiet_cmd_ar_and_symver = AR $@
419 cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)
420
398$(obj)/built-in.a: $(real-obj-y) FORCE421$(obj)/built-in.a: $(real-obj-y) FORCE
399 $(call if_changed,ar_builtin)422 $(call if_changed,ar_and_symver)
400 423
401#424#
402# Rule to create modules.order file425# Rule to create modules.order file
@@ -416,15 +439,26 @@ $(obj)/modules.order: $(obj-m) FORCE · 13 unmodified lines
416#439#
417# Rule to compile a set of .o files into one .a file (with symbol table)440# Rule to compile a set of .o files into one .a file (with symbol table)
418#441#
442quiet_cmd_ar_lib = AR $@
443 cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)
444
419$(obj)/lib.a: $(lib-y) FORCE445$(obj)/lib.a: $(lib-y) FORCE
420 $(call if_changed,ar)446 $(call if_changed,ar_lib)
421 447
422# NOTE:448# NOTE:
423# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object449# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
424# module is turned into a multi object module, $^ will contain header file450# module is turned into a multi object module, $^ will contain header file
425# dependencies recorded in the .*.cmd file.451# dependencies recorded in the .*.cmd file.
452ifdef CONFIG_LTO_CLANG
453quiet_cmd_link_multi-m = AR [M] $@
454cmd_link_multi-m = \
455 $(cmd_update_lto_symversions); \
456 rm -f $@; \
457 $(AR) cDPrsT $@ $(filter %.o,$^)
458else
426quiet_cmd_link_multi-m = LD [M] $@459quiet_cmd_link_multi-m = LD [M] $@
427 cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)460 cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
461endif
428 462
429$(multi-used-m): FORCE463$(multi-used-m): FORCE
430 $(call if_changed,link_multi-m)464 $(call if_changed,link_multi-m)
scripts/Makefile.lib+4−2
@@ -119,9 +119,11 @@ target-stem = $(basename $(patsubst $(obj)/%,%,$@)) · 118 unmodified lines
119# These flags are needed for modversions and compiling, so we define them here119# These flags are needed for modversions and compiling, so we define them here
120# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will120# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will
121# end up in (or would, if it gets compiled in)121# end up in (or would, if it gets compiled in)
122name-fix = $(call stringify,$(subst $(comma),_,$(subst -,_,$1)))122name-fix-token = $(subst $(comma),_,$(subst -,_,$1))
123name-fix = $(call stringify,$(call name-fix-token,$1))
123basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))124basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
124modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))125modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname)) \
126 -D__KBUILD_MODNAME=kmod_$(call name-fix-token,$(modname))
125modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))127modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))
126 128
127_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), \129_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), \
scripts/Makefile.modfinal+8−1
@@ -30,6 +30,12 @@ quiet_cmd_cc_o_c = CC [M] $@ · 29 unmodified lines
30 30
31ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)31ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
32 32
33ifdef CONFIG_LTO_CLANG
34# With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
35# avoid a second slow LTO link
36prelink-ext := .lto
37endif
38
33quiet_cmd_ld_ko_o = LD [M] $@39quiet_cmd_ld_ko_o = LD [M] $@
34 cmd_ld_ko_o = \40 cmd_ld_ko_o = \
35 $(LD) -r $(KBUILD_LDFLAGS) \41 $(LD) -r $(KBUILD_LDFLAGS) \
@@ -53,8 +59,9 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \ · 17 unmodified lines
53 $(cmd); \59 $(cmd); \
54 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)60 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
55 61
62
56# Re-generate module BTFs if either module's .ko or vmlinux changed63# Re-generate module BTFs if either module's .ko or vmlinux changed
57$(modules): %.ko: %.o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE64$(modules): %.ko: %$(prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
58 +$(call if_changed_except,ld_ko_o,vmlinux)65 +$(call if_changed_except,ld_ko_o,vmlinux)
59ifdef CONFIG_DEBUG_INFO_BTF_MODULES66ifdef CONFIG_DEBUG_INFO_BTF_MODULES
60 +$(if $(newer-prereqs),$(call cmd,btf_ko))67 +$(if $(newer-prereqs),$(call cmd,btf_ko))
scripts/Makefile.modpost+23−2
@@ -43,6 +43,9 @@ __modpost: · 42 unmodified lines
43include include/config/auto.conf43include include/config/auto.conf
44include scripts/Kbuild.include44include scripts/Kbuild.include
45 45
46# for ld_flags
47include scripts/Makefile.lib
48
46MODPOST = scripts/mod/modpost \49MODPOST = scripts/mod/modpost \
47 $(if $(CONFIG_MODVERSIONS),-m) \50 $(if $(CONFIG_MODVERSIONS),-m) \
48 $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \51 $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
@@ -102,12 +105,30 @@ $(input-symdump): · 53 unmodified lines
102 @echo >&2 'WARNING: Symbol version dump "$@" is missing.'105 @echo >&2 'WARNING: Symbol version dump "$@" is missing.'
103 @echo >&2 ' Modules may not have dependencies or modversions.'106 @echo >&2 ' Modules may not have dependencies or modversions.'
104 107
108ifdef CONFIG_LTO_CLANG
109# With CONFIG_LTO_CLANG, .o files might be LLVM bitcode, so we need to run
110# LTO to compile them into native code before running modpost
111prelink-ext := .lto
112
113quiet_cmd_cc_lto_link_modules = LTO [M] $@
114cmd_cc_lto_link_modules = \
115 $(LD) $(ld_flags) -r -o $@ \
116 $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
117 echo -T $(@:.lto.o=.o.symversions)) \
118 --whole-archive $^
119
120%.lto.o: %.o
121 $(call if_changed,cc_lto_link_modules)
122endif
123
124modules := $(sort $(shell cat $(MODORDER)))
125
105# Read out modules.order to pass in modpost.126# Read out modules.order to pass in modpost.
106# Otherwise, allmodconfig would fail with "Argument list too long".127# Otherwise, allmodconfig would fail with "Argument list too long".
107quiet_cmd_modpost = MODPOST $@128quiet_cmd_modpost = MODPOST $@
108 cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -129 cmd_modpost = sed 's/\.ko$$/$(prelink-ext)\.o/' $< | $(MODPOST) -T -
109 130
110$(output-symdump): $(MODORDER) $(input-symdump) FORCE131$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(prelink-ext).o) FORCE
111 $(call if_changed,modpost)132 $(call if_changed,modpost)
112 133
113targets += $(output-symdump)134targets += $(output-symdump)
scripts/generate_initcall_order.pl+270−0
@@ -0,0 +1,270 @@
1#!/usr/bin/env perl
2# SPDX-License-Identifier: GPL-2.0
3#
4# Generates a linker script that specifies the correct initcall order.
5#
6# Copyright (C) 2019 Google LLC
7
8use strict;
9use warnings;
10use IO::Handle;
11use IO::Select;
12use POSIX ":sys_wait_h";
13
14my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
15my $objtree = $ENV{'objtree'} || '.';
16
17## currently active child processes
18my $jobs = {}; # child process pid -> file handle
19## results from child processes
20my $results = {}; # object index -> [ { level, secname }, ... ]
21
22## reads _NPROCESSORS_ONLN to determine the maximum number of processes to
23## start
24sub get_online_processors {
25 open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
26 or die "$0: ERROR: failed to execute getconf: $!";
27 my $procs = <$fh>;
28 close($fh);
29
30 if (!($procs =~ /^\d+$/)) {
31 return 1;
32 }
33
34 return int($procs);
35}
36
37## writes results to the parent process
38## format: <file index> <initcall level> <base initcall section name>
39sub write_results {
40 my ($index, $initcalls) = @_;
41
42 # sort by the counter value to ensure the order of initcalls within
43 # each object file is correct
44 foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
45 my $level = $initcalls->{$counter}->{'level'};
46
47 # section name for the initcall function
48 my $secname = $initcalls->{$counter}->{'module'} . '__' .
49 $counter . '_' .
50 $initcalls->{$counter}->{'line'} . '_' .
51 $initcalls->{$counter}->{'function'};
52
53 print "$index $level $secname\n";
54 }
55}
56
57## reads a result line from a child process and adds it to the $results array
58sub read_results{
59 my ($fh) = @_;
60
61 # each child prints out a full line w/ autoflush and exits after the
62 # last line, so even if buffered I/O blocks here, it shouldn't block
63 # very long
64 my $data = <$fh>;
65
66 if (!defined($data)) {
67 return 0;
68 }
69
70 chomp($data);
71
72 my ($index, $level, $secname) = $data =~
73 /^(\d+)\ ([^\ ]+)\ (.*)$/;
74
75 if (!defined($index) ||
76 !defined($level) ||
77 !defined($secname)) {
78 die "$0: ERROR: child process returned invalid data: $data\n";
79 }
80
81 $index = int($index);
82
83 if (!exists($results->{$index})) {
84 $results->{$index} = [];
85 }
86
87 push (@{$results->{$index}}, {
88 'level' => $level,
89 'secname' => $secname
90 });
91
92 return 1;
93}
94
95## finds initcalls from an object file or all object files in an archive, and
96## writes results back to the parent process
97sub find_initcalls {
98 my ($index, $file) = @_;
99
100 die "$0: ERROR: file $file doesn't exist?" if (! -f $file);
101
102 open(my $fh, "\"$nm\" --defined-only \"$file\" 2>/dev/null |")
103 or die "$0: ERROR: failed to execute \"$nm\": $!";
104
105 my $initcalls = {};
106
107 while (<$fh>) {
108 chomp;
109
110 # check for the start of a new object file (if processing an
111 # archive)
112 my ($path)= $_ =~ /^(.+)\:$/;
113
114 if (defined($path)) {
115 write_results($index, $initcalls);
116 $initcalls = {};
117 next;
118 }
119
120 # look for an initcall
121 my ($module, $counter, $line, $symbol) = $_ =~
122 /[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$/;
123
124 if (!defined($module)) {
125 $module = ''
126 }
127
128 if (!defined($counter) ||
129 !defined($line) ||
130 !defined($symbol)) {
131 next;
132 }
133
134 # parse initcall level
135 my ($function, $level) = $symbol =~
136 /^(.*)((early|rootfs|con|[0-9])s?)$/;
137
138 die "$0: ERROR: invalid initcall name $symbol in $file($path)"
139 if (!defined($function) || !defined($level));
140
141 $initcalls->{$counter} = {
142 'module' => $module,
143 'line' => $line,
144 'function' => $function,
145 'level' => $level,
146 };
147 }
148
149 close($fh);
150 write_results($index, $initcalls);
151}
152
153## waits for any child process to complete, reads the results, and adds them to
154## the $results array for later processing
155sub wait_for_results {
156 my ($select) = @_;
157
158 my $pid = 0;
159 do {
160 # unblock children that may have a full write buffer
161 foreach my $fh ($select->can_read(0)) {
162 read_results($fh);
163 }
164
165 # check for children that have exited, read the remaining data
166 # from them, and clean up
167 $pid = waitpid(-1, WNOHANG);
168 if ($pid > 0) {
169 if (!exists($jobs->{$pid})) {
170 next;
171 }
172
173 my $fh = $jobs->{$pid};
174 $select->remove($fh);
175
176 while (read_results($fh)) {
177 # until eof
178 }
179
180 close($fh);
181 delete($jobs->{$pid});
182 }
183 } while ($pid > 0);
184}
185
186## forks a child to process each file passed in the command line and collects
187## the results
188sub process_files {
189 my $index = 0;
190 my $njobs = $ENV{'PARALLELISM'} || get_online_processors();
191 my $select = IO::Select->new();
192
193 while (my $file = shift(@ARGV)) {
194 # fork a child process and read it's stdout
195 my $pid = open(my $fh, '-|');
196
197 if (!defined($pid)) {
198 die "$0: ERROR: failed to fork: $!";
199 } elsif ($pid) {
200 # save the child process pid and the file handle
201 $select->add($fh);
202 $jobs->{$pid} = $fh;
203 } else {
204 # in the child process
205 STDOUT->autoflush(1);
206 find_initcalls($index, "$objtree/$file");
207 exit;
208 }
209
210 $index++;
211
212 # limit the number of children to $njobs
213 if (scalar(keys(%{$jobs})) >= $njobs) {
214 wait_for_results($select);
215 }
216 }
217
218 # wait for the remaining children to complete
219 while (scalar(keys(%{$jobs})) > 0) {
220 wait_for_results($select);
221 }
222}
223
224sub generate_initcall_lds() {
225 process_files();
226
227 my $sections = {}; # level -> [ secname, ...]
228
229 # sort results to retain link order and split to sections per
230 # initcall level
231 foreach my $index (sort { $a <=> $b } keys(%{$results})) {
232 foreach my $result (@{$results->{$index}}) {
233 my $level = $result->{'level'};
234
235 if (!exists($sections->{$level})) {
236 $sections->{$level} = [];
237 }
238
239 push(@{$sections->{$level}}, $result->{'secname'});
240 }
241 }
242
243 die "$0: ERROR: no initcalls?" if (!keys(%{$sections}));
244
245 # print out a linker script that defines the order of initcalls for
246 # each level
247 print "SECTIONS {\n";
248
249 foreach my $level (sort(keys(%{$sections}))) {
250 my $section;
251
252 if ($level eq 'con') {
253 $section = '.con_initcall.init';
254 } else {
255 $section = ".initcall${level}.init";
256 }
257
258 print "\t${section} : {\n";
259
260 foreach my $secname (@{$sections->{$level}}) {
261 print "\t\t*(${section}..${secname}) ;\n";
262 }
263
264 print "\t}\n";
265 }
266
267 print "}\n";
268}
269
270generate_initcall_lds();
scripts/link-vmlinux.sh+61−9
@@ -43,11 +43,37 @@ info() · 42 unmodified lines
43 fi43 fi
44}44}
45 45
46# Generate a linker script to ensure correct ordering of initcalls.
47gen_initcalls()
48{
49 info GEN .tmp_initcalls.lds
50
51 ${PYTHON} ${srctree}/scripts/jobserver-exec \
52 ${PERL} ${srctree}/scripts/generate_initcall_order.pl \
53 ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
54 > .tmp_initcalls.lds
55}
56
57# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
58# .tmp_symversions.lds
59gen_symversions()
60{
61 info GEN .tmp_symversions.lds
62 rm -f .tmp_symversions.lds
63
64 for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
65 if [ -f ${o}.symversions ]; then
66 cat ${o}.symversions >> .tmp_symversions.lds
67 fi
68 done
69}
70
46# Link of vmlinux.o used for section mismatch analysis71# Link of vmlinux.o used for section mismatch analysis
47# ${1} output file72# ${1} output file
48modpost_link()73modpost_link()
49{74{
50 local objects75 local objects
76 local lds=""
51 77
52 objects="--whole-archive \78 objects="--whole-archive \
53 ${KBUILD_VMLINUX_OBJS} \79 ${KBUILD_VMLINUX_OBJS} \
@@ -56,7 +82,23 @@ modpost_link() · 2 unmodified lines
56 ${KBUILD_VMLINUX_LIBS} \82 ${KBUILD_VMLINUX_LIBS} \
57 --end-group"83 --end-group"
58 84
59 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}85 if [ -n "${CONFIG_LTO_CLANG}" ]; then
86 gen_initcalls
87 lds="-T .tmp_initcalls.lds"
88
89 if [ -n "${CONFIG_MODVERSIONS}" ]; then
90 gen_symversions
91 lds="${lds} -T .tmp_symversions.lds"
92 fi
93
94 # This might take a while, so indicate that we're doing
95 # an LTO link
96 info LTO ${1}
97 else
98 info LD ${1}
99 fi
100
101 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
60}102}
61 103
62objtool_link()104objtool_link()
@@ -103,13 +145,22 @@ vmlinux_link() · 40 unmodified lines
103 fi145 fi
104 146
105 if [ "${SRCARCH}" != "um" ]; then147 if [ "${SRCARCH}" != "um" ]; then
106 objects="--whole-archive \148 if [ -n "${CONFIG_LTO_CLANG}" ]; then
107 ${KBUILD_VMLINUX_OBJS} \149 # Use vmlinux.o instead of performing the slow LTO
108 --no-whole-archive \150 # link again.
109 --start-group \151 objects="--whole-archive \
110 ${KBUILD_VMLINUX_LIBS} \152 vmlinux.o \
111 --end-group \153 --no-whole-archive \
112 ${@}"154 ${@}"
155 else
156 objects="--whole-archive \
157 ${KBUILD_VMLINUX_OBJS} \
158 --no-whole-archive \
159 --start-group \
160 ${KBUILD_VMLINUX_LIBS} \
161 --end-group \
162 ${@}"
163 fi
113 164
114 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \165 ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
115 ${strip_debug#-Wl,} \166 ${strip_debug#-Wl,} \
@@ -225,6 +276,8 @@ cleanup() · 109 unmodified lines
225{276{
226 rm -f .btf.*277 rm -f .btf.*
227 rm -f .tmp_System.map278 rm -f .tmp_System.map
279 rm -f .tmp_initcalls.lds
280 rm -f .tmp_symversions.lds
228 rm -f .tmp_vmlinux*281 rm -f .tmp_vmlinux*
229 rm -f System.map282 rm -f System.map
230 rm -f vmlinux283 rm -f vmlinux
@@ -274,7 +327,6 @@ fi; · 43 unmodified lines
274${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1327${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
275 328
276#link vmlinux.o329#link vmlinux.o
277info LD vmlinux.o
278modpost_link vmlinux.o330modpost_link vmlinux.o
279objtool_link vmlinux.o331objtool_link vmlinux.o
280 332
scripts/lto-used-symbollist.txt+5−0
@@ -0,0 +1,5 @@
1memcpy
2memmove
3memset
4__stack_chk_fail
5__stack_chk_guard
scripts/mod/Makefile+1−0
@@ -1,5 +1,6 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2OBJECT_FILES_NON_STANDARD := y2OBJECT_FILES_NON_STANDARD := y
3CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
3 4
4hostprogs-always-y += modpost mk_elfconfig5hostprogs-always-y += modpost mk_elfconfig
5always-y += empty.o6always-y += empty.o
scripts/mod/modpost.c+7−9
@@ -17,7 +17,6 @@ · 16 unmodified lines
17#include <ctype.h>17#include <ctype.h>
18#include <string.h>18#include <string.h>
19#include <limits.h>19#include <limits.h>
20#include <stdbool.h>
21#include <errno.h>20#include <errno.h>
22#include "modpost.h"21#include "modpost.h"
23#include "../../include/linux/license.h"22#include "../../include/linux/license.h"
@@ -84,14 +83,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...) · 60 unmodified lines
84 error_occurred = true;83 error_occurred = true;
85}84}
86 85
87static inline bool strends(const char *str, const char *postfix)
88{
89 if (strlen(str) < strlen(postfix))
90 return false;
91
92 return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
93}
94
95void *do_nofail(void *ptr, const char *expr)86void *do_nofail(void *ptr, const char *expr)
96{87{
97 if (!ptr)88 if (!ptr)
@@ -1988,6 +1979,10 @@ static char *remove_dot(char *s) · 1890 unmodified lines
1988 size_t m = strspn(s + n + 1, "0123456789");1979 size_t m = strspn(s + n + 1, "0123456789");
1989 if (m && (s[n + m] == '.' || s[n + m] == 0))1980 if (m && (s[n + m] == '.' || s[n + m] == 0))
1990 s[n] = 0;1981 s[n] = 0;
1982
1983 /* strip trailing .lto */
1984 if (strends(s, ".lto"))
1985 s[strlen(s) - 4] = '\0';
1991 }1986 }
1992 return s;1987 return s;
1993}1988}
@@ -2011,6 +2006,9 @@ static void read_symbols(const char *modname) · 17 unmodified lines
2011 /* strip trailing .o */2006 /* strip trailing .o */
2012 tmp = NOFAIL(strdup(modname));2007 tmp = NOFAIL(strdup(modname));
2013 tmp[strlen(tmp) - 2] = '\0';2008 tmp[strlen(tmp) - 2] = '\0';
2009 /* strip trailing .lto */
2010 if (strends(tmp, ".lto"))
2011 tmp[strlen(tmp) - 4] = '\0';
2014 mod = new_module(tmp);2012 mod = new_module(tmp);
2015 free(tmp);2013 free(tmp);
2016 }2014 }
scripts/mod/modpost.h+9−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2#include <stdio.h>2#include <stdio.h>
3#include <stdlib.h>3#include <stdlib.h>
4#include <stdarg.h>4#include <stdarg.h>
5#include <stdbool.h>
5#include <string.h>6#include <string.h>
6#include <sys/types.h>7#include <sys/types.h>
7#include <sys/stat.h>8#include <sys/stat.h>
@@ -180,6 +181,14 @@ static inline unsigned int get_secindex(const struct elf_info *info, · 172 unmodified lines
180 return info->symtab_shndx_start[sym - info->symtab_start];181 return info->symtab_shndx_start[sym - info->symtab_start];
181}182}
182 183
184static inline bool strends(const char *str, const char *postfix)
185{
186 if (strlen(str) < strlen(postfix))
187 return false;
188
189 return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
190}
191
183/* file2alias.c */192/* file2alias.c */
184extern unsigned int cross_build;193extern unsigned int cross_build;
185void handle_moddevtable(struct module *mod, struct elf_info *info,194void handle_moddevtable(struct module *mod, struct elf_info *info,
scripts/mod/sumversion.c+5−1
@@ -391,10 +391,14 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) · 390 unmodified lines
391 struct md4_ctx md;391 struct md4_ctx md;
392 char *fname;392 char *fname;
393 char filelist[PATH_MAX + 1];393 char filelist[PATH_MAX + 1];
394 int postfix_len = 1;
395
396 if (strends(modname, ".lto.o"))
397 postfix_len = 5;
394 398
395 /* objects for a module are listed in the first line of *.mod file. */399 /* objects for a module are listed in the first line of *.mod file. */
396 snprintf(filelist, sizeof(filelist), "%.*smod",400 snprintf(filelist, sizeof(filelist), "%.*smod",
397 (int)strlen(modname) - 1, modname);401 (int)strlen(modname) - postfix_len, modname);
398 402
399 buf = read_text_file(filelist);403 buf = read_text_file(filelist);
400 404
scripts/module.lds.S+24−0
@@ -23,6 +23,30 @@ SECTIONS { · 22 unmodified lines
23 .init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) }23 .init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) }
24 24
25 __jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) }25 __jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) }
26
27 __patchable_function_entries : { *(__patchable_function_entries) }
28
29 /*
30 * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and
31 * -ffunction-sections, which increases the size of the final module.
32 * Merge the split sections in the final binary.
33 */
34 .bss : {
35 *(.bss .bss.[0-9a-zA-Z_]*)
36 *(.bss..L*)
37 }
38
39 .data : {
40 *(.data .data.[0-9a-zA-Z_]*)
41 *(.data..L*)
42 }
43
44 .rodata : {
45 *(.rodata .rodata.[0-9a-zA-Z_]*)
46 *(.rodata..L*)
47 }
48
49 .text : { *(.text .text.[0-9a-zA-Z_]*) }
26}50}
27 51
28/* bring in arch-specific sections */52/* bring in arch-specific sections */