History

kbuild: link of vmlinux moved to a script

Move the final link of vmlinux to a script to improve readability and maintainability of the code. The Makefile fragments used to link vmlinux has over the years seen far too many changes and the logic had become hard to follow. As the process by nature is serialized there was nothing gained including this in the Makefile. "um" has special link requirments - and the only way to handle this was to hard-code the linking of "um" in the script. This was better than trying to modularize it only for the benefit of "um" anyway. The shell script has been improved after input from: Arnaud Lacombe <lacombar@gmail.com> Nick Bowler <nbowler@elliptictech.com>

Sam Ravnborg committed 14 years ago

Commit 1f2bfbd1 parent 95698573 files · +225 −212Browse files

Unified · Split

3 files
  1. Makefile +12 −203
  2. arch/um/Makefile +2 −9
  3. scripts/link-vmlinux.sh +211 −0
Makefile+12−203
@@ -337,7 +337,6 @@ AWK = awk · 336 unmodified lines
337337 GENKSYMS = scripts/genksyms/genksyms
338338 INSTALLKERNEL := installkernel
339339 DEPMOD = /sbin/depmod
340−KALLSYMS = scripts/kallsyms
341340 PERL = perl
342341 CHECK = sparse
343342
@@ -723,191 +722,21 @@ libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) · 379 unmodified lines
723722 libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
724723 libs-y := $(libs-y1) $(libs-y2)
725724
726−# externally visible symbols
725+# Externally visible symbols (used by link-vmlinux.sh)
727726 export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
728727 export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)
729728 export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
729+export LDFLAGS_vmlinux
730730
731−# Build vmlinux
732−# ---------------------------------------------------------------------------
733−# vmlinux is built from the objects selected by $(vmlinux-init) and
734−# $(vmlinux-main). Most are built-in.o files from top-level directories
735−# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
736−# Ordering when linking is important, and $(vmlinux-init) must be first.
737−#
738−# vmlinux
739−# ^
740−# |
741−# +-< $(vmlinux-init)
742−# | +--< init/version.o + more
743−# |
744−# +--< $(vmlinux-main)
745−# | +--< driver/built-in.o mm/built-in.o + more
746−# |
747−# +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
748−#
749−# vmlinux version (uname -v) cannot be updated during normal
750−# descending-into-subdirs phase since we do not yet know if we need to
751−# update vmlinux.
752−# Therefore this step is delayed until just before final link of vmlinux -
753−# except in the kallsyms case where it is done just before adding the
754−# symbols to the kernel.
755−#
756−# System.map is generated to document addresses of all kernel symbols
757−
758−vmlinux-init := $(head-y) $(init-y)
759−vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
760−vmlinux-all := $(vmlinux-init) $(vmlinux-main)
761−vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
762−
763−# Rule to link vmlinux - also used during CONFIG_KALLSYMS
764−# May be overridden by arch/$(ARCH)/Makefile
765−quiet_cmd_vmlinux__ ?= LD $@
766− cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
767− -T $(vmlinux-lds) $(vmlinux-init) \
768− --start-group $(vmlinux-main) --end-group \
769− $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
770−
771−# Generate new vmlinux version
772−quiet_cmd_vmlinux_version = GEN .version
773− cmd_vmlinux_version = set -e; \
774− if [ ! -r .version ]; then \
775− rm -f .version; \
776− echo 1 >.version; \
777− else \
778− mv .version .old_version; \
779− expr 0$$(cat .old_version) + 1 >.version; \
780− fi; \
781− $(MAKE) $(build)=init
782−
783−# Generate System.map
784−quiet_cmd_sysmap = SYSMAP
785− cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
786−
787−# Link of vmlinux
788−# If CONFIG_KALLSYMS is set .version is already updated
789−# Generate System.map and verify that the content is consistent
790−# Use + in front of the vmlinux_version rule to silent warning with make -j2
791−# First command is ':' to allow us to use + in front of the rule
792−define rule_vmlinux__
793− :
794− $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
795−
796− $(call cmd,vmlinux__)
797− $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
798−
799− $(Q)$(if $($(quiet)cmd_sysmap), \
800− echo ' $($(quiet)cmd_sysmap) System.map' &&) \
801− $(cmd_sysmap) $@ System.map; \
802− if [ $$? -ne 0 ]; then \
803− rm -f $@; \
804− /bin/false; \
805− fi;
806− $(verify_kallsyms)
807−endef
808−
809−
810−ifdef CONFIG_KALLSYMS
811−# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
812−# It's a three stage process:
813−# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
814−# empty
815−# Running kallsyms on that gives us .tmp_kallsyms1.o with
816−# the right size - vmlinux version (uname -v) is updated during this step
817−# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
818−# but due to the added section, some addresses have shifted.
819−# From here, we generate a correct .tmp_kallsyms2.o
820−# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
821−# o Verify that the System.map from vmlinux matches the map from
822−# .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
823−# o If 'make KALLSYMS_EXTRA_PASS=1" was used, do an extra pass using
824−# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a
825−# temporary bypass to allow the kernel to be built while the
826−# maintainers work out what went wrong with kallsyms.
827−
828−last_kallsyms := 2
829−
830−ifdef KALLSYMS_EXTRA_PASS
831−ifneq ($(KALLSYMS_EXTRA_PASS),0)
832−last_kallsyms := 3
833−endif
834−endif
835−
836−kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
837−
838−define verify_kallsyms
839− $(Q)$(if $($(quiet)cmd_sysmap), \
840− echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \
841− $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
842− $(Q)cmp -s System.map .tmp_System.map || \
843− (echo Inconsistent kallsyms data; \
844− echo This is a bug - please report about it; \
845− echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround; \
846− rm .tmp_kallsyms* ; /bin/false )
847−endef
848−
849−# Update vmlinux version before link
850−# Use + in front of this rule to silent warning about make -j1
851−# First command is ':' to allow us to use + in front of this rule
852−cmd_ksym_ld = $(cmd_vmlinux__)
853−define rule_ksym_ld
854− :
855− +$(call cmd,vmlinux_version)
856− $(call cmd,vmlinux__)
857− $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
858−endef
859−
860−# Generate .S file with all kernel symbols
861−quiet_cmd_kallsyms = KSYM $@
862− cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
863− $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
864−
865−.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
866− $(call if_changed_dep,as_o_S)
731+vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
867732
868−.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
869− $(call cmd,kallsyms)
733+# Final link of vmlinux
734+ cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux)
735+quiet_cmd_link-vmlinux = LINK $@
870736
871−# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
872−.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
873− $(call if_changed_rule,ksym_ld)
874−
875−.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
876− $(call if_changed,vmlinux__)
877−
878−.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
879− $(call if_changed,vmlinux__)
880−
881−# Needs to visit scripts/ before $(KALLSYMS) can be used.
882−$(KALLSYMS): scripts ;
883−
884−# Generate some data for debugging strange kallsyms problems
885−debug_kallsyms: .tmp_map$(last_kallsyms)
886−
887−.tmp_map%: .tmp_vmlinux% FORCE
888− ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
889−
890−.tmp_map3: .tmp_map2
891−
892−.tmp_map2: .tmp_map1
893−
894−endif # ifdef CONFIG_KALLSYMS
895−
896−# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
897−# relevant sections renamed as per the linker script.
898−quiet_cmd_vmlinux-modpost = LD $@
899− cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
900− $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
901− $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
902−define rule_vmlinux-modpost
903− :
904− +$(call cmd,vmlinux-modpost)
905− $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
906− $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
907−endef
908−
909−# vmlinux image - including updated kernel symbols
910−vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
737+# Include targets which we want to
738+# execute if the rest of the kernel build went well.
739+vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
911740 ifdef CONFIG_HEADERS_CHECK
912741 $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
913742 endif
@@ -917,22 +746,11 @@ endif · 3 unmodified lines
917746 ifdef CONFIG_BUILD_DOCSRC
918747 $(Q)$(MAKE) $(build)=Documentation
919748 endif
920− $(call vmlinux-modpost)
921− $(call if_changed_rule,vmlinux__)
922− $(Q)rm -f .old_version
923−
924−# build vmlinux.o first to catch section mismatch errors early
925−ifdef CONFIG_KALLSYMS
926−.tmp_vmlinux1: vmlinux.o
927−endif
928−
929−modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
930−vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
931− $(call if_changed_rule,vmlinux-modpost)
749+ +$(call if_changed,link-vmlinux)
932750
933751 # The actual objects are generated when descending,
934752 # make sure no implicit rule kicks in
935−$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
753+$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
936754
937755 # Handle descending into subdirectories listed in $(vmlinux-dirs)
938756 # Preset locale variables to speed up the build process. Limit locale
@@ -1156,8 +974,6 @@ endif # CONFIG_MODULES · 217 unmodified lines
1156974
1157975 # Directories & files removed with 'make clean'
1158976 CLEAN_DIRS += $(MODVERDIR)
1159−CLEAN_FILES += vmlinux System.map \
1160− .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
1161977
1162978 # Directories & files removed with 'make mrproper'
1163979 MRPROPER_DIRS += include/config usr/include include/generated \
@@ -1403,6 +1219,7 @@ scripts: ; · 239 unmodified lines
14031219 endif # KBUILD_EXTMOD
14041220
14051221 clean: $(clean-dirs)
1222+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
14061223 $(call cmd,rmdirs)
14071224 $(call cmd,rmfiles)
14081225 @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
@@ -1536,14 +1353,6 @@ quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) · 127 unmodified lines
15361353 cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
15371354 $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
15381355
1539−a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \
1540− $(KBUILD_AFLAGS_KERNEL) \
1541− $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CPPFLAGS) \
1542− $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
1543−
1544−quiet_cmd_as_o_S = AS $@
1545−cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
1546−
15471356 # read all saved command lines
15481357
15491358 targets := $(wildcard $(sort $(targets)))
arch/um/Makefile+2−9
@@ -121,15 +121,8 @@ LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc · 120 unmodified lines
121121
122122 LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
123123
124−CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
125−define cmd_vmlinux__
126− $(CC) $(CFLAGS_vmlinux) -o $@ \
127− -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
128− -Wl,--start-group $(vmlinux-main) -Wl,--end-group \
129− -lutil \
130− $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o \
131− FORCE ,$^) ; rm -f linux
132−endef
124+# Used by link-vmlinux.sh which has special support for um link
125+export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
133126
134127 # When cleaning we don't include .config, so we don't include
135128 # TT or skas makefiles and don't clean skas_ptregs.h.
scripts/link-vmlinux.sh+211−0
@@ -0,0 +1,211 @@
1+#!/bin/sh
2+#
3+# link vmlinux
4+#
5+# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and
6+# $(KBUILD_VMLINUX_MAIN). Most are built-in.o files from top-level directories
7+# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
8+# Ordering when linking is important, and $(KBUILD_VMLINUX_INIT) must be first.
9+#
10+# vmlinux
11+# ^
12+# |
13+# +-< $(KBUILD_VMLINUX_INIT)
14+# | +--< init/version.o + more
15+# |
16+# +--< $(KBUILD_VMLINUX_MAIN)
17+# | +--< drivers/built-in.o mm/built-in.o + more
18+# |
19+# +-< ${kallsymso} (see description in KALLSYMS section)
20+#
21+# vmlinux version (uname -v) cannot be updated during normal
22+# descending-into-subdirs phase since we do not yet know if we need to
23+# update vmlinux.
24+# Therefore this step is delayed until just before final link of vmlinux.
25+#
26+# System.map is generated to document addresses of all kernel symbols
27+
28+# Error out on error
29+set -e
30+
31+# Nice output in kbuild format
32+# Will be supressed by "make -s"
33+info()
34+{
35+ if [ "${quiet}" != "silent_" ]; then
36+ printf " %-7s %s\n" ${1} ${2}
37+ fi
38+}
39+
40+# Link of vmlinux.o used for section mismatch analysis
41+# ${1} output file
42+modpost_link()
43+{
44+ ${LD} ${LDFLAGS} -r -o ${1} ${KBUILD_VMLINUX_INIT} \
45+ --start-group ${KBUILD_VMLINUX_MAIN} --end-group
46+}
47+
48+# Link of vmlinux
49+# ${1} - optional extra .o files
50+# ${2} - output file
51+vmlinux_link()
52+{
53+ local lds="${objtree}/${KBUILD_LDS}"
54+
55+ if [ "${SRCARCH}" != "um" ]; then
56+ ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
57+ -T ${lds} ${KBUILD_VMLINUX_INIT} \
58+ --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}
59+ else
60+ ${CC} ${CFLAGS_vmlinux} -o ${2} \
61+ -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \
62+ -Wl,--start-group \
63+ ${KBUILD_VMLINUX_MAIN} \
64+ -Wl,--end-group \
65+ -lutil ${1}
66+ rm -f linux
67+ fi
68+}
69+
70+
71+# Create ${2} .o file with all symbols from the ${1} object file
72+kallsyms()
73+{
74+ info KSYM ${2}
75+ local kallsymopt;
76+
77+ if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
78+ kallsymopt=--all-symbols
79+ fi
80+
81+ local aflags="${KBUILD_AFLAGS} ${NOSTDINC_FLAGS} \
82+ ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
83+
84+ ${NM} -n ${1} | \
85+ scripts/kallsyms ${kallsymopt} | \
86+ ${CC} ${aflags} -c -o ${2} -x assembler-with-cpp -
87+}
88+
89+# Create map file with all symbols from ${1}
90+# See mksymap for additional details
91+mksysmap()
92+{
93+ ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
94+}
95+
96+# Delete output files in case of error
97+trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM ERR
98+cleanup()
99+{
100+ rm -f .old_version
101+ rm -f .tmp_System.map
102+ rm -f .tmp_kallsyms*
103+ rm -f .tmp_version
104+ rm -f .tmp_vmlinux*
105+ rm -f System.map
106+ rm -f vmlinux
107+ rm -f vmlinux.o
108+}
109+
110+#
111+#
112+# Use "make V=1" to debug this script
113+case "${KBUILD_VERBOSE}" in
114+*1*)
115+ set -x
116+ ;;
117+esac
118+
119+if [ "$1" = "clean" ]; then
120+ cleanup
121+ exit 0
122+fi
123+
124+# We need access to CONFIG_ symbols
125+. ./.config
126+
127+#link vmlinux.o
128+info LD vmlinux.o
129+modpost_link vmlinux.o
130+
131+# modpost vmlinux.o to check for section mismatches
132+${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
133+
134+# Update version
135+info GEN .version
136+if [ ! -r .version ]; then
137+ rm -f .version;
138+ echo 1 >.version;
139+else
140+ mv .version .old_version;
141+ expr 0$(cat .old_version) + 1 >.version;
142+fi;
143+
144+# final build of init/
145+${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
146+
147+kallsymso=""
148+kallsyms_vmlinux=""
149+if [ -n "${CONFIG_KALLSYMS}" ]; then
150+
151+ # kallsyms support
152+ # Generate section listing all symbols and add it into vmlinux
153+ # It's a three step process:
154+ # 1) Link .tmp_vmlinux1 so it has all symbols and sections,
155+ # but __kallsyms is empty.
156+ # Running kallsyms on that gives us .tmp_kallsyms1.o with
157+ # the right size
158+ # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of
159+ # the right size, but due to the added section, some
160+ # addresses have shifted.
161+ # From here, we generate a correct .tmp_kallsyms2.o
162+ # 2a) We may use an extra pass as this has been necessary to
163+ # woraround some alignment related bugs.
164+ # KALLSYMS_EXTRA_PASS=1 is used to trigger this.
165+ # 3) The correct ${kallsymso} is linked into the final vmlinux.
166+ #
167+ # a) Verify that the System.map from vmlinux matches the map from
168+ # ${kallsymso}.
169+
170+ kallsymso=.tmp_kallsyms2.o
171+ kallsyms_vmlinux=.tmp_vmlinux2
172+
173+ # step 1
174+ vmlinux_link "" .tmp_vmlinux1
175+ kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
176+
177+ # step 2
178+ vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
179+ kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
180+
181+ # step 2a
182+ if [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
183+ kallsymso=.tmp_kallsyms3.o
184+ kallsyms_vmlinux=.tmp_vmlinux3
185+
186+ vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
187+
188+ kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
189+ fi
190+fi
191+
192+info LD vmlinux
193+vmlinux_link "${kallsymso}" vmlinux
194+
195+info SYSMAP System.map
196+mksysmap vmlinux System.map
197+
198+# step a (see comment above)
199+if [ -n "${CONFIG_KALLSYMS}" ]; then
200+ mksysmap ${kallsyms_vmlinux} .tmp_System.map
201+
202+ if ! cmp -s System.map .tmp_System.map; then
203+ echo Inconsistent kallsyms data
204+ echo echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
205+ cleanup
206+ exit 1
207+ fi
208+fi
209+
210+# We made a new kernel - delete old version file
211+rm -f .old_version