#!/bin/sh # # link vmlinux # # vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and # $(KBUILD_VMLINUX_MAIN). Most are built-in.o files from top-level directories # in the kernel tree, others are specified in arch/$(ARCH)/Makefile. # Ordering when linking is important, and $(KBUILD_VMLINUX_INIT) must be first. # # vmlinux # ^ # | # +-< $(KBUILD_VMLINUX_INIT) # | +--< init/version.o + more # | # +--< $(KBUILD_VMLINUX_MAIN) # | +--< drivers/built-in.o mm/built-in.o + more # | # +-< ${kallsymso} (see description in KALLSYMS section) # # vmlinux version (uname -v) cannot be updated during normal # descending-into-subdirs phase since we do not yet know if we need to # update vmlinux. # Therefore this step is delayed until just before final link of vmlinux. # # System.map is generated to document addresses of all kernel symbols # Error out on error set -e # Nice output in kbuild format # Will be supressed by "make -s" proc info { if test $(quiet) != "silent_" { printf " %-7s %s\n" $(1) $(2) } } # Link of vmlinux.o used for section mismatch analysis # ${1} output file proc modpost_link { $(LD) $(LDFLAGS) -r -o $(1) $(KBUILD_VMLINUX_INIT) \ --start-group $(KBUILD_VMLINUX_MAIN) --end-group } # Link of vmlinux # ${1} - optional extra .o files # ${2} - output file proc vmlinux_link { var lds = ""$(objtree)/$(KBUILD_LDS)"" if test $(SRCARCH) != "um" { $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $(2) \ -T $(lds) $(KBUILD_VMLINUX_INIT) \ --start-group $(KBUILD_VMLINUX_MAIN) --end-group $(1) } else { $(CC) $(CFLAGS_vmlinux) -o $(2) \ -Wl,-T,$(lds) $(KBUILD_VMLINUX_INIT) \ -Wl,--start-group \ $(KBUILD_VMLINUX_MAIN) \ -Wl,--end-group \ -lutil -lrt -lpthread $(1) rm -f linux } } # Create ${2} .o file with all symbols from the ${1} object file proc kallsyms { info KSYM $(2) var kallsymopt = ''; if test -n $(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX) { set kallsymopt = ""$(kallsymopt) --symbol-prefix=_"" } if test -n $(CONFIG_KALLSYMS_ALL) { set kallsymopt = ""$(kallsymopt) --all-symbols"" } if test -n $(CONFIG_KALLSYMS_ABSOLUTE_PERCPU) { set kallsymopt = ""$(kallsymopt) --absolute-percpu"" } if test -n $(CONFIG_KALLSYMS_BASE_RELATIVE) { set kallsymopt = ""$(kallsymopt) --base-relative"" } var aflags = ""$(KBUILD_AFLAGS) $(KBUILD_AFLAGS_KERNEL) \ $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CPPFLAGS)"" var afile = ""$[basename $(2) .o].S"" $(NM) -n $(1) | scripts/kallsyms $(kallsymopt) > $(afile) $(CC) $(aflags) -c -o $(2) $(afile) } # Create map file with all symbols from ${1} # See mksymap for additional details proc mksysmap { $(CONFIG_SHELL) "$(srctree)/scripts/mksysmap" $(1) $(2) } proc sortextable { $(objtree)/scripts/sortextable $(1) } # Delete output files in case of error proc cleanup { rm -f .old_version rm -f .tmp_System.map rm -f .tmp_kallsyms* rm -f .tmp_version rm -f .tmp_vmlinux* rm -f System.map rm -f vmlinux rm -f vmlinux.o } proc on_exit { if test $Status -ne 0 { cleanup } } trap on_exit EXIT proc on_signals { exit 1 } trap on_signals HUP INT QUIT TERM # # # Use "make V=1" to debug this script match $(KBUILD_VERBOSE) { with *1* set -x } if test $1 = "clean" { cleanup exit 0 } # We need access to CONFIG_ symbols match $(KCONFIG_CONFIG) { with */* source "${KCONFIG_CONFIG}" with * # Force using a file from the current directory source "./${KCONFIG_CONFIG}" } #link vmlinux.o info LD vmlinux.o modpost_link vmlinux.o # modpost vmlinux.o to check for section mismatches $(MAKE) -f "$(srctree)/scripts/Makefile.modpost" vmlinux.o # Update version info GEN .version if test ! -r .version { rm -f .version; echo 1 >.version; } else { mv .version .old_version; expr 0$[cat .old_version] + 1 >.version; }; # final build of init/ $(MAKE) -f "$(srctree)/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="$(GCC_PLUGINS_CFLAGS)" setglobal kallsymso = ''"" setglobal kallsyms_vmlinux = ''"" if test -n $(CONFIG_KALLSYMS) { # kallsyms support # Generate section listing all symbols and add it into vmlinux # It's a three step process: # 1) Link .tmp_vmlinux1 so it has all symbols and sections, # but __kallsyms is empty. # Running kallsyms on that gives us .tmp_kallsyms1.o with # the right size # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of # the right size, but due to the added section, some # addresses have shifted. # From here, we generate a correct .tmp_kallsyms2.o # 2a) We may use an extra pass as this has been necessary to # woraround some alignment related bugs. # KALLSYMS_EXTRA_PASS=1 is used to trigger this. # 3) The correct ${kallsymso} is linked into the final vmlinux. # # a) Verify that the System.map from vmlinux matches the map from # ${kallsymso}. setglobal kallsymso = '.tmp_kallsyms2.o' setglobal kallsyms_vmlinux = '.tmp_vmlinux2' # step 1 vmlinux_link "" .tmp_vmlinux1 kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o # step 2 vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o # step 2a if test -n $(KALLSYMS_EXTRA_PASS) { setglobal kallsymso = '.tmp_kallsyms3.o' setglobal kallsyms_vmlinux = '.tmp_vmlinux3' vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o } } info LD vmlinux vmlinux_link $(kallsymso) vmlinux if test -n $(CONFIG_BUILDTIME_EXTABLE_SORT) { info SORTEX vmlinux sortextable vmlinux } info SYSMAP System.map mksysmap vmlinux System.map # step a (see comment above) if test -n $(CONFIG_KALLSYMS) { mksysmap $(kallsyms_vmlinux) .tmp_System.map if ! cmp -s System.map .tmp_System.map { echo >&2 Inconsistent kallsyms data> !2 Inconsistent kallsyms data echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround> !2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround exit 1 } } # We made a new kernel - delete old version file rm -f .old_version